1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
4 ; This test checks that commutative instructions where the operands are
5 ; swapped are outlined as the same function.
7 ; It also checks that non-commutative instructions outlined as different
8 ; functions when the operands are swapped;
10 ; These are identical functions, except that in the flipped functions,
11 ; the operands in the adds are commuted. However, since add instructions
12 ; are commutative, we should still outline from all four as the same
15 define void @outline_from_add1() {
16 ; CHECK-LABEL: @outline_from_add1(
18 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
19 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
20 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
21 ; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
22 ; CHECK-NEXT: ret void
25 %a = alloca i32, align 4
26 %b = alloca i32, align 4
27 %c = alloca i32, align 4
28 store i32 2, ptr %a, align 4
29 store i32 3, ptr %b, align 4
30 store i32 4, ptr %c, align 4
31 %al = load i32, ptr %a
32 %bl = load i32, ptr %b
33 %cl = load i32, ptr %c
40 define void @outline_from_add2() {
41 ; CHECK-LABEL: @outline_from_add2(
43 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
44 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
45 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
46 ; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
47 ; CHECK-NEXT: ret void
50 %a = alloca i32, align 4
51 %b = alloca i32, align 4
52 %c = alloca i32, align 4
53 store i32 2, ptr %a, align 4
54 store i32 3, ptr %b, align 4
55 store i32 4, ptr %c, align 4
56 %al = load i32, ptr %a
57 %bl = load i32, ptr %b
58 %cl = load i32, ptr %c
65 define void @outline_from_flipped_add3() {
66 ; CHECK-LABEL: @outline_from_flipped_add3(
68 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
69 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
70 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
71 ; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
72 ; CHECK-NEXT: ret void
75 %a = alloca i32, align 4
76 %b = alloca i32, align 4
77 %c = alloca i32, align 4
78 store i32 2, ptr %a, align 4
79 store i32 3, ptr %b, align 4
80 store i32 4, ptr %c, align 4
81 %al = load i32, ptr %a
82 %bl = load i32, ptr %b
83 %cl = load i32, ptr %c
90 define void @outline_from_flipped_add4() {
91 ; CHECK-LABEL: @outline_from_flipped_add4(
93 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
94 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
95 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
96 ; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
97 ; CHECK-NEXT: ret void
100 %a = alloca i32, align 4
101 %b = alloca i32, align 4
102 %c = alloca i32, align 4
103 store i32 2, ptr %a, align 4
104 store i32 3, ptr %b, align 4
105 store i32 4, ptr %c, align 4
106 %al = load i32, ptr %a
107 %bl = load i32, ptr %b
108 %cl = load i32, ptr %c
109 %0 = add i32 %bl, %al
110 %1 = add i32 %cl, %al
111 %2 = add i32 %cl, %bl
115 ; These are identical functions, except that in the flipped functions,
116 ; the operands in the subtractions are commuted. Since subtraction
117 ; instructions are not commutative, we should outline the first two functions
118 ; differently than the second two functions.
120 define void @outline_from_sub1() {
121 ; CHECK-LABEL: @outline_from_sub1(
123 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
124 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
125 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
126 ; CHECK-NEXT: call void @outlined_ir_func_2(ptr [[A]], ptr [[B]], ptr [[C]])
127 ; CHECK-NEXT: ret void
130 %a = alloca i32, align 4
131 %b = alloca i32, align 4
132 %c = alloca i32, align 4
133 store i32 2, ptr %a, align 4
134 store i32 3, ptr %b, align 4
135 store i32 4, ptr %c, align 4
136 %al = load i32, ptr %a
137 %bl = load i32, ptr %b
138 %cl = load i32, ptr %c
139 %0 = sub i32 %al, %bl
140 %1 = sub i32 %al, %cl
141 %2 = sub i32 %bl, %cl
145 define void @outline_from_sub2() {
146 ; CHECK-LABEL: @outline_from_sub2(
148 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
149 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
150 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
151 ; CHECK-NEXT: call void @outlined_ir_func_2(ptr [[A]], ptr [[B]], ptr [[C]])
152 ; CHECK-NEXT: ret void
155 %a = alloca i32, align 4
156 %b = alloca i32, align 4
157 %c = alloca i32, align 4
158 store i32 2, ptr %a, align 4
159 store i32 3, ptr %b, align 4
160 store i32 4, ptr %c, align 4
161 %al = load i32, ptr %a
162 %bl = load i32, ptr %b
163 %cl = load i32, ptr %c
164 %0 = sub i32 %al, %bl
165 %1 = sub i32 %al, %cl
166 %2 = sub i32 %bl, %cl
170 define void @dontoutline_from_flipped_sub3() {
171 ; CHECK-LABEL: @dontoutline_from_flipped_sub3(
173 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
174 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
175 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
176 ; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[C]])
177 ; CHECK-NEXT: ret void
180 %a = alloca i32, align 4
181 %b = alloca i32, align 4
182 %c = alloca i32, align 4
183 store i32 2, ptr %a, align 4
184 store i32 3, ptr %b, align 4
185 store i32 4, ptr %c, align 4
186 %al = load i32, ptr %a
187 %bl = load i32, ptr %b
188 %cl = load i32, ptr %c
189 %0 = sub i32 %bl, %al
190 %1 = sub i32 %cl, %al
191 %2 = sub i32 %cl, %bl
195 define void @dontoutline_from_flipped_sub4() {
196 ; CHECK-LABEL: @dontoutline_from_flipped_sub4(
198 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
199 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
200 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
201 ; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[C]])
202 ; CHECK-NEXT: ret void
205 %a = alloca i32, align 4
206 %b = alloca i32, align 4
207 %c = alloca i32, align 4
208 store i32 2, ptr %a, align 4
209 store i32 3, ptr %b, align 4
210 store i32 4, ptr %c, align 4
211 %al = load i32, ptr %a
212 %bl = load i32, ptr %b
213 %cl = load i32, ptr %c
214 %0 = sub i32 %bl, %al
215 %1 = sub i32 %cl, %al
216 %2 = sub i32 %cl, %bl
220 ; CHECK: define internal void @outlined_ir_func_0(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #0 {
221 ; CHECK: entry_to_outline:
222 ; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4
223 ; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4
224 ; CHECK-NEXT: store i32 4, ptr [[ARG2]], align 4
225 ; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[ARG0]], align 4
226 ; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[ARG1]], align 4
227 ; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[ARG2]], align 4
228 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[AL]], [[BL]]
229 ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[AL]], [[CL]]
230 ; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[BL]], [[CL]]
232 ; CHECK: define internal void @outlined_ir_func_1(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #0 {
233 ; CHECK: entry_to_outline:
234 ; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4
235 ; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4
236 ; CHECK-NEXT: store i32 4, ptr [[ARG2]], align 4
237 ; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[ARG0]], align 4
238 ; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[ARG1]], align 4
239 ; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[ARG2]], align 4
240 ; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[BL]], [[AL]]
241 ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[CL]], [[AL]]
242 ; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[CL]], [[BL]]
244 ; CHECK: define internal void @outlined_ir_func_2(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #0 {
245 ; CHECK: entry_to_outline:
246 ; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4
247 ; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4
248 ; CHECK-NEXT: store i32 4, ptr [[ARG2]], align 4
249 ; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[ARG0]], align 4
250 ; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[ARG1]], align 4
251 ; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[ARG2]], align 4
252 ; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[AL]], [[BL]]
253 ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[AL]], [[CL]]
254 ; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[BL]], [[CL]]