1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -instcombine < %s | FileCheck %s
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
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
37 ; Right now we don't deal with case where there are more than 2 elements.
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
58 ; Likewise, we only deal with a single-level aggregates.
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
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
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
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
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
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
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
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
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
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
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
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(
267 ; CHECK-NEXT: br label [[END:%.*]]
269 ; CHECK-NEXT: ret { i32, i32 } [[SRCAGG:%.*]]
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
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(
285 ; CHECK-NEXT: br i1 [[C:%.*]], label [[INTERMEDIATE:%.*]], label [[END:%.*]]
286 ; CHECK: intermediate:
287 ; CHECK-NEXT: br label [[END]]
289 ; CHECK-NEXT: [[SRCAGG_PHI:%.*]] = phi { i32, i32 } [ [[SRCAGG0:%.*]], [[ENTRY:%.*]] ], [ [[SRCAGG1:%.*]], [[INTERMEDIATE]] ]
290 ; CHECK-NEXT: ret { i32, i32 } [[SRCAGG_PHI]]
293 br i1 %c, label %intermediate, label %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