xref: /llvm-project/llvm/test/Transforms/InstCombine/phi-of-insertvalues.ll (revision 1650f1b3d7f97ca95eb930984e74bdfd91b02b4e)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3
4declare void @usei32i32agg({ i32, i32 })
5
6; If we have a phi of insertvalues, we can sink it,
7; Here, we only need a PHI for inserted values.
8define { i32, i32 } @test0({ i32, i32 } %agg, i32 %val_left, i32 %val_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:    [[VAL_LEFT_PN:%.*]] = phi i32 [ [[VAL_LEFT:%.*]], [[LEFT]] ], [ [[VAL_RIGHT:%.*]], [[RIGHT]] ]
18; CHECK-NEXT:    [[R:%.*]] = insertvalue { i32, i32 } [[AGG:%.*]], i32 [[VAL_LEFT_PN]], 0
19; CHECK-NEXT:    ret { i32, i32 } [[R]]
20;
21entry:
22  br i1 %c, label %left, label %right
23
24left:
25  %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 0
26  br label %end
27
28right:
29  %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 0
30  br label %end
31
32end:
33  %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]
34  ret { i32, i32 } %r
35}
36
37; But only if the insertvalues have no extra uses
38define { i32, i32 } @test1_extrause0({ i32, i32 } %agg, i32 %val_left, i32 %val_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:%.*]] = insertvalue { i32, i32 } [[AGG:%.*]], i32 [[VAL_LEFT:%.*]], 0
44; CHECK-NEXT:    call void @usei32i32agg({ i32, i32 } [[I0]])
45; CHECK-NEXT:    br label [[END:%.*]]
46; CHECK:       right:
47; CHECK-NEXT:    [[I1:%.*]] = insertvalue { i32, i32 } [[AGG]], i32 [[VAL_RIGHT:%.*]], 0
48; CHECK-NEXT:    br label [[END]]
49; CHECK:       end:
50; CHECK-NEXT:    [[R:%.*]] = phi { i32, i32 } [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
51; CHECK-NEXT:    ret { i32, i32 } [[R]]
52;
53entry:
54  br i1 %c, label %left, label %right
55
56left:
57  %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 0
58  call void  @usei32i32agg({ i32, i32 } %i0 )
59  br label %end
60
61right:
62  %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 0
63  br label %end
64
65end:
66  %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]
67  ret { i32, i32 } %r
68}
69define { i32, i32 } @test2_extrause1({ i32, i32 } %agg, i32 %val_left, i32 %val_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:%.*]] = insertvalue { i32, i32 } [[AGG:%.*]], i32 [[VAL_LEFT:%.*]], 0
75; CHECK-NEXT:    br label [[END:%.*]]
76; CHECK:       right:
77; CHECK-NEXT:    [[I1:%.*]] = insertvalue { i32, i32 } [[AGG]], i32 [[VAL_RIGHT:%.*]], 0
78; CHECK-NEXT:    call void @usei32i32agg({ i32, i32 } [[I1]])
79; CHECK-NEXT:    br label [[END]]
80; CHECK:       end:
81; CHECK-NEXT:    [[R:%.*]] = phi { i32, i32 } [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
82; CHECK-NEXT:    ret { i32, i32 } [[R]]
83;
84entry:
85  br i1 %c, label %left, label %right
86
87left:
88  %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 0
89  br label %end
90
91right:
92  %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 0
93  call void  @usei32i32agg({ i32, i32 } %i1 )
94  br label %end
95
96end:
97  %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]
98  ret { i32, i32 } %r
99}
100define { i32, i32 } @test3_extrause2({ i32, i32 } %agg, i32 %val_left, i32 %val_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:%.*]] = insertvalue { i32, i32 } [[AGG:%.*]], i32 [[VAL_LEFT:%.*]], 0
106; CHECK-NEXT:    call void @usei32i32agg({ i32, i32 } [[I0]])
107; CHECK-NEXT:    br label [[END:%.*]]
108; CHECK:       right:
109; CHECK-NEXT:    [[I1:%.*]] = insertvalue { i32, i32 } [[AGG]], i32 [[VAL_RIGHT:%.*]], 0
110; CHECK-NEXT:    call void @usei32i32agg({ i32, i32 } [[I1]])
111; CHECK-NEXT:    br label [[END]]
112; CHECK:       end:
113; CHECK-NEXT:    [[R:%.*]] = phi { i32, i32 } [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
114; CHECK-NEXT:    ret { i32, i32 } [[R]]
115;
116entry:
117  br i1 %c, label %left, label %right
118
119left:
120  %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 0
121  call void  @usei32i32agg({ i32, i32 } %i0 )
122  br label %end
123
124right:
125  %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 0
126  call void  @usei32i32agg({ i32, i32 } %i1 )
127  br label %end
128
129end:
130  %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]
131  ret { i32, i32 } %r
132}
133
134; Here, we only need a PHI for base aggregate
135define { i32, i32 } @test4({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i32 %val, 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:    br label [[END:%.*]]
141; CHECK:       right:
142; CHECK-NEXT:    br label [[END]]
143; CHECK:       end:
144; CHECK-NEXT:    [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ]
145; CHECK-NEXT:    [[R:%.*]] = insertvalue { i32, i32 } [[AGG_LEFT_PN]], i32 [[VAL:%.*]], 0
146; CHECK-NEXT:    ret { i32, i32 } [[R]]
147;
148entry:
149  br i1 %c, label %left, label %right
150
151left:
152  %i0 = insertvalue { i32, i32 } %agg_left, i32 %val, 0
153  br label %end
154
155right:
156  %i1 = insertvalue { i32, i32 } %agg_right, i32 %val, 0
157  br label %end
158
159end:
160  %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]
161  ret { i32, i32 } %r
162}
163
164; Here, we need a PHI for both the base and the inserted value
165define { i32, i32 } @test5({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i32 %val_left, i32 %val_right, i1 %c) {
166; CHECK-LABEL: @test5(
167; CHECK-NEXT:  entry:
168; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
169; CHECK:       left:
170; CHECK-NEXT:    br label [[END:%.*]]
171; CHECK:       right:
172; CHECK-NEXT:    br label [[END]]
173; CHECK:       end:
174; CHECK-NEXT:    [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ]
175; CHECK-NEXT:    [[VAL_LEFT_PN:%.*]] = phi i32 [ [[VAL_LEFT:%.*]], [[LEFT]] ], [ [[VAL_RIGHT:%.*]], [[RIGHT]] ]
176; CHECK-NEXT:    [[R:%.*]] = insertvalue { i32, i32 } [[AGG_LEFT_PN]], i32 [[VAL_LEFT_PN]], 0
177; CHECK-NEXT:    ret { i32, i32 } [[R]]
178;
179entry:
180  br i1 %c, label %left, label %right
181
182left:
183  %i0 = insertvalue { i32, i32 } %agg_left, i32 %val_left, 0
184  br label %end
185
186right:
187  %i1 = insertvalue { i32, i32 } %agg_right, i32 %val_right, 0
188  br label %end
189
190end:
191  %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]
192  ret { i32, i32 } %r
193}
194
195; But the indices must match
196define { i32, i32 } @test6({ i32, i32 } %agg, i32 %val_left, i32 %val_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:%.*]] = insertvalue { i32, i32 } [[AGG:%.*]], i32 [[VAL_LEFT:%.*]], 0
202; CHECK-NEXT:    br label [[END:%.*]]
203; CHECK:       right:
204; CHECK-NEXT:    [[I1:%.*]] = insertvalue { i32, i32 } [[AGG]], i32 [[VAL_RIGHT:%.*]], 1
205; CHECK-NEXT:    br label [[END]]
206; CHECK:       end:
207; CHECK-NEXT:    [[R:%.*]] = phi { i32, i32 } [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
208; CHECK-NEXT:    ret { i32, i32 } [[R]]
209;
210entry:
211  br i1 %c, label %left, label %right
212
213left:
214  %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 0
215  br label %end
216
217right:
218  %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 1
219  br label %end
220
221end:
222  %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]
223  ret { i32, i32 } %r
224}
225
226; More complex aggregates are fine, too, as long as indices match.
227define {{ i32, i32 }, { i32, i32 }} @test7({{ i32, i32 }, { i32, i32 }} %agg, i32 %val_left, i32 %val_right, i1 %c) {
228; CHECK-LABEL: @test7(
229; CHECK-NEXT:  entry:
230; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
231; CHECK:       left:
232; CHECK-NEXT:    br label [[END:%.*]]
233; CHECK:       right:
234; CHECK-NEXT:    br label [[END]]
235; CHECK:       end:
236; CHECK-NEXT:    [[VAL_LEFT_PN:%.*]] = phi i32 [ [[VAL_LEFT:%.*]], [[LEFT]] ], [ [[VAL_RIGHT:%.*]], [[RIGHT]] ]
237; CHECK-NEXT:    [[R:%.*]] = insertvalue { { i32, i32 }, { i32, i32 } } [[AGG:%.*]], i32 [[VAL_LEFT_PN]], 0, 0
238; CHECK-NEXT:    ret { { i32, i32 }, { i32, i32 } } [[R]]
239;
240entry:
241  br i1 %c, label %left, label %right
242
243left:
244  %i0 = insertvalue {{ i32, i32 }, { i32, i32 }} %agg, i32 %val_left, 0, 0
245  br label %end
246
247right:
248  %i1 = insertvalue {{ i32, i32 }, { i32, i32 }} %agg, i32 %val_right, 0, 0
249  br label %end
250
251end:
252  %r = phi {{ i32, i32 }, { i32, i32 }} [ %i0, %left ], [ %i1, %right ]
253  ret {{ i32, i32 }, { i32, i32 }} %r
254}
255
256; The indices must fully match, on all levels.
257define {{ i32, i32 }, { i32, i32 }} @test8({{ i32, i32 }, { i32, i32 }} %agg, i32 %val_left, i32 %val_right, i1 %c) {
258; CHECK-LABEL: @test8(
259; CHECK-NEXT:  entry:
260; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
261; CHECK:       left:
262; CHECK-NEXT:    [[I0:%.*]] = insertvalue { { i32, i32 }, { i32, i32 } } [[AGG:%.*]], i32 [[VAL_LEFT:%.*]], 0, 0
263; CHECK-NEXT:    br label [[END:%.*]]
264; CHECK:       right:
265; CHECK-NEXT:    [[I1:%.*]] = insertvalue { { i32, i32 }, { i32, i32 } } [[AGG]], i32 [[VAL_RIGHT:%.*]], 0, 1
266; CHECK-NEXT:    br label [[END]]
267; CHECK:       end:
268; CHECK-NEXT:    [[R:%.*]] = phi { { i32, i32 }, { i32, i32 } } [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
269; CHECK-NEXT:    ret { { i32, i32 }, { i32, i32 } } [[R]]
270;
271entry:
272  br i1 %c, label %left, label %right
273
274left:
275  %i0 = insertvalue {{ i32, i32 }, { i32, i32 }} %agg, i32 %val_left, 0, 0
276  br label %end
277
278right:
279  %i1 = insertvalue {{ i32, i32 }, { i32, i32 }} %agg, i32 %val_right, 0, 1
280  br label %end
281
282end:
283  %r = phi {{ i32, i32 }, { i32, i32 }} [ %i0, %left ], [ %i1, %right ]
284  ret {{ i32, i32 }, { i32, i32 }} %r
285}
286
287; It is fine if there are multiple uses of the PHI's value, as long as they are all in the PHI node itself
288define { i32, i32 } @test9({ i32, i32 } %agg, i32 %val_left, i32 %val_right, i1 %c0, i1 %c1) {
289; CHECK-LABEL: @test9(
290; CHECK-NEXT:  entry:
291; CHECK-NEXT:    br i1 [[C0:%.*]], label [[END:%.*]], label [[DISPATCH:%.*]]
292; CHECK:       dispatch:
293; CHECK-NEXT:    br i1 [[C1:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
294; CHECK:       left:
295; CHECK-NEXT:    br label [[END]]
296; CHECK:       right:
297; CHECK-NEXT:    br label [[END]]
298; CHECK:       end:
299; CHECK-NEXT:    [[VAL_LEFT_PN:%.*]] = phi i32 [ [[VAL_LEFT:%.*]], [[ENTRY:%.*]] ], [ [[VAL_LEFT]], [[LEFT]] ], [ [[VAL_RIGHT:%.*]], [[RIGHT]] ]
300; CHECK-NEXT:    [[R:%.*]] = insertvalue { i32, i32 } [[AGG:%.*]], i32 [[VAL_LEFT_PN]], 0
301; CHECK-NEXT:    ret { i32, i32 } [[R]]
302;
303entry:
304  %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 0
305  %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 0
306  br i1 %c0, label %end, label %dispatch
307
308dispatch:
309  br i1 %c1, label %left, label %right
310
311left:
312  br label %end
313
314right:
315  br label %end
316
317end:
318  %r = phi { i32, i32 } [ %i0, %entry ], [ %i0, %left ], [ %i1, %right ]
319  ret { i32, i32 } %r
320}
321; Which isn't the case here, there is a legitimate external use.
322define { i32, i32 } @test10({ i32, i32 } %agg, i32 %val_left, i32 %val_right, i1 %c0, i1 %c1) {
323; CHECK-LABEL: @test10(
324; CHECK-NEXT:  entry:
325; CHECK-NEXT:    [[I0:%.*]] = insertvalue { i32, i32 } [[AGG:%.*]], i32 [[VAL_LEFT:%.*]], 0
326; CHECK-NEXT:    [[I1:%.*]] = insertvalue { i32, i32 } [[AGG]], i32 [[VAL_RIGHT:%.*]], 0
327; CHECK-NEXT:    call void @usei32i32agg({ i32, i32 } [[I0]])
328; CHECK-NEXT:    br i1 [[C0:%.*]], label [[END:%.*]], label [[DISPATCH:%.*]]
329; CHECK:       dispatch:
330; CHECK-NEXT:    br i1 [[C1:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
331; CHECK:       left:
332; CHECK-NEXT:    br label [[END]]
333; CHECK:       right:
334; CHECK-NEXT:    br label [[END]]
335; CHECK:       end:
336; CHECK-NEXT:    [[R:%.*]] = phi { i32, i32 } [ [[I0]], [[ENTRY:%.*]] ], [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
337; CHECK-NEXT:    ret { i32, i32 } [[R]]
338;
339entry:
340  %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 0
341  %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 0
342  call void @usei32i32agg({ i32, i32 } %i0)
343  br i1 %c0, label %end, label %dispatch
344
345dispatch:
346  br i1 %c1, label %left, label %right
347
348left:
349  br label %end
350
351right:
352  br label %end
353
354end:
355  %r = phi { i32, i32 } [ %i0, %entry ], [ %i0, %left ], [ %i1, %right ]
356  ret { i32, i32 } %r
357}
358