Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / IROutliner / outlining-commutative.ll
blob8862dc295d43517e21dece71282a4e774dc783e3
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
13 ; instruction.
15 define void @outline_from_add1() {
16 ; CHECK-LABEL: @outline_from_add1(
17 ; CHECK-NEXT:  entry:
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
24 entry:
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
34   %0 = add i32 %al, %bl
35   %1 = add i32 %al, %cl
36   %2 = add i32 %bl, %cl
37   ret void
40 define void @outline_from_add2() {
41 ; CHECK-LABEL: @outline_from_add2(
42 ; CHECK-NEXT:  entry:
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
49 entry:
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
59   %0 = add i32 %al, %bl
60   %1 = add i32 %al, %cl
61   %2 = add i32 %bl, %cl
62   ret void
65 define void @outline_from_flipped_add3() {
66 ; CHECK-LABEL: @outline_from_flipped_add3(
67 ; CHECK-NEXT:  entry:
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
74 entry:
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
84   %0 = add i32 %bl, %al
85   %1 = add i32 %cl, %al
86   %2 = add i32 %cl, %bl
87   ret void
90 define void @outline_from_flipped_add4() {
91 ; CHECK-LABEL: @outline_from_flipped_add4(
92 ; CHECK-NEXT:  entry:
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
99 entry:
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
112   ret void
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(
122 ; CHECK-NEXT:  entry:
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
129 entry:
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
142   ret void
145 define void @outline_from_sub2() {
146 ; CHECK-LABEL: @outline_from_sub2(
147 ; CHECK-NEXT:  entry:
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
154 entry:
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
167   ret void
170 define void @dontoutline_from_flipped_sub3() {
171 ; CHECK-LABEL: @dontoutline_from_flipped_sub3(
172 ; CHECK-NEXT:  entry:
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
179 entry:
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
192   ret void
195 define void @dontoutline_from_flipped_sub4() {
196 ; CHECK-LABEL: @dontoutline_from_flipped_sub4(
197 ; CHECK-NEXT:  entry:
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
204 entry:
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
217   ret void
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]]