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 ; Here we have multiple exits, but different sources, and only one has an
5 ; output set. We check to make sure that we do not generated extra output
6 ; blocks or entries in the switch statement.
8 define void @outline_outputs1() #0 {
10 %output = alloca i32, align 4
11 %result = alloca i32, align 4
12 %output2 = alloca i32, align 4
13 %result2 = alloca i32, align 4
14 %a = alloca i32, align 4
15 %b = alloca i32, align 4
18 %a2 = alloca i32, align 4
19 %b2 = alloca i32, align 4
22 %a2val = load i32, i32* %a
23 %b2val = load i32, i32* %b
24 %add2 = add i32 2, %a2val
25 %mul2 = mul i32 2, %b2val
28 %aval = load i32, i32* %a
29 %bval = load i32, i32* %b
30 %add = add i32 2, %aval
31 %mul = mul i32 2, %bval
34 store i32 %add, i32* %output, align 4
35 store i32 %mul, i32* %result, align 4
38 store i32 %add2, i32* %output, align 4
39 store i32 %mul2, i32* %result, align 4
47 define void @outline_outputs2() #0 {
49 %output = alloca i32, align 4
50 %result = alloca i32, align 4
51 %output2 = alloca i32, align 4
52 %result2 = alloca i32, align 4
53 %a = alloca i32, align 4
54 %b = alloca i32, align 4
57 %a2 = alloca i32, align 4
58 %b2 = alloca i32, align 4
61 %a2val = load i32, i32* %a
62 %b2val = load i32, i32* %b
63 %add2 = add i32 2, %a2val
64 %mul2 = mul i32 2, %b2val
67 %aval = load i32, i32* %a
68 %bval = load i32, i32* %b
69 %add = add i32 2, %aval
70 %mul = mul i32 2, %bval
73 store i32 %add, i32* %output, align 4
74 store i32 %mul, i32* %result, align 4
77 store i32 %add2, i32* %output, align 4
78 store i32 %mul2, i32* %result, align 4
81 %diff = sub i32 %a2val, %b2val
84 %quot = udiv i32 %add, %mul
87 ; CHECK-LABEL: @outline_outputs1(
89 ; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
90 ; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
91 ; CHECK-NEXT: [[OUTPUT2:%.*]] = alloca i32, align 4
92 ; CHECK-NEXT: [[RESULT2:%.*]] = alloca i32, align 4
93 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
94 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
95 ; CHECK-NEXT: br label [[BLOCK_2:%.*]]
97 ; CHECK-NEXT: [[A2:%.*]] = alloca i32, align 4
98 ; CHECK-NEXT: [[B2:%.*]] = alloca i32, align 4
99 ; CHECK-NEXT: br label [[BLOCK_2]]
101 ; CHECK-NEXT: [[TMP0:%.*]] = call i1 @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[OUTPUT]], i32* [[RESULT]], i32* null, i32* null, i32* null, i32* null, i32 -1)
102 ; CHECK-NEXT: br i1 [[TMP0]], label [[BLOCK_6:%.*]], label [[BLOCK_7:%.*]]
104 ; CHECK-NEXT: ret void
106 ; CHECK-NEXT: ret void
109 ; CHECK-LABEL: @outline_outputs2(
111 ; CHECK-NEXT: [[MUL_LOC:%.*]] = alloca i32, align 4
112 ; CHECK-NEXT: [[ADD_LOC:%.*]] = alloca i32, align 4
113 ; CHECK-NEXT: [[B2VAL_LOC:%.*]] = alloca i32, align 4
114 ; CHECK-NEXT: [[A2VAL_LOC:%.*]] = alloca i32, align 4
115 ; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
116 ; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
117 ; CHECK-NEXT: [[OUTPUT2:%.*]] = alloca i32, align 4
118 ; CHECK-NEXT: [[RESULT2:%.*]] = alloca i32, align 4
119 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
120 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
121 ; CHECK-NEXT: br label [[BLOCK_2:%.*]]
123 ; CHECK-NEXT: [[A2:%.*]] = alloca i32, align 4
124 ; CHECK-NEXT: [[B2:%.*]] = alloca i32, align 4
125 ; CHECK-NEXT: br label [[BLOCK_2]]
127 ; CHECK-NEXT: [[LT_CAST:%.*]] = bitcast i32* [[A2VAL_LOC]] to i8*
128 ; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST]])
129 ; CHECK-NEXT: [[LT_CAST1:%.*]] = bitcast i32* [[B2VAL_LOC]] to i8*
130 ; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST1]])
131 ; CHECK-NEXT: [[LT_CAST2:%.*]] = bitcast i32* [[ADD_LOC]] to i8*
132 ; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST2]])
133 ; CHECK-NEXT: [[LT_CAST3:%.*]] = bitcast i32* [[MUL_LOC]] to i8*
134 ; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST3]])
135 ; CHECK-NEXT: [[TMP0:%.*]] = call i1 @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[OUTPUT]], i32* [[RESULT]], i32* [[A2VAL_LOC]], i32* [[B2VAL_LOC]], i32* [[ADD_LOC]], i32* [[MUL_LOC]], i32 0)
136 ; CHECK-NEXT: [[A2VAL_RELOAD:%.*]] = load i32, i32* [[A2VAL_LOC]], align 4
137 ; CHECK-NEXT: [[B2VAL_RELOAD:%.*]] = load i32, i32* [[B2VAL_LOC]], align 4
138 ; CHECK-NEXT: [[ADD_RELOAD:%.*]] = load i32, i32* [[ADD_LOC]], align 4
139 ; CHECK-NEXT: [[MUL_RELOAD:%.*]] = load i32, i32* [[MUL_LOC]], align 4
140 ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[LT_CAST]])
141 ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[LT_CAST1]])
142 ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[LT_CAST2]])
143 ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[LT_CAST3]])
144 ; CHECK-NEXT: br i1 [[TMP0]], label [[BLOCK_7:%.*]], label [[BLOCK_6:%.*]]
146 ; CHECK-NEXT: [[DIFF:%.*]] = sub i32 [[A2VAL_RELOAD]], [[B2VAL_RELOAD]]
147 ; CHECK-NEXT: ret void
149 ; CHECK-NEXT: [[QUOT:%.*]] = udiv i32 [[ADD_RELOAD]], [[MUL_RELOAD]]
150 ; CHECK-NEXT: ret void
153 ; CHECK: define internal i1 @outlined_ir_func_0(
154 ; CHECK-NEXT: newFuncRoot:
155 ; CHECK-NEXT: br label [[BLOCK_2_TO_OUTLINE:%.*]]
156 ; CHECK: block_2_to_outline:
157 ; CHECK-NEXT: [[A2VAL:%.*]] = load i32, i32* [[TMP0:%.*]], align 4
158 ; CHECK-NEXT: [[B2VAL:%.*]] = load i32, i32* [[TMP1:%.*]], align 4
159 ; CHECK-NEXT: [[ADD2:%.*]] = add i32 2, [[A2VAL]]
160 ; CHECK-NEXT: [[MUL2:%.*]] = mul i32 2, [[B2VAL]]
161 ; CHECK-NEXT: br label [[BLOCK_5:%.*]]
163 ; CHECK-NEXT: [[AVAL:%.*]] = load i32, i32* [[TMP0]], align 4
164 ; CHECK-NEXT: [[BVAL:%.*]] = load i32, i32* [[TMP1]], align 4
165 ; CHECK-NEXT: [[ADD:%.*]] = add i32 2, [[AVAL]]
166 ; CHECK-NEXT: [[MUL:%.*]] = mul i32 2, [[BVAL]]
167 ; CHECK-NEXT: br label [[BLOCK_4:%.*]]
169 ; CHECK-NEXT: store i32 [[ADD]], i32* [[TMP2:%.*]], align 4
170 ; CHECK-NEXT: store i32 [[MUL]], i32* [[TMP3:%.*]], align 4
171 ; CHECK-NEXT: br label [[BLOCK_6_EXITSTUB:%.*]]
173 ; CHECK-NEXT: store i32 [[ADD2]], i32* [[TMP2]], align 4
174 ; CHECK-NEXT: store i32 [[MUL2]], i32* [[TMP3]], align 4
175 ; CHECK-NEXT: br label [[BLOCK_7_EXITSTUB:%.*]]
176 ; CHECK: block_6.exitStub:
177 ; CHECK-NEXT: switch i32 [[TMP8:%.*]], label [[FINAL_BLOCK_1:%.*]] [
178 ; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_1_1:%.*]]
180 ; CHECK: block_7.exitStub:
181 ; CHECK-NEXT: switch i32 [[TMP8]], label [[FINAL_BLOCK_0:%.*]] [
182 ; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_1_0:%.*]]
184 ; CHECK: output_block_1_0:
185 ; CHECK-NEXT: store i32 [[A2VAL]], i32* [[TMP4:%.*]], align 4
186 ; CHECK-NEXT: store i32 [[B2VAL]], i32* [[TMP5:%.*]], align 4
187 ; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
188 ; CHECK: output_block_1_1:
189 ; CHECK-NEXT: store i32 [[ADD]], i32* [[TMP6:%.*]], align 4
190 ; CHECK-NEXT: store i32 [[MUL]], i32* [[TMP7:%.*]], align 4
191 ; CHECK-NEXT: br label [[FINAL_BLOCK_1]]
192 ; CHECK: final_block_0:
193 ; CHECK-NEXT: ret i1 false
194 ; CHECK: final_block_1:
195 ; CHECK-NEXT: ret i1 true