• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -instcombine < %s | FileCheck %s
3
4declare void @usei32(i32)
5
6; If we have a phi of extractvalues, we can sink it,
7; Here, we only need a PHI for extracted values.
8define i32 @test0({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c) {
9; CHECK-LABEL: @test0(
10; CHECK-NEXT:  entry:
11; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
12; CHECK:       left:
13; CHECK-NEXT:    br label [[END:%.*]]
14; CHECK:       right:
15; CHECK-NEXT:    br label [[END]]
16; CHECK:       end:
17; CHECK-NEXT:    [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ]
18; CHECK-NEXT:    [[R:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT_PN]], 0
19; CHECK-NEXT:    ret i32 [[R]]
20;
21entry:
22  br i1 %c, label %left, label %right
23
24left:
25  %i0 = extractvalue { i32, i32 } %agg_left, 0
26  br label %end
27
28right:
29  %i1 = extractvalue { i32, i32 } %agg_right, 0
30  br label %end
31
32end:
33  %r = phi i32 [ %i0, %left ], [ %i1, %right ]
34  ret i32 %r
35}
36
37; But only if the extractvalues have no extra uses
38define i32 @test1_extrause0({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c) {
39; CHECK-LABEL: @test1_extrause0(
40; CHECK-NEXT:  entry:
41; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
42; CHECK:       left:
43; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT:%.*]], 0
44; CHECK-NEXT:    call void @usei32(i32 [[I0]])
45; CHECK-NEXT:    br label [[END:%.*]]
46; CHECK:       right:
47; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT:%.*]], 0
48; CHECK-NEXT:    br label [[END]]
49; CHECK:       end:
50; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
51; CHECK-NEXT:    ret i32 [[R]]
52;
53entry:
54  br i1 %c, label %left, label %right
55
56left:
57  %i0 = extractvalue { i32, i32 } %agg_left, 0
58  call void  @usei32(i32 %i0)
59  br label %end
60
61right:
62  %i1 = extractvalue { i32, i32 } %agg_right, 0
63  br label %end
64
65end:
66  %r = phi i32 [ %i0, %left ], [ %i1, %right ]
67  ret i32 %r
68}
69define i32 @test2_extrause1({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c) {
70; CHECK-LABEL: @test2_extrause1(
71; CHECK-NEXT:  entry:
72; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
73; CHECK:       left:
74; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT:%.*]], 0
75; CHECK-NEXT:    br label [[END:%.*]]
76; CHECK:       right:
77; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT:%.*]], 0
78; CHECK-NEXT:    call void @usei32(i32 [[I1]])
79; CHECK-NEXT:    br label [[END]]
80; CHECK:       end:
81; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
82; CHECK-NEXT:    ret i32 [[R]]
83;
84entry:
85  br i1 %c, label %left, label %right
86
87left:
88  %i0 = extractvalue { i32, i32 } %agg_left, 0
89  br label %end
90
91right:
92  %i1 = extractvalue { i32, i32 } %agg_right, 0
93  call void  @usei32(i32 %i1)
94  br label %end
95
96end:
97  %r = phi i32 [ %i0, %left ], [ %i1, %right ]
98  ret i32 %r
99}
100define i32 @test3_extrause2({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c) {
101; CHECK-LABEL: @test3_extrause2(
102; CHECK-NEXT:  entry:
103; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
104; CHECK:       left:
105; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT:%.*]], 0
106; CHECK-NEXT:    call void @usei32(i32 [[I0]])
107; CHECK-NEXT:    br label [[END:%.*]]
108; CHECK:       right:
109; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT:%.*]], 0
110; CHECK-NEXT:    call void @usei32(i32 [[I1]])
111; CHECK-NEXT:    br label [[END]]
112; CHECK:       end:
113; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
114; CHECK-NEXT:    ret i32 [[R]]
115;
116entry:
117  br i1 %c, label %left, label %right
118
119left:
120  %i0 = extractvalue { i32, i32 } %agg_left, 0
121  call void  @usei32(i32 %i0)
122  br label %end
123
124right:
125  %i1 = extractvalue { i32, i32 } %agg_right, 0
126  call void  @usei32(i32 %i1)
127  br label %end
128
129end:
130  %r = phi i32 [ %i0, %left ], [ %i1, %right ]
131  ret i32 %r
132}
133
134; But the indicies must match
135define i32 @test4({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c) {
136; CHECK-LABEL: @test4(
137; CHECK-NEXT:  entry:
138; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
139; CHECK:       left:
140; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT:%.*]], 0
141; CHECK-NEXT:    br label [[END:%.*]]
142; CHECK:       right:
143; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT:%.*]], 1
144; CHECK-NEXT:    br label [[END]]
145; CHECK:       end:
146; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
147; CHECK-NEXT:    ret i32 [[R]]
148;
149entry:
150  br i1 %c, label %left, label %right
151
152left:
153  %i0 = extractvalue { i32, i32 } %agg_left, 0
154  br label %end
155
156right:
157  %i1 = extractvalue { i32, i32 } %agg_right, 1
158  br label %end
159
160end:
161  %r = phi i32 [ %i0, %left ], [ %i1, %right ]
162  ret i32 %r
163}
164
165; More complex aggregates are fine, too, as long as indicies match.
166define i32 @test5({{ i32, i32 }, { i32, i32 }} %agg_left, {{ i32, i32 }, { i32, i32 }} %agg_right, i1 %c) {
167; CHECK-LABEL: @test5(
168; CHECK-NEXT:  entry:
169; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
170; CHECK:       left:
171; CHECK-NEXT:    br label [[END:%.*]]
172; CHECK:       right:
173; CHECK-NEXT:    br label [[END]]
174; CHECK:       end:
175; CHECK-NEXT:    [[AGG_LEFT_PN:%.*]] = phi { { i32, i32 }, { i32, i32 } } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ]
176; CHECK-NEXT:    [[R:%.*]] = extractvalue { { i32, i32 }, { i32, i32 } } [[AGG_LEFT_PN]], 0, 0
177; CHECK-NEXT:    ret i32 [[R]]
178;
179entry:
180  br i1 %c, label %left, label %right
181
182left:
183  %i0 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_left, 0, 0
184  br label %end
185
186right:
187  %i1 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_right, 0, 0
188  br label %end
189
190end:
191  %r = phi i32 [ %i0, %left ], [ %i1, %right ]
192  ret i32 %r
193}
194
195; The indicies must fully match, on all levels.
196define i32 @test6({{ i32, i32 }, { i32, i32 }} %agg_left, {{ i32, i32 }, { i32, i32 }} %agg_right, i1 %c) {
197; CHECK-LABEL: @test6(
198; CHECK-NEXT:  entry:
199; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
200; CHECK:       left:
201; CHECK-NEXT:    [[I0:%.*]] = extractvalue { { i32, i32 }, { i32, i32 } } [[AGG_LEFT:%.*]], 0, 0
202; CHECK-NEXT:    br label [[END:%.*]]
203; CHECK:       right:
204; CHECK-NEXT:    [[I1:%.*]] = extractvalue { { i32, i32 }, { i32, i32 } } [[AGG_RIGHT:%.*]], 0, 1
205; CHECK-NEXT:    br label [[END]]
206; CHECK:       end:
207; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
208; CHECK-NEXT:    ret i32 [[R]]
209;
210entry:
211  br i1 %c, label %left, label %right
212
213left:
214  %i0 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_left, 0, 0
215  br label %end
216
217right:
218  %i1 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_right, 0, 1
219  br label %end
220
221end:
222  %r = phi i32 [ %i0, %left ], [ %i1, %right ]
223  ret i32 %r
224}
225define i32 @test7({{ i32, i32 }, { i32, i32 }} %agg_left, {{ i32, i32 }, { i32, i32 }} %agg_right, i1 %c) {
226; CHECK-LABEL: @test7(
227; CHECK-NEXT:  entry:
228; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
229; CHECK:       left:
230; CHECK-NEXT:    [[I0:%.*]] = extractvalue { { i32, i32 }, { i32, i32 } } [[AGG_LEFT:%.*]], 0, 0
231; CHECK-NEXT:    br label [[END:%.*]]
232; CHECK:       right:
233; CHECK-NEXT:    [[I1:%.*]] = extractvalue { { i32, i32 }, { i32, i32 } } [[AGG_RIGHT:%.*]], 1, 0
234; CHECK-NEXT:    br label [[END]]
235; CHECK:       end:
236; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
237; CHECK-NEXT:    ret i32 [[R]]
238;
239entry:
240  br i1 %c, label %left, label %right
241
242left:
243  %i0 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_left, 0, 0
244  br label %end
245
246right:
247  %i1 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_right, 1, 0
248  br label %end
249
250end:
251  %r = phi i32 [ %i0, %left ], [ %i1, %right ]
252  ret i32 %r
253}
254define i32 @test8({{ i32, i32 }, { i32, i32 }} %agg_left, {{ i32, i32 }, { i32, i32 }} %agg_right, i1 %c) {
255; CHECK-LABEL: @test8(
256; CHECK-NEXT:  entry:
257; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
258; CHECK:       left:
259; CHECK-NEXT:    [[I0:%.*]] = extractvalue { { i32, i32 }, { i32, i32 } } [[AGG_LEFT:%.*]], 0, 0
260; CHECK-NEXT:    br label [[END:%.*]]
261; CHECK:       right:
262; CHECK-NEXT:    [[I1:%.*]] = extractvalue { { i32, i32 }, { i32, i32 } } [[AGG_RIGHT:%.*]], 1, 1
263; CHECK-NEXT:    br label [[END]]
264; CHECK:       end:
265; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
266; CHECK-NEXT:    ret i32 [[R]]
267;
268entry:
269  br i1 %c, label %left, label %right
270
271left:
272  %i0 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_left, 0, 0
273  br label %end
274
275right:
276  %i1 = extractvalue {{ i32, i32 }, { i32, i32 }} %agg_right, 1, 1
277  br label %end
278
279end:
280  %r = phi i32 [ %i0, %left ], [ %i1, %right ]
281  ret i32 %r
282}
283
284; Also, unlike PHI-of-insertvalues, here the base aggregates of extractvalue
285; can have different types, and just checking the indicies is not enough.
286define i32 @test9({ i32, i32 } %agg_left, { i32, { i32, i32 } } %agg_right, i1 %c) {
287; CHECK-LABEL: @test9(
288; CHECK-NEXT:  entry:
289; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
290; CHECK:       left:
291; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT:%.*]], 0
292; CHECK-NEXT:    br label [[END:%.*]]
293; CHECK:       right:
294; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, { i32, i32 } } [[AGG_RIGHT:%.*]], 0
295; CHECK-NEXT:    br label [[END]]
296; CHECK:       end:
297; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
298; CHECK-NEXT:    ret i32 [[R]]
299;
300entry:
301  br i1 %c, label %left, label %right
302
303left:
304  %i0 = extractvalue { i32, i32 } %agg_left, 0
305  br label %end
306
307right:
308  %i1 = extractvalue { i32, { i32, i32 } } %agg_right, 0
309  br label %end
310
311end:
312  %r = phi i32 [ %i0, %left ], [ %i1, %right ]
313  ret i32 %r
314}
315
316; It is fine if there are multiple uses of the PHI's value, as long as they are all in the PHI node itself
317define i32 @test10({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c0, i1 %c1) {
318; CHECK-LABEL: @test10(
319; CHECK-NEXT:  entry:
320; CHECK-NEXT:    br i1 [[C0:%.*]], label [[END:%.*]], label [[DISPATCH:%.*]]
321; CHECK:       dispatch:
322; CHECK-NEXT:    br i1 [[C1:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
323; CHECK:       left:
324; CHECK-NEXT:    br label [[END]]
325; CHECK:       right:
326; CHECK-NEXT:    br label [[END]]
327; CHECK:       end:
328; CHECK-NEXT:    [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[ENTRY:%.*]] ], [ [[AGG_LEFT]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ]
329; CHECK-NEXT:    [[R:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT_PN]], 0
330; CHECK-NEXT:    ret i32 [[R]]
331;
332entry:
333  %i0 = extractvalue { i32, i32 } %agg_left, 0
334  %i1 = extractvalue { i32, i32 } %agg_right, 0
335  br i1 %c0, label %end, label %dispatch
336
337dispatch:
338  br i1 %c1, label %left, label %right
339
340left:
341  br label %end
342
343right:
344  br label %end
345
346end:
347  %r = phi i32 [ %i0, %entry ], [ %i0, %left ], [ %i1, %right ]
348  ret i32 %r
349}
350; Which isn't the case here, there is a legitimate external use.
351define i32 @test11({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c0, i1 %c1) {
352; CHECK-LABEL: @test11(
353; CHECK-NEXT:  entry:
354; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT:%.*]], 0
355; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT:%.*]], 0
356; CHECK-NEXT:    call void @usei32(i32 [[I0]])
357; CHECK-NEXT:    br i1 [[C0:%.*]], label [[END:%.*]], label [[DISPATCH:%.*]]
358; CHECK:       dispatch:
359; CHECK-NEXT:    br i1 [[C1:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
360; CHECK:       left:
361; CHECK-NEXT:    br label [[END]]
362; CHECK:       right:
363; CHECK-NEXT:    br label [[END]]
364; CHECK:       end:
365; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[I0]], [[ENTRY:%.*]] ], [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
366; CHECK-NEXT:    ret i32 [[R]]
367;
368entry:
369  %i0 = extractvalue { i32, i32 } %agg_left, 0
370  %i1 = extractvalue { i32, i32 } %agg_right, 0
371  call void @usei32(i32 %i0)
372  br i1 %c0, label %end, label %dispatch
373
374dispatch:
375  br i1 %c1, label %left, label %right
376
377left:
378  br label %end
379
380right:
381  br label %end
382
383end:
384  %r = phi i32 [ %i0, %entry ], [ %i0, %left ], [ %i1, %right ]
385  ret i32 %r
386}
387