1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -instcombine -S < %s | FileCheck %s
3
4; Most basic case, fully identical PHI nodes
5define 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
18;
19entry:
20  br i1 %c, label %b0, label %b1
21
22b0:
23  br label %end
24
25b1:
26  br label %end
27
28end:
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
34}
35
36; Fully identical PHI nodes, but order of operands differs
37define 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
50;
51entry:
52  br i1 %c, label %b0, label %b1
53
54b0:
55  br label %end
56
57b1:
58  br label %end
59
60end:
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
66}
67
68; Different incoming values in second PHI
69define 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
83;
84entry:
85  br i1 %c, label %b0, label %b1
86
87b0:
88  br label %end
89
90b1:
91  br label %end
92
93end:
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
99}
100define 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
114;
115entry:
116  br i1 %c, label %b0, label %b1
117
118b0:
119  br label %end
120
121b1:
122  br label %end
123
124end:
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
130}
131define 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
144;
145entry:
146  br i1 %c, label %b0, label %b1
147
148b0:
149  br label %end
150
151b1:
152  br label %end
153
154end:
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
160}
161
162; Both PHI's are identical, but the first one has no uses, so ignore it.
163define 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
175;
176entry:
177  br i1 %c, label %b0, label %b1
178
179b0:
180  br label %end
181
182b1:
183  br label %end
184
185end:
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
190}
191; Second PHI has no uses
192define 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
204;
205entry:
206  br i1 %c, label %b0, label %b1
207
208b0:
209  br label %end
210
211b1:
212  br label %end
213
214end:
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
219}
220
221; Non-matching PHI node should be ignored without terminating CSE.
222define 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
237;
238entry:
239  br i1 %c, label %b0, label %b1
240
241b0:
242  br label %end
243
244b1:
245  br label %end
246
247end:
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
255}
256define 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
271;
272entry:
273  br i1 %c, label %b0, label %b1
274
275b0:
276  br label %end
277
278b1:
279  br label %end
280
281end:
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
289}
290define 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
305;
306entry:
307  br i1 %c, label %b0, label %b1
308
309b0:
310  br label %end
311
312b1:
313  br label %end
314
315end:
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
323}
324