1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
2 ; RUN: opt -S -verify -iroutliner -ir-outlining-no-cost < %s | FileCheck %s
4 ; This test ensures that an extra output is not added when there is a bitcast
5 ; that is relocated to outside of the extraction due to a starting lifetime
6 ; instruction outside of the extracted region.
8 ; Additionally, we check that the newly added bitcast instruction is excluded in
11 declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
12 declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
14 define void @outline_bitcast_base() {
16 %a = alloca i32, align 4
17 %b = alloca i32, align 4
18 %c = alloca i32, align 4
19 %d = alloca i32, align 4
20 store i32 2, i32* %a, align 4
21 store i32 3, i32* %b, align 4
22 store i32 4, i32* %c, align 4
23 %X = bitcast i32* %d to i8*
24 %al = load i32, i32* %a
25 %bl = load i32, i32* %b
26 %cl = load i32, i32* %c
30 define void @outline_bitcast_removed() {
32 %a = alloca i32, align 4
33 %b = alloca i32, align 4
34 %c = alloca i32, align 4
35 %d = alloca i32, align 4
36 store i32 2, i32* %a, align 4
37 store i32 3, i32* %b, align 4
38 store i32 4, i32* %c, align 4
39 %X = bitcast i32* %d to i8*
40 %al = load i32, i32* %a
41 %bl = load i32, i32* %b
42 %cl = load i32, i32* %c
43 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %X)
44 %am = load i32, i32* %b
45 %bm = load i32, i32* %a
46 %cm = load i32, i32* %c
47 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %X)
51 ; The first bitcast is moved down to lifetime start, and, since the original
52 ; endpoint does not match the new endpoint, we cannot extract and outline the
53 ; second bitcast and set of adds. Outlining only occurs in this case due to
54 ; the lack of a cost model, as denoted by the debug command line argument.
56 define void @outline_bitcast_base2(i32 %a, i32 %b, i32 %c) {
58 %d = alloca i32, align 4
59 %X = bitcast i32* %d to i8*
63 %buffer = mul i32 %a, %b
64 %Y = bitcast i32* %d to i8*
68 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %X)
69 call void @llvm.lifetime.end.p0i8(i64 -1, i8* %X)
73 ; CHECK-LABEL: @outline_bitcast_base(
75 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
76 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
77 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
78 ; CHECK-NEXT: [[D:%.*]] = alloca i32, align 4
79 ; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[C]], i32* [[D]])
80 ; CHECK-NEXT: ret void
83 ; CHECK-LABEL: @outline_bitcast_removed(
85 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
86 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
87 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
88 ; CHECK-NEXT: [[D:%.*]] = alloca i32, align 4
89 ; CHECK-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[C]], i32* [[D]])
90 ; CHECK-NEXT: [[LT_CAST1:%.*]] = bitcast i32* [[D]] to i8*
91 ; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST1]])
92 ; CHECK-NEXT: [[AM:%.*]] = load i32, i32* [[B]], align 4
93 ; CHECK-NEXT: [[BM:%.*]] = load i32, i32* [[A]], align 4
94 ; CHECK-NEXT: [[CM:%.*]] = load i32, i32* [[C]], align 4
95 ; CHECK-NEXT: [[LT_CAST:%.*]] = bitcast i32* [[D]] to i8*
96 ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[LT_CAST]])
97 ; CHECK-NEXT: ret void
100 ; CHECK-LABEL: @outline_bitcast_base2(
102 ; CHECK-NEXT: [[D:%.*]] = alloca i32, align 4
103 ; CHECK-NEXT: [[X:%.*]] = bitcast i32* [[D]] to i8*
104 ; CHECK-NEXT: [[AL:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
105 ; CHECK-NEXT: [[BL:%.*]] = add i32 [[B]], [[A]]
106 ; CHECK-NEXT: [[CL:%.*]] = add i32 [[B]], [[C:%.*]]
107 ; CHECK-NEXT: [[BUFFER:%.*]] = mul i32 [[A]], [[B]]
108 ; CHECK-NEXT: [[Y:%.*]] = bitcast i32* [[D]] to i8*
109 ; CHECK-NEXT: [[AM:%.*]] = add i32 [[A]], [[B]]
110 ; CHECK-NEXT: [[BM:%.*]] = add i32 [[B]], [[A]]
111 ; CHECK-NEXT: [[CM:%.*]] = add i32 [[B]], [[C]]
112 ; CHECK-NEXT: [[LT_CAST1:%.*]] = bitcast i32* [[D]] to i8*
113 ; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST1]])
114 ; CHECK-NEXT: [[LT_CAST:%.*]] = bitcast i32* [[D]] to i8*
115 ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[LT_CAST]])
116 ; CHECK-NEXT: ret void
119 ; CHECK-LABEL: @outlined_ir_func_0(
120 ; CHECK-NEXT: newFuncRoot:
121 ; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
122 ; CHECK: entry_to_outline:
123 ; CHECK-NEXT: store i32 2, i32* [[TMP0:%.*]], align 4
124 ; CHECK-NEXT: store i32 3, i32* [[TMP1:%.*]], align 4
125 ; CHECK-NEXT: store i32 4, i32* [[TMP2:%.*]], align 4
126 ; CHECK-NEXT: [[X:%.*]] = bitcast i32* [[TMP3:%.*]] to i8*
127 ; CHECK-NEXT: [[AL:%.*]] = load i32, i32* [[TMP0]], align 4
128 ; CHECK-NEXT: [[BL:%.*]] = load i32, i32* [[TMP1]], align 4
129 ; CHECK-NEXT: [[CL:%.*]] = load i32, i32* [[TMP2]], align 4
130 ; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
131 ; CHECK: entry_after_outline.exitStub:
132 ; CHECK-NEXT: ret void