Revert "[InstCombine] Support gep nuw in icmp folds" (#118698)
[llvm-project.git] / llvm / test / Transforms / InstCombine / aggregate-reconstruction.ll
blobcb7c0dee9feb49a5e7a30193a9390c1cc29588e0
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s
4 declare void @foo()
5 declare void @bar()
6 declare void @baz()
8 declare void @usei32(i32)
9 declare void @usei32i32agg({ i32, i32 })
11 ; Most basic test - we explode the original aggregate into it's elements,
12 ; and then merge them back together exactly the way they were.
13 ; We should just return the source aggregate.
14 define { i32, i32 } @test0({ i32, i32 } %srcagg) {
15 ; CHECK-LABEL: @test0(
16 ; CHECK-NEXT:    ret { i32, i32 } [[SRCAGG:%.*]]
18   %i0 = extractvalue { i32, i32 } %srcagg, 0
19   %i1 = extractvalue { i32, i32 } %srcagg, 1
20   %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0
21   %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 1
22   ret { i32, i32 } %i3
25 ; Arrays are still aggregates
26 define [2 x i32] @test1([2 x i32] %srcagg) {
27 ; CHECK-LABEL: @test1(
28 ; CHECK-NEXT:    ret [2 x i32] [[SRCAGG:%.*]]
30   %i0 = extractvalue [2 x i32] %srcagg, 0
31   %i1 = extractvalue [2 x i32] %srcagg, 1
32   %i2 = insertvalue [2 x i32] undef, i32 %i0, 0
33   %i3 = insertvalue [2 x i32] %i2, i32 %i1, 1
34   ret [2 x i32] %i3
37 ; Right now we don't deal with case where there are more than 2 elements.
38 ; FIXME: should we?
39 define [3 x i32] @test2([3 x i32] %srcagg) {
40 ; CHECK-LABEL: @test2(
41 ; CHECK-NEXT:    [[I0:%.*]] = extractvalue [3 x i32] [[SRCAGG:%.*]], 0
42 ; CHECK-NEXT:    [[I1:%.*]] = extractvalue [3 x i32] [[SRCAGG]], 1
43 ; CHECK-NEXT:    [[I2:%.*]] = extractvalue [3 x i32] [[SRCAGG]], 2
44 ; CHECK-NEXT:    [[I3:%.*]] = insertvalue [3 x i32] undef, i32 [[I0]], 0
45 ; CHECK-NEXT:    [[I4:%.*]] = insertvalue [3 x i32] [[I3]], i32 [[I1]], 1
46 ; CHECK-NEXT:    [[I5:%.*]] = insertvalue [3 x i32] [[I4]], i32 [[I2]], 2
47 ; CHECK-NEXT:    ret [3 x i32] [[I5]]
49   %i0 = extractvalue [3 x i32] %srcagg, 0
50   %i1 = extractvalue [3 x i32] %srcagg, 1
51   %i2 = extractvalue [3 x i32] %srcagg, 2
52   %i3 = insertvalue [3 x i32] undef, i32 %i0, 0
53   %i4 = insertvalue [3 x i32] %i3, i32 %i1, 1
54   %i5 = insertvalue [3 x i32] %i4, i32 %i2, 2
55   ret [3 x i32] %i5
58 ; Likewise, we only deal with a single-level aggregates.
59 ; FIXME: should we?
60 define {{ i32, i32 }} @test3({{ i32, i32 }} %srcagg) {
61 ; CHECK-LABEL: @test3(
62 ; CHECK-NEXT:    [[I0:%.*]] = extractvalue { { i32, i32 } } [[SRCAGG:%.*]], 0, 0
63 ; CHECK-NEXT:    [[I1:%.*]] = extractvalue { { i32, i32 } } [[SRCAGG]], 0, 1
64 ; CHECK-NEXT:    [[I2:%.*]] = insertvalue { { i32, i32 } } undef, i32 [[I0]], 0, 0
65 ; CHECK-NEXT:    [[I3:%.*]] = insertvalue { { i32, i32 } } [[I2]], i32 [[I1]], 0, 1
66 ; CHECK-NEXT:    ret { { i32, i32 } } [[I3]]
68   %i0 = extractvalue {{ i32, i32 }} %srcagg, 0, 0
69   %i1 = extractvalue {{ i32, i32 }} %srcagg, 0, 1
70   %i2 = insertvalue {{ i32, i32 }} undef, i32 %i0, 0, 0
71   %i3 = insertvalue {{ i32, i32 }} %i2, i32 %i1, 0, 1
72   ret {{ i32, i32 }} %i3
75 ; This is fine, however, all elements are on the same level
76 define { i32, { i32 } } @test4({ i32, { i32 } } %srcagg) {
77 ; CHECK-LABEL: @test4(
78 ; CHECK-NEXT:    ret { i32, { i32 } } [[SRCAGG:%.*]]
80   %i0 = extractvalue { i32, { i32 } } %srcagg, 0
81   %i1 = extractvalue { i32, { i32 } } %srcagg, 1
82   %i2 = insertvalue { i32, { i32 } } undef, i32 %i0, 0
83   %i3 = insertvalue { i32, { i32 } } %i2, { i32 } %i1, 1
84   ret { i32, { i32 } } %i3
87 ; All element of the newly-created aggregate must come from the same base
88 ; aggregate. Here the second element comes from some other origin.
89 define { i32, i32 } @negative_test5({ i32, i32 } %srcagg, i32 %replacement) {
90 ; CHECK-LABEL: @negative_test5(
91 ; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0
92 ; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0
93 ; CHECK-NEXT:    [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 [[REPLACEMENT:%.*]], 1
94 ; CHECK-NEXT:    ret { i32, i32 } [[I3]]
96   %i0 = extractvalue { i32, i32 } %srcagg, 0
97   ; %i1 = extractvalue { i32, i32 } %srcagg, 1
98   %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0
99   %i3 = insertvalue { i32, i32 } %i2, i32 %replacement, 1
100   ret { i32, i32 } %i3
103 ; Here we don't know the value of second element of %otheragg,
104 define { i32, i32 } @negative_test6({ i32, i32 } %srcagg, { i32, i32 } %otheragg) {
105 ; CHECK-LABEL: @negative_test6(
106 ; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0
107 ; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } [[OTHERAGG:%.*]], i32 [[I0]], 0
108 ; CHECK-NEXT:    ret { i32, i32 } [[I2]]
110   %i0 = extractvalue { i32, i32 } %srcagg, 0
111   ; %i1 = extractvalue { i32, i32 } %srcagg, 1
112   %i2 = insertvalue { i32, i32 } %otheragg, i32 %i0, 0
113   ret { i32, i32 } %i2
116 ; All element of the newly-created aggregate must come from the same base
117 ; aggregate. Here different elements come from different base aggregates.
118 define { i32, i32 } @negative_test7({ i32, i32 } %srcagg0, { i32, i32 } %srcagg1) {
119 ; CHECK-LABEL: @negative_test7(
120 ; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG0:%.*]], 0
121 ; CHECK-NEXT:    [[I3:%.*]] = extractvalue { i32, i32 } [[SRCAGG1:%.*]], 1
122 ; CHECK-NEXT:    [[I4:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0
123 ; CHECK-NEXT:    [[I5:%.*]] = insertvalue { i32, i32 } [[I4]], i32 [[I3]], 1
124 ; CHECK-NEXT:    ret { i32, i32 } [[I5]]
126   %i0 = extractvalue { i32, i32 } %srcagg0, 0
127   ; %i1 = extractvalue { i32, i32 } %srcagg0, 1
129   ; %i2 = extractvalue { i32, i32 } %srcagg1, 0
130   %i3 = extractvalue { i32, i32 } %srcagg1, 1
132   %i4 = insertvalue { i32, i32 } undef, i32 %i0, 0
133   %i5 = insertvalue { i32, i32 } %i4, i32 %i3, 1
134   ret { i32, i32 } %i5
137 ; Here the element order is swapped as compared to the base aggregate.
138 define { i32, i32 } @negative_test8({ i32, i32 } %srcagg) {
139 ; CHECK-LABEL: @negative_test8(
140 ; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0
141 ; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, i32 } [[SRCAGG]], 1
142 ; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 1
143 ; CHECK-NEXT:    [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 [[I1]], 0
144 ; CHECK-NEXT:    ret { i32, i32 } [[I3]]
146   %i0 = extractvalue { i32, i32 } %srcagg, 0
147   %i1 = extractvalue { i32, i32 } %srcagg, 1
148   %i2 = insertvalue { i32, i32 } undef, i32 %i0, 1
149   %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 0
150   ret { i32, i32 } %i3
153 ; Here both elements of the new aggregate come from the same element of the old aggregate.
154 define { i32, i32 } @negative_test9({ i32, i32 } %srcagg) {
155 ; CHECK-LABEL: @negative_test9(
156 ; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0
157 ; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0
158 ; CHECK-NEXT:    [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 [[I0]], 1
159 ; CHECK-NEXT:    ret { i32, i32 } [[I3]]
161   %i0 = extractvalue { i32, i32 } %srcagg, 0
162   ; %i1 = extractvalue { i32, i32 } %srcagg, 1
163   %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0
164   %i3 = insertvalue { i32, i32 } %i2, i32 %i0, 1
165   ret { i32, i32 } %i3
168 ; Here the second element of the new aggregate is undef, , so we must keep this as-is, because in %srcagg it might be poison.
169 ; FIXME: defer to noundef attribute on %srcagg
170 define { i32, i32 } @negative_test10({ i32, i32 } %srcagg) {
171 ; CHECK-LABEL: @negative_test10(
172 ; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0
173 ; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0
174 ; CHECK-NEXT:    ret { i32, i32 } [[I2]]
176   %i0 = extractvalue { i32, i32 } %srcagg, 0
177   ; %i1 = extractvalue { i32, i32 } %srcagg, 1
178   %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0
179   ret { i32, i32 } %i2
182 ; Here the second element of the new aggregate is undef, so we must keep this as-is, because in %srcagg it might be poison.
183 ; FIXME: defer to noundef attribute on %srcagg
184 define { i32, i32 } @negative_test11({ i32, i32 } %srcagg) {
185 ; CHECK-LABEL: @negative_test11(
186 ; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0
187 ; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0
188 ; CHECK-NEXT:    [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 undef, 1
189 ; CHECK-NEXT:    ret { i32, i32 } [[I3]]
191   %i0 = extractvalue { i32, i32 } %srcagg, 0
192   ; %i1 = extractvalue { i32, i32 } %srcagg, 1
193   %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0
194   %i3 = insertvalue { i32, i32 } %i2, i32 undef, 1
195   ret { i32, i32 } %i3
198 ; This fold does not care whether or not intermediate instructions have extra uses.
199 define { i32, i32 } @test12({ i32, i32 } %srcagg) {
200 ; CHECK-LABEL: @test12(
201 ; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[SRCAGG:%.*]], 0
202 ; CHECK-NEXT:    call void @usei32(i32 [[I0]])
203 ; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, i32 } [[SRCAGG]], 1
204 ; CHECK-NEXT:    call void @usei32(i32 [[I1]])
205 ; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0
206 ; CHECK-NEXT:    call void @usei32i32agg({ i32, i32 } [[I2]])
207 ; CHECK-NEXT:    ret { i32, i32 } [[SRCAGG]]
209   %i0 = extractvalue { i32, i32 } %srcagg, 0
210   call void @usei32(i32 %i0)
211   %i1 = extractvalue { i32, i32 } %srcagg, 1
212   call void @usei32(i32 %i1)
213   %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0
214   call void @usei32i32agg({ i32, i32 } %i2)
215   %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 1
216   ret { i32, i32 } %i3
219 ; Even though we originally store %i1 into first element, it is later
220 ; overwritten with %i0, so all is fine.
221 define { i32, i32 } @test13({ i32, i32 } %srcagg) {
222 ; CHECK-LABEL: @test13(
223 ; CHECK-NEXT:    ret { i32, i32 } [[SRCAGG:%.*]]
225   %i0 = extractvalue { i32, i32 } %srcagg, 0
226   %i1 = extractvalue { i32, i32 } %srcagg, 1
227   %i2 = insertvalue { i32, i32 } undef, i32 %i1, 0
228   %i3 = insertvalue { i32, i32 } %i2, i32 %i0, 0
229   %i4 = insertvalue { i32, i32 } %i3, i32 %i1, 1
230   ret { i32, i32 } %i4
233 ; The aggregate type must match exactly between the original and recreation.
234 define { i32, i32 } @negative_test14({ i32, i32, i32 } %srcagg) {
235 ; CHECK-LABEL: @negative_test14(
236 ; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32, i32 } [[SRCAGG:%.*]], 0
237 ; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, i32, i32 } [[SRCAGG]], 1
238 ; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0
239 ; CHECK-NEXT:    [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 [[I1]], 1
240 ; CHECK-NEXT:    ret { i32, i32 } [[I3]]
242   %i0 = extractvalue { i32, i32, i32 } %srcagg, 0
243   %i1 = extractvalue { i32, i32, i32 } %srcagg, 1
244   %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0
245   %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 1
246   ret { i32, i32 } %i3
248 define { i32, i32 } @negative_test15({ i32, {i32} } %srcagg) {
249 ; CHECK-LABEL: @negative_test15(
250 ; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, { i32 } } [[SRCAGG:%.*]], 0
251 ; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, { i32 } } [[SRCAGG]], 1, 0
252 ; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0
253 ; CHECK-NEXT:    [[I3:%.*]] = insertvalue { i32, i32 } [[I2]], i32 [[I1]], 1
254 ; CHECK-NEXT:    ret { i32, i32 } [[I3]]
256   %i0 = extractvalue { i32, {i32} } %srcagg, 0
257   %i1 = extractvalue { i32, {i32} } %srcagg, 1, 0
258   %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0
259   %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 1
260   ret { i32, i32 } %i3
263 ; Just because there are predecessors doesn't mean we should look into them.
264 define { i32, i32 } @test16({ i32, i32 } %srcagg) {
265 ; CHECK-LABEL: @test16(
266 ; CHECK-NEXT:  entry:
267 ; CHECK-NEXT:    br label [[END:%.*]]
268 ; CHECK:       end:
269 ; CHECK-NEXT:    ret { i32, i32 } [[SRCAGG:%.*]]
271 entry:
272   br label %end
273 end:
274   %i0 = extractvalue { i32, i32 } %srcagg, 0
275   %i1 = extractvalue { i32, i32 } %srcagg, 1
276   %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0
277   %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 1
278   ret { i32, i32 } %i3
281 ; Again, we should first try to perform local reasoning, without looking to predecessors.
282 define { i32, i32 } @test17({ i32, i32 } %srcagg0, { i32, i32 } %srcagg1, i1 %c) {
283 ; CHECK-LABEL: @test17(
284 ; CHECK-NEXT:  entry:
285 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[INTERMEDIATE:%.*]], label [[END:%.*]]
286 ; CHECK:       intermediate:
287 ; CHECK-NEXT:    br label [[END]]
288 ; CHECK:       end:
289 ; CHECK-NEXT:    [[SRCAGG_PHI:%.*]] = phi { i32, i32 } [ [[SRCAGG0:%.*]], [[ENTRY:%.*]] ], [ [[SRCAGG1:%.*]], [[INTERMEDIATE]] ]
290 ; CHECK-NEXT:    ret { i32, i32 } [[SRCAGG_PHI]]
292 entry:
293   br i1 %c, label %intermediate, label %end
294 intermediate:
295   br label %end
296 end:
297   %srcagg.phi = phi { i32, i32 } [ %srcagg0, %entry ], [ %srcagg1, %intermediate ]
298   %i0 = extractvalue { i32, i32 } %srcagg.phi, 0
299   %i1 = extractvalue { i32, i32 } %srcagg.phi, 1
300   %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0
301   %i3 = insertvalue { i32, i32 } %i2, i32 %i1, 1
302   ret { i32, i32 } %i3
305 ; Like test2 but with a poison base.
306 define [3 x i32] @poison_base([3 x i32] %srcagg) {
307 ; CHECK-LABEL: @poison_base(
308 ; CHECK-NEXT:    ret [3 x i32] [[SRCAGG:%.*]]
310   %i0 = extractvalue [3 x i32] %srcagg, 0
311   %i1 = extractvalue [3 x i32] %srcagg, 1
312   %i2 = extractvalue [3 x i32] %srcagg, 2
313   %i3 = insertvalue [3 x i32] poison, i32 %i0, 0
314   %i4 = insertvalue [3 x i32] %i3, i32 %i1, 1
315   %i5 = insertvalue [3 x i32] %i4, i32 %i2, 2
316   ret [3 x i32] %i5