[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / phi-cse.ll
blob5f86a5e893dbfcc5c85fde33b0f5a51731dd98eb
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -instcombine -S < %s | FileCheck %s
4 ; Most basic case, fully identical PHI nodes
5 define void @test0(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
6 ; CHECK-LABEL: @test0(
7 ; CHECK-NEXT:  entry:
8 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
9 ; CHECK:       b0:
10 ; CHECK-NEXT:    br label [[END:%.*]]
11 ; CHECK:       b1:
12 ; CHECK-NEXT:    br label [[END]]
13 ; CHECK:       end:
14 ; CHECK-NEXT:    [[I1:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
15 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D0:%.*]], align 4
16 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D1:%.*]], align 4
17 ; CHECK-NEXT:    ret void
19 entry:
20   br i1 %c, label %b0, label %b1
22 b0:
23   br label %end
25 b1:
26   br label %end
28 end:
29   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
30   %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
31   store i32 %i0, i32* %d0
32   store i32 %i1, i32* %d1
33   ret void
36 ; Fully identical PHI nodes, but order of operands differs
37 define void @test1(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
38 ; CHECK-LABEL: @test1(
39 ; CHECK-NEXT:  entry:
40 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
41 ; CHECK:       b0:
42 ; CHECK-NEXT:    br label [[END:%.*]]
43 ; CHECK:       b1:
44 ; CHECK-NEXT:    br label [[END]]
45 ; CHECK:       end:
46 ; CHECK-NEXT:    [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
47 ; CHECK-NEXT:    store i32 [[I0]], i32* [[D0:%.*]], align 4
48 ; CHECK-NEXT:    store i32 [[I0]], i32* [[D1:%.*]], align 4
49 ; CHECK-NEXT:    ret void
51 entry:
52   br i1 %c, label %b0, label %b1
54 b0:
55   br label %end
57 b1:
58   br label %end
60 end:
61   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
62   %i1 = phi i32 [ %v1, %b1 ], [ %v0, %b0 ]
63   store i32 %i0, i32* %d0
64   store i32 %i1, i32* %d1
65   ret void
68 ; Different incoming values in second PHI
69 define void @negative_test2(i32 %v0, i32 %v1, i32 %v2, i1 %c, i32* %d0, i32* %d1) {
70 ; CHECK-LABEL: @negative_test2(
71 ; CHECK-NEXT:  entry:
72 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
73 ; CHECK:       b0:
74 ; CHECK-NEXT:    br label [[END:%.*]]
75 ; CHECK:       b1:
76 ; CHECK-NEXT:    br label [[END]]
77 ; CHECK:       end:
78 ; CHECK-NEXT:    [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
79 ; CHECK-NEXT:    [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V2:%.*]], [[B1]] ]
80 ; CHECK-NEXT:    store i32 [[I0]], i32* [[D0:%.*]], align 4
81 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D1:%.*]], align 4
82 ; CHECK-NEXT:    ret void
84 entry:
85   br i1 %c, label %b0, label %b1
87 b0:
88   br label %end
90 b1:
91   br label %end
93 end:
94   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
95   %i1 = phi i32 [ %v0, %b0 ], [ %v2, %b1 ] ; from %b0 takes %v2 instead of %v1
96   store i32 %i0, i32* %d0
97   store i32 %i1, i32* %d1
98   ret void
100 define void @negative_test3(i32 %v0, i32 %v1, i32 %v2, i1 %c, i32* %d0, i32* %d1) {
101 ; CHECK-LABEL: @negative_test3(
102 ; CHECK-NEXT:  entry:
103 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
104 ; CHECK:       b0:
105 ; CHECK-NEXT:    br label [[END:%.*]]
106 ; CHECK:       b1:
107 ; CHECK-NEXT:    br label [[END]]
108 ; CHECK:       end:
109 ; CHECK-NEXT:    [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
110 ; CHECK-NEXT:    [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V2:%.*]], [[B1]] ]
111 ; CHECK-NEXT:    store i32 [[I0]], i32* [[D0:%.*]], align 4
112 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D1:%.*]], align 4
113 ; CHECK-NEXT:    ret void
115 entry:
116   br i1 %c, label %b0, label %b1
119   br label %end
122   br label %end
124 end:
125   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
126   %i1 = phi i32 [ %v2, %b1 ], [ %v0, %b0 ] ; from %b0 takes %v2 instead of %v1
127   store i32 %i0, i32* %d0
128   store i32 %i1, i32* %d1
129   ret void
131 define void @negative_test4(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
132 ; CHECK-LABEL: @negative_test4(
133 ; CHECK-NEXT:  entry:
134 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
135 ; CHECK:       b0:
136 ; CHECK-NEXT:    br label [[END:%.*]]
137 ; CHECK:       b1:
138 ; CHECK-NEXT:    br label [[END]]
139 ; CHECK:       end:
140 ; CHECK-NEXT:    [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
141 ; CHECK-NEXT:    store i32 [[I0]], i32* [[D0:%.*]], align 4
142 ; CHECK-NEXT:    store i32 [[I0]], i32* [[D1:%.*]], align 4
143 ; CHECK-NEXT:    ret void
145 entry:
146   br i1 %c, label %b0, label %b1
149   br label %end
152   br label %end
154 end:
155   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
156   %i1 = phi i32 [ %v1, %b1 ], [ %v0, %b0 ] ; incoming values are swapped
157   store i32 %i0, i32* %d0
158   store i32 %i1, i32* %d1
159   ret void
162 ; Both PHI's are identical, but the first one has no uses, so ignore it.
163 define void @test5(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
164 ; CHECK-LABEL: @test5(
165 ; CHECK-NEXT:  entry:
166 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
167 ; CHECK:       b0:
168 ; CHECK-NEXT:    br label [[END:%.*]]
169 ; CHECK:       b1:
170 ; CHECK-NEXT:    br label [[END]]
171 ; CHECK:       end:
172 ; CHECK-NEXT:    [[I1:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
173 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D1:%.*]], align 4
174 ; CHECK-NEXT:    ret void
176 entry:
177   br i1 %c, label %b0, label %b1
180   br label %end
183   br label %end
185 end:
186   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] ; unused
187   %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
188   store i32 %i1, i32* %d1
189   ret void
191 ; Second PHI has no uses
192 define void @test6(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
193 ; CHECK-LABEL: @test6(
194 ; CHECK-NEXT:  entry:
195 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
196 ; CHECK:       b0:
197 ; CHECK-NEXT:    br label [[END:%.*]]
198 ; CHECK:       b1:
199 ; CHECK-NEXT:    br label [[END]]
200 ; CHECK:       end:
201 ; CHECK-NEXT:    [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
202 ; CHECK-NEXT:    store i32 [[I0]], i32* [[D0:%.*]], align 4
203 ; CHECK-NEXT:    ret void
205 entry:
206   br i1 %c, label %b0, label %b1
209   br label %end
212   br label %end
214 end:
215   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
216   %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] ; unused
217   store i32 %i0, i32* %d0
218   ret void
221 ; Non-matching PHI node should be ignored without terminating CSE.
222 define void @test7(i32 %v0, i32 %v1, i16 %v2, i16 %v3, i1 %c, i32* %d0, i32* %d1, i16* %d2) {
223 ; CHECK-LABEL: @test7(
224 ; CHECK-NEXT:  entry:
225 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
226 ; CHECK:       b0:
227 ; CHECK-NEXT:    br label [[END:%.*]]
228 ; CHECK:       b1:
229 ; CHECK-NEXT:    br label [[END]]
230 ; CHECK:       end:
231 ; CHECK-NEXT:    [[IBAD:%.*]] = phi i16 [ [[V2:%.*]], [[B0]] ], [ [[V3:%.*]], [[B1]] ]
232 ; CHECK-NEXT:    [[I1:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
233 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D0:%.*]], align 4
234 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D1:%.*]], align 4
235 ; CHECK-NEXT:    store i16 [[IBAD]], i16* [[D2:%.*]], align 2
236 ; CHECK-NEXT:    ret void
238 entry:
239   br i1 %c, label %b0, label %b1
242   br label %end
245   br label %end
247 end:
248   %iBAD = phi i16 [ %v2, %b0 ], [ %v3, %b1 ]
249   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
250   %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
251   store i32 %i0, i32* %d0
252   store i32 %i1, i32* %d1
253   store i16 %iBAD, i16* %d2
254   ret void
256 define void @test8(i32 %v0, i32 %v1, i16 %v2, i16 %v3, i1 %c, i32* %d0, i32* %d1, i16* %d2) {
257 ; CHECK-LABEL: @test8(
258 ; CHECK-NEXT:  entry:
259 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
260 ; CHECK:       b0:
261 ; CHECK-NEXT:    br label [[END:%.*]]
262 ; CHECK:       b1:
263 ; CHECK-NEXT:    br label [[END]]
264 ; CHECK:       end:
265 ; CHECK-NEXT:    [[IBAD:%.*]] = phi i16 [ [[V2:%.*]], [[B0]] ], [ [[V3:%.*]], [[B1]] ]
266 ; CHECK-NEXT:    [[I1:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
267 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D0:%.*]], align 4
268 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D1:%.*]], align 4
269 ; CHECK-NEXT:    store i16 [[IBAD]], i16* [[D2:%.*]], align 2
270 ; CHECK-NEXT:    ret void
272 entry:
273   br i1 %c, label %b0, label %b1
276   br label %end
279   br label %end
281 end:
282   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
283   %iBAD = phi i16 [ %v2, %b0 ], [ %v3, %b1 ]
284   %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
285   store i32 %i0, i32* %d0
286   store i32 %i1, i32* %d1
287   store i16 %iBAD, i16* %d2
288   ret void
290 define void @test9(i32 %v0, i32 %v1, i16 %v2, i16 %v3, i1 %c, i32* %d0, i32* %d1, i16* %d2) {
291 ; CHECK-LABEL: @test9(
292 ; CHECK-NEXT:  entry:
293 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
294 ; CHECK:       b0:
295 ; CHECK-NEXT:    br label [[END:%.*]]
296 ; CHECK:       b1:
297 ; CHECK-NEXT:    br label [[END]]
298 ; CHECK:       end:
299 ; CHECK-NEXT:    [[I1:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
300 ; CHECK-NEXT:    [[IBAD:%.*]] = phi i16 [ [[V2:%.*]], [[B0]] ], [ [[V3:%.*]], [[B1]] ]
301 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D0:%.*]], align 4
302 ; CHECK-NEXT:    store i32 [[I1]], i32* [[D1:%.*]], align 4
303 ; CHECK-NEXT:    store i16 [[IBAD]], i16* [[D2:%.*]], align 2
304 ; CHECK-NEXT:    ret void
306 entry:
307   br i1 %c, label %b0, label %b1
310   br label %end
313   br label %end
315 end:
316   %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
317   %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
318   %iBAD = phi i16 [ %v2, %b0 ], [ %v3, %b1 ]
319   store i32 %i0, i32* %d0
320   store i32 %i1, i32* %d1
321   store i16 %iBAD, i16* %d2
322   ret void