[AArch64][NFC] NFC for const vector as Instruction operand (#116790)
[llvm-project.git] / llvm / test / Transforms / InstCombine / merging-multiple-stores-into-successor.ll
blobfbf58d47a32d20289f23c2d4f501798b07fe82b0
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 target datalayout = "n32"
6 @var_7 = external global i8, align 1
7 @var_1 = external global i32, align 4
8 @var_0 = external global i16, align 2
9 @var_5 = external global i64, align 8
10 @arr_2 = external global [0 x i32], align 4
11 @arr_4 = external global [0 x i16], align 2
12 @arr_3 = external global [8 x i32], align 16
14 define void @_Z4testv() {
15 ; CHECK-LABEL: @_Z4testv(
16 ; CHECK-NEXT:  bb:
17 ; CHECK-NEXT:    [[I:%.*]] = load i8, ptr @var_7, align 1
18 ; CHECK-NEXT:    [[I1:%.*]] = icmp eq i8 [[I]], -1
19 ; CHECK-NEXT:    [[I4:%.*]] = load i16, ptr @var_0, align 2
20 ; CHECK-NEXT:    br i1 [[I1]], label [[BB10:%.*]], label [[BB9:%.*]]
21 ; CHECK:       bb9:
22 ; CHECK-NEXT:    br label [[BB12:%.*]]
23 ; CHECK:       bb10:
24 ; CHECK-NEXT:    [[I2:%.*]] = load i32, ptr @var_1, align 4
25 ; CHECK-NEXT:    [[I3:%.*]] = icmp eq i32 [[I2]], 0
26 ; CHECK-NEXT:    [[I6:%.*]] = load i64, ptr @var_5, align 8
27 ; CHECK-NEXT:    [[I5:%.*]] = sext i16 [[I4]] to i64
28 ; CHECK-NEXT:    [[I7:%.*]] = select i1 [[I3]], i64 [[I6]], i64 [[I5]]
29 ; CHECK-NEXT:    [[I11:%.*]] = trunc i64 [[I7]] to i32
30 ; CHECK-NEXT:    br label [[BB12]]
31 ; CHECK:       bb12:
32 ; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ 1, [[BB9]] ], [ [[I11]], [[BB10]] ]
33 ; CHECK-NEXT:    store i32 [[STOREMERGE]], ptr @arr_2, align 4
34 ; CHECK-NEXT:    store i16 [[I4]], ptr @arr_4, align 2
35 ; CHECK-NEXT:    [[I8:%.*]] = sext i16 [[I4]] to i32
36 ; CHECK-NEXT:    store i32 [[I8]], ptr @arr_3, align 4
37 ; CHECK-NEXT:    store i32 [[STOREMERGE]], ptr getelementptr inbounds (i8, ptr @arr_2, i64 4), align 4
38 ; CHECK-NEXT:    store i16 [[I4]], ptr getelementptr inbounds (i8, ptr @arr_4, i64 2), align 2
39 ; CHECK-NEXT:    store i32 [[I8]], ptr getelementptr inbounds (i8, ptr @arr_3, i64 4), align 4
40 ; CHECK-NEXT:    ret void
42 bb:
43   %i = load i8, ptr @var_7, align 1
44   %i1 = icmp eq i8 %i, -1
45   %i2 = load i32, ptr @var_1, align 4
46   %i3 = icmp eq i32 %i2, 0
47   %i4 = load i16, ptr @var_0, align 2
48   %i5 = sext i16 %i4 to i64
49   %i6 = load i64, ptr @var_5, align 8
50   %i7 = select i1 %i3, i64 %i6, i64 %i5
51   %i8 = sext i16 %i4 to i32
52   br i1 %i1, label %bb10, label %bb9
54 bb9:                                              ; preds = %bb
55   store i32 1, ptr @arr_2, align 4
56   store i16 %i4, ptr @arr_4, align 2
57   store i32 %i8, ptr @arr_3, align 4
58   store i32 1, ptr getelementptr inbounds ([0 x i32], ptr @arr_2, i64 0, i64 1), align 4
59   store i16 %i4, ptr getelementptr inbounds ([0 x i16], ptr @arr_4, i64 0, i64 1), align 2
60   store i32 %i8, ptr getelementptr inbounds ([8 x i32], ptr @arr_3, i64 0, i64 1), align 4
61   br label %bb12
63 bb10:                                             ; preds = %bb
64   %i11 = trunc i64 %i7 to i32
65   store i32 %i11, ptr @arr_2, align 4
66   store i16 %i4, ptr @arr_4, align 2
67   store i32 %i8, ptr @arr_3, align 4
68   store i32 %i11, ptr getelementptr inbounds ([0 x i32], ptr @arr_2, i64 0, i64 1), align 4
69   store i16 %i4, ptr getelementptr inbounds ([0 x i16], ptr @arr_4, i64 0, i64 1), align 2
70   store i32 %i8, ptr getelementptr inbounds ([8 x i32], ptr @arr_3, i64 0, i64 1), align 4
71   br label %bb12
73 bb12:                                             ; preds = %bb10, %bb9
74   ret void
77 define half @diff_types_same_width_merge(i1 %cond, half %a, i16 %b) {
78 ; CHECK-LABEL: @diff_types_same_width_merge(
79 ; CHECK-NEXT:  entry:
80 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
81 ; CHECK:       BB0:
82 ; CHECK-NEXT:    br label [[SINK:%.*]]
83 ; CHECK:       BB1:
84 ; CHECK-NEXT:    [[TMP0:%.*]] = bitcast i16 [[B:%.*]] to half
85 ; CHECK-NEXT:    br label [[SINK]]
86 ; CHECK:       sink:
87 ; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi half [ [[TMP0]], [[BB1]] ], [ [[A:%.*]], [[BB0]] ]
88 ; CHECK-NEXT:    ret half [[STOREMERGE]]
90 entry:
91   %alloca = alloca half
92   br i1 %cond, label %BB0, label %BB1
93 BB0:
94   store half %a, ptr %alloca
95   br label %sink
96 BB1:
97   store i16 %b, ptr %alloca
98   br label %sink
99 sink:
100   %val = load half, ptr %alloca
101   ret half %val
104 define i32 @diff_types_diff_width_no_merge(i1 %cond, i32 %a, i64 %b) {
105 ; CHECK-LABEL: @diff_types_diff_width_no_merge(
106 ; CHECK-NEXT:  entry:
107 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca i64, align 8
108 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
109 ; CHECK:       if:
110 ; CHECK-NEXT:    store i32 [[A:%.*]], ptr [[ALLOCA]], align 4
111 ; CHECK-NEXT:    br label [[SINK:%.*]]
112 ; CHECK:       else:
113 ; CHECK-NEXT:    store i64 [[B:%.*]], ptr [[ALLOCA]], align 4
114 ; CHECK-NEXT:    br label [[SINK]]
115 ; CHECK:       sink:
116 ; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ALLOCA]], align 4
117 ; CHECK-NEXT:    ret i32 [[VAL]]
119 entry:
120   %alloca = alloca i64
121   br i1 %cond, label %if, label %else
123   store i32 %a, ptr %alloca
124   br label %sink
125   else:
126   store i64 %b, ptr %alloca
127   br label %sink
128 sink:
129   %val = load i32, ptr %alloca
130   ret i32 %val
133 define <4 x i32> @vec_no_merge(i1 %cond, <2 x i32> %a, <4 x i32> %b) {
134 ; CHECK-LABEL: @vec_no_merge(
135 ; CHECK-NEXT:  entry:
136 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca i64, align 8
137 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
138 ; CHECK:       if:
139 ; CHECK-NEXT:    store <2 x i32> [[A:%.*]], ptr [[ALLOCA]], align 8
140 ; CHECK-NEXT:    br label [[SINK:%.*]]
141 ; CHECK:       else:
142 ; CHECK-NEXT:    store <4 x i32> [[B:%.*]], ptr [[ALLOCA]], align 16
143 ; CHECK-NEXT:    br label [[SINK]]
144 ; CHECK:       sink:
145 ; CHECK-NEXT:    [[VAL:%.*]] = load <4 x i32>, ptr [[ALLOCA]], align 16
146 ; CHECK-NEXT:    ret <4 x i32> [[VAL]]
148 entry:
149   %alloca = alloca i64
150   br i1 %cond, label %if, label %else
152   store <2 x i32> %a, ptr %alloca
153   br label %sink
154 else:
155   store <4 x i32> %b, ptr %alloca
156   br label %sink
157 sink:
158   %val = load <4 x i32>, ptr %alloca
159   ret <4 x i32> %val
162 %struct.half = type { half };
164 define %struct.half @one_elem_struct_merge(i1 %cond, %struct.half %a, half %b) {
165 ; CHECK-LABEL: @one_elem_struct_merge(
166 ; CHECK-NEXT:  entry:
167 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
168 ; CHECK:       BB0:
169 ; CHECK-NEXT:    [[TMP0:%.*]] = extractvalue [[STRUCT_HALF:%.*]] [[A:%.*]], 0
170 ; CHECK-NEXT:    br label [[SINK:%.*]]
171 ; CHECK:       BB1:
172 ; CHECK-NEXT:    br label [[SINK]]
173 ; CHECK:       sink:
174 ; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi half [ [[TMP0]], [[BB0]] ], [ [[B:%.*]], [[BB1]] ]
175 ; CHECK-NEXT:    [[VAL1:%.*]] = insertvalue [[STRUCT_HALF]] poison, half [[STOREMERGE]], 0
176 ; CHECK-NEXT:    ret [[STRUCT_HALF]] [[VAL1]]
178 entry:
179   %alloca = alloca i64
180   br i1 %cond, label %BB0, label %BB1
181 BB0:
182   store %struct.half %a, ptr %alloca
183   br label %sink
184 BB1:
185   store half %b, ptr %alloca
186   br label %sink
187 sink:
188   %val = load %struct.half, ptr %alloca
189   ret %struct.half %val
192 %struct.tup = type { half, i32 };
194 define %struct.tup @multi_elem_struct_no_merge(i1 %cond, %struct.tup %a, half %b) {
195 ; CHECK-LABEL: @multi_elem_struct_no_merge(
196 ; CHECK-NEXT:  entry:
197 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca i64, align 8
198 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
199 ; CHECK:       if:
200 ; CHECK-NEXT:    store [[STRUCT_TUP:%.*]] [[A:%.*]], ptr [[ALLOCA]], align 4
201 ; CHECK-NEXT:    br label [[SINK:%.*]]
202 ; CHECK:       else:
203 ; CHECK-NEXT:    store half [[B:%.*]], ptr [[ALLOCA]], align 2
204 ; CHECK-NEXT:    br label [[SINK]]
205 ; CHECK:       sink:
206 ; CHECK-NEXT:    [[VAL:%.*]] = load [[STRUCT_TUP]], ptr [[ALLOCA]], align 4
207 ; CHECK-NEXT:    ret [[STRUCT_TUP]] [[VAL]]
209 entry:
210   %alloca = alloca i64
211   br i1 %cond, label %if, label %else
213   store %struct.tup %a, ptr %alloca
214   br label %sink
215 else:
216   store half %b, ptr %alloca
217   br label %sink
218 sink:
219   %val = load %struct.tup, ptr %alloca
220   ret %struct.tup %val
223 define i16 @same_types_diff_align_no_merge(i1 %cond, i16 %a, i16 %b) {
224 ; CHECK-LABEL: @same_types_diff_align_no_merge(
225 ; CHECK-NEXT:  entry:
226 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca i16, align 4
227 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
228 ; CHECK:       BB0:
229 ; CHECK-NEXT:    store i16 [[A:%.*]], ptr [[ALLOCA]], align 8
230 ; CHECK-NEXT:    br label [[SINK:%.*]]
231 ; CHECK:       BB1:
232 ; CHECK-NEXT:    store i16 [[B:%.*]], ptr [[ALLOCA]], align 4
233 ; CHECK-NEXT:    br label [[SINK]]
234 ; CHECK:       sink:
235 ; CHECK-NEXT:    [[VAL:%.*]] = load i16, ptr [[ALLOCA]], align 2
236 ; CHECK-NEXT:    ret i16 [[VAL]]
238 entry:
239   %alloca = alloca i16, align 4
240   br i1 %cond, label %BB0, label %BB1
241 BB0:
242   store i16 %a, ptr %alloca, align 8
243   br label %sink
244 BB1:
245   store i16 %b, ptr %alloca, align 4
246   br label %sink
247 sink:
248   %val = load i16, ptr %alloca
249   ret i16 %val
252 define i64 @ptrtoint_merge(i1 %cond, i64 %a, ptr %b) {
253 ; CHECK-LABEL: @ptrtoint_merge(
254 ; CHECK-NEXT:  entry:
255 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca ptr, align 8
256 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
257 ; CHECK:       BB0:
258 ; CHECK-NEXT:    store i64 [[A:%.*]], ptr [[ALLOCA]], align 4
259 ; CHECK-NEXT:    br label [[SINK:%.*]]
260 ; CHECK:       BB1:
261 ; CHECK-NEXT:    store ptr [[B:%.*]], ptr [[ALLOCA]], align 8
262 ; CHECK-NEXT:    br label [[SINK]]
263 ; CHECK:       sink:
264 ; CHECK-NEXT:    [[VAL:%.*]] = load i64, ptr [[ALLOCA]], align 4
265 ; CHECK-NEXT:    ret i64 [[VAL]]
267 entry:
268   %alloca = alloca ptr
269   br i1 %cond, label %BB0, label %BB1
270 BB0:
271   store i64 %a, ptr %alloca
272   br label %sink
273 BB1:
274   store ptr %b, ptr %alloca
275   br label %sink
276 sink:
277   %val = load i64, ptr %alloca
278   ret i64 %val
281 define ptr @inttoptr_merge(i1 %cond, i64 %a, ptr %b) {
282 ; CHECK-LABEL: @inttoptr_merge(
283 ; CHECK-NEXT:  entry:
284 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
285 ; CHECK:       BB0:
286 ; CHECK-NEXT:    [[TMP0:%.*]] = inttoptr i64 [[A:%.*]] to ptr
287 ; CHECK-NEXT:    br label [[SINK:%.*]]
288 ; CHECK:       BB1:
289 ; CHECK-NEXT:    br label [[SINK]]
290 ; CHECK:       sink:
291 ; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi ptr [ [[B:%.*]], [[BB1]] ], [ [[TMP0]], [[BB0]] ]
292 ; CHECK-NEXT:    ret ptr [[STOREMERGE]]
294 entry:
295   %alloca = alloca ptr
296   br i1 %cond, label %BB0, label %BB1
297 BB0:
298   store i64 %a, ptr %alloca, align 8
299   br label %sink
300 BB1:
301   store ptr %b, ptr %alloca, align 8
302   br label %sink
303 sink:
304   %val = load ptr, ptr %alloca
305   ret ptr %val
309 define void @pr46688(i1 %cond, i32 %x, i16 %d, ptr %p1, ptr %p2) {
310 ; CHECK-LABEL: @pr46688(
311 ; CHECK-NEXT:  entry:
312 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
313 ; CHECK:       if:
314 ; CHECK-NEXT:    br label [[EXIT:%.*]]
315 ; CHECK:       else:
316 ; CHECK-NEXT:    br label [[EXIT]]
317 ; CHECK:       exit:
318 ; CHECK-NEXT:    [[DONV_PN:%.*]] = zext i16 [[D:%.*]] to i32
319 ; CHECK-NEXT:    [[THR_PN:%.*]] = lshr i32 [[DONV_PN]], [[X:%.*]]
320 ; CHECK-NEXT:    [[THR1_PN:%.*]] = lshr i32 [[THR_PN]], [[X]]
321 ; CHECK-NEXT:    [[THR2_PN:%.*]] = lshr i32 [[THR1_PN]], [[X]]
322 ; CHECK-NEXT:    [[STOREMERGE:%.*]] = lshr i32 [[THR2_PN]], [[X]]
323 ; CHECK-NEXT:    [[STOREMERGE1:%.*]] = trunc nuw i32 [[STOREMERGE]] to i16
324 ; CHECK-NEXT:    store i16 [[STOREMERGE1]], ptr [[P1:%.*]], align 2
325 ; CHECK-NEXT:    store i32 [[STOREMERGE]], ptr [[P2:%.*]], align 4
326 ; CHECK-NEXT:    ret void
328 entry:
329   br i1 %cond, label %if, label %else
332   %conv = zext i16 %d to i32
333   %shr = lshr i32 %conv, %x
334   %shr1 = lshr i32 %shr, %x
335   %shr2 = lshr i32 %shr1, %x
336   %shr3 = lshr i32 %shr2, %x
337   %conv4 = trunc i32 %shr3 to i16
338   store i16 %conv4, ptr %p1, align 2
339   %conv5 = and i32 %shr3, 65535
340   store i32 %conv5, ptr %p2, align 4
341   br label %exit
343 else:
344   %donv = zext i16 %d to i32
345   %thr = lshr i32 %donv, %x
346   %thr1 = lshr i32 %thr, %x
347   %thr2 = lshr i32 %thr1, %x
348   %thr3 = lshr i32 %thr2, %x
349   %donv4 = trunc i32 %thr3 to i16
350   store i16 %donv4, ptr %p1, align 2
351   store i32 %thr3, ptr %p2, align 4
352   br label %exit
354 exit:
355   ret void