[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / EarlyCSE / phi.ll
blobe9c86ec5d37402abd44d1e37c08d5a4d86a8ccf5
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -early-cse -earlycse-debug-hash -S < %s | FileCheck %s
3 ; RUN: opt -basic-aa -early-cse-memssa -S < %s | FileCheck %s
5 ; Most basic case, fully identical PHI nodes
6 define void @test0(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
7 ; CHECK-LABEL: @test0(
8 ; CHECK-NEXT:  entry:
9 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
10 ; CHECK:       b0:
11 ; CHECK-NEXT:    br label [[END:%.*]]
12 ; CHECK:       b1:
13 ; CHECK-NEXT:    br label [[END]]
14 ; CHECK:       end:
15 ; CHECK-NEXT:    [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
16 ; CHECK-NEXT:    [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V1]], [[B1]] ]
17 ; CHECK-NEXT:    store i32 [[I0]], i32* [[D0:%.*]], align 4
18 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D1:%.*]], align 4
19 ; CHECK-NEXT:    ret void
21 entry:
22   br i1 %c, label %b0, label %b1
24 b0:
25   br label %end
27 b1:
28   br label %end
30 end:
31   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
32   %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
33   store i32 %i0, i32* %d0
34   store i32 %i1, i32* %d1
35   ret void
38 ; Fully identical PHI nodes, but order of operands differs
39 define void @test1(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
40 ; CHECK-LABEL: @test1(
41 ; CHECK-NEXT:  entry:
42 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
43 ; CHECK:       b0:
44 ; CHECK-NEXT:    br label [[END:%.*]]
45 ; CHECK:       b1:
46 ; CHECK-NEXT:    br label [[END]]
47 ; CHECK:       end:
48 ; CHECK-NEXT:    [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
49 ; CHECK-NEXT:    [[I1:%.*]] = phi i32 [ [[V1]], [[B1]] ], [ [[V0]], [[B0]] ]
50 ; CHECK-NEXT:    store i32 [[I0]], i32* [[D0:%.*]], align 4
51 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D1:%.*]], align 4
52 ; CHECK-NEXT:    ret void
54 entry:
55   br i1 %c, label %b0, label %b1
57 b0:
58   br label %end
60 b1:
61   br label %end
63 end:
64   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
65   %i1 = phi i32 [ %v1, %b1 ], [ %v0, %b0 ]
66   store i32 %i0, i32* %d0
67   store i32 %i1, i32* %d1
68   ret void
71 ; Different incoming values in second PHI
72 define void @negative_test2(i32 %v0, i32 %v1, i32 %v2, i1 %c, i32* %d0, i32* %d1) {
73 ; CHECK-LABEL: @negative_test2(
74 ; CHECK-NEXT:  entry:
75 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
76 ; CHECK:       b0:
77 ; CHECK-NEXT:    br label [[END:%.*]]
78 ; CHECK:       b1:
79 ; CHECK-NEXT:    br label [[END]]
80 ; CHECK:       end:
81 ; CHECK-NEXT:    [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
82 ; CHECK-NEXT:    [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V2:%.*]], [[B1]] ]
83 ; CHECK-NEXT:    store i32 [[I0]], i32* [[D0:%.*]], align 4
84 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D1:%.*]], align 4
85 ; CHECK-NEXT:    ret void
87 entry:
88   br i1 %c, label %b0, label %b1
90 b0:
91   br label %end
93 b1:
94   br label %end
96 end:
97   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
98   %i1 = phi i32 [ %v0, %b0 ], [ %v2, %b1 ] ; from %b0 takes %v2 instead of %v1
99   store i32 %i0, i32* %d0
100   store i32 %i1, i32* %d1
101   ret void
103 define void @negative_test3(i32 %v0, i32 %v1, i32 %v2, i1 %c, i32* %d0, i32* %d1) {
104 ; CHECK-LABEL: @negative_test3(
105 ; CHECK-NEXT:  entry:
106 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
107 ; CHECK:       b0:
108 ; CHECK-NEXT:    br label [[END:%.*]]
109 ; CHECK:       b1:
110 ; CHECK-NEXT:    br label [[END]]
111 ; CHECK:       end:
112 ; CHECK-NEXT:    [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
113 ; CHECK-NEXT:    [[I1:%.*]] = phi i32 [ [[V2:%.*]], [[B1]] ], [ [[V0]], [[B0]] ]
114 ; CHECK-NEXT:    store i32 [[I0]], i32* [[D0:%.*]], align 4
115 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D1:%.*]], align 4
116 ; CHECK-NEXT:    ret void
118 entry:
119   br i1 %c, label %b0, label %b1
122   br label %end
125   br label %end
127 end:
128   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
129   %i1 = phi i32 [ %v2, %b1 ], [ %v0, %b0 ] ; from %b0 takes %v2 instead of %v1
130   store i32 %i0, i32* %d0
131   store i32 %i1, i32* %d1
132   ret void
134 define void @negative_test4(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
135 ; CHECK-LABEL: @negative_test4(
136 ; CHECK-NEXT:  entry:
137 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
138 ; CHECK:       b0:
139 ; CHECK-NEXT:    br label [[END:%.*]]
140 ; CHECK:       b1:
141 ; CHECK-NEXT:    br label [[END]]
142 ; CHECK:       end:
143 ; CHECK-NEXT:    [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
144 ; CHECK-NEXT:    [[I1:%.*]] = phi i32 [ [[V1]], [[B1]] ], [ [[V0]], [[B0]] ]
145 ; CHECK-NEXT:    store i32 [[I0]], i32* [[D0:%.*]], align 4
146 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D1:%.*]], align 4
147 ; CHECK-NEXT:    ret void
149 entry:
150   br i1 %c, label %b0, label %b1
153   br label %end
156   br label %end
158 end:
159   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
160   %i1 = phi i32 [ %v1, %b1 ], [ %v0, %b0 ] ; incoming values are swapped
161   store i32 %i0, i32* %d0
162   store i32 %i1, i32* %d1
163   ret void
166 ; Both PHI's are identical, but the first one has no uses, so ignore it.
167 define void @test5(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
168 ; CHECK-LABEL: @test5(
169 ; CHECK-NEXT:  entry:
170 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
171 ; CHECK:       b0:
172 ; CHECK-NEXT:    br label [[END:%.*]]
173 ; CHECK:       b1:
174 ; CHECK-NEXT:    br label [[END]]
175 ; CHECK:       end:
176 ; CHECK-NEXT:    [[I1:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
177 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D1:%.*]], align 4
178 ; CHECK-NEXT:    ret void
180 entry:
181   br i1 %c, label %b0, label %b1
184   br label %end
187   br label %end
189 end:
190   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] ; unused
191   %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
192   store i32 %i1, i32* %d1
193   ret void
195 ; Second PHI has no uses
196 define void @test6(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
197 ; CHECK-LABEL: @test6(
198 ; CHECK-NEXT:  entry:
199 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
200 ; CHECK:       b0:
201 ; CHECK-NEXT:    br label [[END:%.*]]
202 ; CHECK:       b1:
203 ; CHECK-NEXT:    br label [[END]]
204 ; CHECK:       end:
205 ; CHECK-NEXT:    [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
206 ; CHECK-NEXT:    store i32 [[I0]], i32* [[D0:%.*]], align 4
207 ; CHECK-NEXT:    ret void
209 entry:
210   br i1 %c, label %b0, label %b1
213   br label %end
216   br label %end
218 end:
219   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
220   %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] ; unused
221   store i32 %i0, i32* %d0
222   ret void
225 ; Non-matching PHI node should be ignored without terminating CSE.
226 define void @test7(i32 %v0, i32 %v1, i16 %v2, i16 %v3, i1 %c, i32* %d0, i32* %d1, i16* %d2) {
227 ; CHECK-LABEL: @test7(
228 ; CHECK-NEXT:  entry:
229 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
230 ; CHECK:       b0:
231 ; CHECK-NEXT:    br label [[END:%.*]]
232 ; CHECK:       b1:
233 ; CHECK-NEXT:    br label [[END]]
234 ; CHECK:       end:
235 ; CHECK-NEXT:    [[IBAD:%.*]] = phi i16 [ [[V2:%.*]], [[B0]] ], [ [[V3:%.*]], [[B1]] ]
236 ; CHECK-NEXT:    [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
237 ; CHECK-NEXT:    [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V1]], [[B1]] ]
238 ; CHECK-NEXT:    store i32 [[I0]], i32* [[D0:%.*]], align 4
239 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D1:%.*]], align 4
240 ; CHECK-NEXT:    store i16 [[IBAD]], i16* [[D2:%.*]], align 2
241 ; CHECK-NEXT:    ret void
243 entry:
244   br i1 %c, label %b0, label %b1
247   br label %end
250   br label %end
252 end:
253   %iBAD = phi i16 [ %v2, %b0 ], [ %v3, %b1 ]
254   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
255   %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
256   store i32 %i0, i32* %d0
257   store i32 %i1, i32* %d1
258   store i16 %iBAD, i16* %d2
259   ret void
261 define void @test8(i32 %v0, i32 %v1, i16 %v2, i16 %v3, i1 %c, i32* %d0, i32* %d1, i16* %d2) {
262 ; CHECK-LABEL: @test8(
263 ; CHECK-NEXT:  entry:
264 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
265 ; CHECK:       b0:
266 ; CHECK-NEXT:    br label [[END:%.*]]
267 ; CHECK:       b1:
268 ; CHECK-NEXT:    br label [[END]]
269 ; CHECK:       end:
270 ; CHECK-NEXT:    [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
271 ; CHECK-NEXT:    [[IBAD:%.*]] = phi i16 [ [[V2:%.*]], [[B0]] ], [ [[V3:%.*]], [[B1]] ]
272 ; CHECK-NEXT:    [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V1]], [[B1]] ]
273 ; CHECK-NEXT:    store i32 [[I0]], i32* [[D0:%.*]], align 4
274 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D1:%.*]], align 4
275 ; CHECK-NEXT:    store i16 [[IBAD]], i16* [[D2:%.*]], align 2
276 ; CHECK-NEXT:    ret void
278 entry:
279   br i1 %c, label %b0, label %b1
282   br label %end
285   br label %end
287 end:
288   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
289   %iBAD = phi i16 [ %v2, %b0 ], [ %v3, %b1 ]
290   %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
291   store i32 %i0, i32* %d0
292   store i32 %i1, i32* %d1
293   store i16 %iBAD, i16* %d2
294   ret void
296 define void @test9(i32 %v0, i32 %v1, i16 %v2, i16 %v3, i1 %c, i32* %d0, i32* %d1, i16* %d2) {
297 ; CHECK-LABEL: @test9(
298 ; CHECK-NEXT:  entry:
299 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
300 ; CHECK:       b0:
301 ; CHECK-NEXT:    br label [[END:%.*]]
302 ; CHECK:       b1:
303 ; CHECK-NEXT:    br label [[END]]
304 ; CHECK:       end:
305 ; CHECK-NEXT:    [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
306 ; CHECK-NEXT:    [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V1]], [[B1]] ]
307 ; CHECK-NEXT:    [[IBAD:%.*]] = phi i16 [ [[V2:%.*]], [[B0]] ], [ [[V3:%.*]], [[B1]] ]
308 ; CHECK-NEXT:    store i32 [[I0]], i32* [[D0:%.*]], align 4
309 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D1:%.*]], align 4
310 ; CHECK-NEXT:    store i16 [[IBAD]], i16* [[D2:%.*]], align 2
311 ; CHECK-NEXT:    ret void
313 entry:
314   br i1 %c, label %b0, label %b1
317   br label %end
320   br label %end
322 end:
323   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
324   %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
325   %iBAD = phi i16 [ %v2, %b0 ], [ %v3, %b1 ]
326   store i32 %i0, i32* %d0
327   store i32 %i1, i32* %d1
328   store i16 %iBAD, i16* %d2
329   ret void