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) {
8 ; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
10 ; CHECK-NEXT: br label [[END:%.*]]
12 ; CHECK-NEXT: br label [[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
20 br i1 %c, label %b0, label %b1
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
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(
40 ; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
42 ; CHECK-NEXT: br label [[END:%.*]]
44 ; CHECK-NEXT: br label [[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
52 br i1 %c, label %b0, label %b1
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
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(
72 ; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
74 ; CHECK-NEXT: br label [[END:%.*]]
76 ; CHECK-NEXT: br label [[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
85 br i1 %c, label %b0, label %b1
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
100 define void @negative_test3(i32 %v0, i32 %v1, i32 %v2, i1 %c, i32* %d0, i32* %d1) {
101 ; CHECK-LABEL: @negative_test3(
103 ; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
105 ; CHECK-NEXT: br label [[END:%.*]]
107 ; CHECK-NEXT: br label [[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
116 br i1 %c, label %b0, label %b1
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
131 define void @negative_test4(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
132 ; CHECK-LABEL: @negative_test4(
134 ; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
136 ; CHECK-NEXT: br label [[END:%.*]]
138 ; CHECK-NEXT: br label [[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
146 br i1 %c, label %b0, label %b1
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
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(
166 ; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
168 ; CHECK-NEXT: br label [[END:%.*]]
170 ; CHECK-NEXT: br label [[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
177 br i1 %c, label %b0, label %b1
186 %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] ; unused
187 %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
188 store i32 %i1, i32* %d1
191 ; Second PHI has no uses
192 define void @test6(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
193 ; CHECK-LABEL: @test6(
195 ; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
197 ; CHECK-NEXT: br label [[END:%.*]]
199 ; CHECK-NEXT: br label [[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
206 br i1 %c, label %b0, label %b1
215 %i0 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ]
216 %i1 = phi i32 [ %v0, %b0 ], [ %v1, %b1 ] ; unused
217 store i32 %i0, i32* %d0
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(
225 ; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
227 ; CHECK-NEXT: br label [[END:%.*]]
229 ; CHECK-NEXT: br label [[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
239 br i1 %c, label %b0, label %b1
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
256 define void @test8(i32 %v0, i32 %v1, i16 %v2, i16 %v3, i1 %c, i32* %d0, i32* %d1, i16* %d2) {
257 ; CHECK-LABEL: @test8(
259 ; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
261 ; CHECK-NEXT: br label [[END:%.*]]
263 ; CHECK-NEXT: br label [[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
273 br i1 %c, label %b0, label %b1
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
290 define void @test9(i32 %v0, i32 %v1, i16 %v2, i16 %v3, i1 %c, i32* %d0, i32* %d1, i16* %d2) {
291 ; CHECK-LABEL: @test9(
293 ; CHECK-NEXT: br i1 [[C:%.*]], label [[B0:%.*]], label [[B1:%.*]]
295 ; CHECK-NEXT: br label [[END:%.*]]
297 ; CHECK-NEXT: br label [[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
307 br i1 %c, label %b0, label %b1
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