xref: /llvm-project/llvm/test/Transforms/InstCombine/merging-multiple-stores-into-successor.ll (revision 10f315dc9c96ec2413881ab55a285e35d80def88)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4target datalayout = "n32"
5
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
13
14define 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 nuw (i8, ptr @arr_2, i64 4), align 4
38; CHECK-NEXT:    store i16 [[I4]], ptr getelementptr inbounds nuw (i8, ptr @arr_4, i64 2), align 2
39; CHECK-NEXT:    store i32 [[I8]], ptr getelementptr inbounds nuw (i8, ptr @arr_3, i64 4), align 4
40; CHECK-NEXT:    ret void
41;
42bb:
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
53
54bb9:                                              ; 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
62
63bb10:                                             ; 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
72
73bb12:                                             ; preds = %bb10, %bb9
74  ret void
75}
76
77define 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]]
89;
90entry:
91  %alloca = alloca half
92  br i1 %cond, label %BB0, label %BB1
93BB0:
94  store half %a, ptr %alloca
95  br label %sink
96BB1:
97  store i16 %b, ptr %alloca
98  br label %sink
99sink:
100  %val = load half, ptr %alloca
101  ret half %val
102}
103
104define 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]]
118;
119entry:
120  %alloca = alloca i64
121  br i1 %cond, label %if, label %else
122if:
123  store i32 %a, ptr %alloca
124  br label %sink
125  else:
126  store i64 %b, ptr %alloca
127  br label %sink
128sink:
129  %val = load i32, ptr %alloca
130  ret i32 %val
131}
132
133define <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]]
147;
148entry:
149  %alloca = alloca i64
150  br i1 %cond, label %if, label %else
151if:
152  store <2 x i32> %a, ptr %alloca
153  br label %sink
154else:
155  store <4 x i32> %b, ptr %alloca
156  br label %sink
157sink:
158  %val = load <4 x i32>, ptr %alloca
159  ret <4 x i32> %val
160}
161
162%struct.half = type { half };
163
164define %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:    br label [[SINK:%.*]]
170; CHECK:       BB1:
171; CHECK-NEXT:    [[TMP0:%.*]] = insertvalue [[STRUCT_HALF:%.*]] poison, half [[B:%.*]], 0
172; CHECK-NEXT:    br label [[SINK]]
173; CHECK:       sink:
174; CHECK-NEXT:    [[VAL1_MERGED:%.*]] = phi [[STRUCT_HALF]] [ [[A:%.*]], [[BB0]] ], [ [[TMP0]], [[BB1]] ]
175; CHECK-NEXT:    ret [[STRUCT_HALF]] [[VAL1_MERGED]]
176;
177entry:
178  %alloca = alloca i64
179  br i1 %cond, label %BB0, label %BB1
180BB0:
181  store %struct.half %a, ptr %alloca
182  br label %sink
183BB1:
184  store half %b, ptr %alloca
185  br label %sink
186sink:
187  %val = load %struct.half, ptr %alloca
188  ret %struct.half %val
189}
190
191%struct.tup = type { half, i32 };
192
193define %struct.tup @multi_elem_struct_no_merge(i1 %cond, %struct.tup %a, half %b) {
194; CHECK-LABEL: @multi_elem_struct_no_merge(
195; CHECK-NEXT:  entry:
196; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca i64, align 8
197; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
198; CHECK:       if:
199; CHECK-NEXT:    store [[STRUCT_TUP:%.*]] [[A:%.*]], ptr [[ALLOCA]], align 4
200; CHECK-NEXT:    br label [[SINK:%.*]]
201; CHECK:       else:
202; CHECK-NEXT:    store half [[B:%.*]], ptr [[ALLOCA]], align 2
203; CHECK-NEXT:    br label [[SINK]]
204; CHECK:       sink:
205; CHECK-NEXT:    [[VAL:%.*]] = load [[STRUCT_TUP]], ptr [[ALLOCA]], align 4
206; CHECK-NEXT:    ret [[STRUCT_TUP]] [[VAL]]
207;
208entry:
209  %alloca = alloca i64
210  br i1 %cond, label %if, label %else
211if:
212  store %struct.tup %a, ptr %alloca
213  br label %sink
214else:
215  store half %b, ptr %alloca
216  br label %sink
217sink:
218  %val = load %struct.tup, ptr %alloca
219  ret %struct.tup %val
220}
221
222define i16 @same_types_diff_align_no_merge(i1 %cond, i16 %a, i16 %b) {
223; CHECK-LABEL: @same_types_diff_align_no_merge(
224; CHECK-NEXT:  entry:
225; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca i16, align 4
226; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
227; CHECK:       BB0:
228; CHECK-NEXT:    store i16 [[A:%.*]], ptr [[ALLOCA]], align 8
229; CHECK-NEXT:    br label [[SINK:%.*]]
230; CHECK:       BB1:
231; CHECK-NEXT:    store i16 [[B:%.*]], ptr [[ALLOCA]], align 4
232; CHECK-NEXT:    br label [[SINK]]
233; CHECK:       sink:
234; CHECK-NEXT:    [[VAL:%.*]] = load i16, ptr [[ALLOCA]], align 2
235; CHECK-NEXT:    ret i16 [[VAL]]
236;
237entry:
238  %alloca = alloca i16, align 4
239  br i1 %cond, label %BB0, label %BB1
240BB0:
241  store i16 %a, ptr %alloca, align 8
242  br label %sink
243BB1:
244  store i16 %b, ptr %alloca, align 4
245  br label %sink
246sink:
247  %val = load i16, ptr %alloca
248  ret i16 %val
249}
250
251define i64 @ptrtoint_merge(i1 %cond, i64 %a, ptr %b) {
252; CHECK-LABEL: @ptrtoint_merge(
253; CHECK-NEXT:  entry:
254; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca ptr, align 8
255; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
256; CHECK:       BB0:
257; CHECK-NEXT:    store i64 [[A:%.*]], ptr [[ALLOCA]], align 4
258; CHECK-NEXT:    br label [[SINK:%.*]]
259; CHECK:       BB1:
260; CHECK-NEXT:    store ptr [[B:%.*]], ptr [[ALLOCA]], align 8
261; CHECK-NEXT:    br label [[SINK]]
262; CHECK:       sink:
263; CHECK-NEXT:    [[VAL:%.*]] = load i64, ptr [[ALLOCA]], align 4
264; CHECK-NEXT:    ret i64 [[VAL]]
265;
266entry:
267  %alloca = alloca ptr
268  br i1 %cond, label %BB0, label %BB1
269BB0:
270  store i64 %a, ptr %alloca
271  br label %sink
272BB1:
273  store ptr %b, ptr %alloca
274  br label %sink
275sink:
276  %val = load i64, ptr %alloca
277  ret i64 %val
278}
279
280define ptr @inttoptr_merge(i1 %cond, i64 %a, ptr %b) {
281; CHECK-LABEL: @inttoptr_merge(
282; CHECK-NEXT:  entry:
283; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
284; CHECK:       BB0:
285; CHECK-NEXT:    [[TMP0:%.*]] = inttoptr i64 [[A:%.*]] to ptr
286; CHECK-NEXT:    br label [[SINK:%.*]]
287; CHECK:       BB1:
288; CHECK-NEXT:    br label [[SINK]]
289; CHECK:       sink:
290; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi ptr [ [[B:%.*]], [[BB1]] ], [ [[TMP0]], [[BB0]] ]
291; CHECK-NEXT:    ret ptr [[STOREMERGE]]
292;
293entry:
294  %alloca = alloca ptr
295  br i1 %cond, label %BB0, label %BB1
296BB0:
297  store i64 %a, ptr %alloca, align 8
298  br label %sink
299BB1:
300  store ptr %b, ptr %alloca, align 8
301  br label %sink
302sink:
303  %val = load ptr, ptr %alloca
304  ret ptr %val
305}
306
307
308define void @pr46688(i1 %cond, i32 %x, i16 %d, ptr %p1, ptr %p2) {
309; CHECK-LABEL: @pr46688(
310; CHECK-NEXT:  entry:
311; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
312; CHECK:       if:
313; CHECK-NEXT:    br label [[EXIT:%.*]]
314; CHECK:       else:
315; CHECK-NEXT:    br label [[EXIT]]
316; CHECK:       exit:
317; CHECK-NEXT:    [[DONV_PN:%.*]] = zext i16 [[D:%.*]] to i32
318; CHECK-NEXT:    [[THR_PN:%.*]] = lshr i32 [[DONV_PN]], [[X:%.*]]
319; CHECK-NEXT:    [[THR1_PN:%.*]] = lshr i32 [[THR_PN]], [[X]]
320; CHECK-NEXT:    [[THR2_PN:%.*]] = lshr i32 [[THR1_PN]], [[X]]
321; CHECK-NEXT:    [[STOREMERGE:%.*]] = lshr i32 [[THR2_PN]], [[X]]
322; CHECK-NEXT:    [[STOREMERGE1:%.*]] = trunc nuw i32 [[STOREMERGE]] to i16
323; CHECK-NEXT:    store i16 [[STOREMERGE1]], ptr [[P1:%.*]], align 2
324; CHECK-NEXT:    store i32 [[STOREMERGE]], ptr [[P2:%.*]], align 4
325; CHECK-NEXT:    ret void
326;
327entry:
328  br i1 %cond, label %if, label %else
329
330if:
331  %conv = zext i16 %d to i32
332  %shr = lshr i32 %conv, %x
333  %shr1 = lshr i32 %shr, %x
334  %shr2 = lshr i32 %shr1, %x
335  %shr3 = lshr i32 %shr2, %x
336  %conv4 = trunc i32 %shr3 to i16
337  store i16 %conv4, ptr %p1, align 2
338  %conv5 = and i32 %shr3, 65535
339  store i32 %conv5, ptr %p2, align 4
340  br label %exit
341
342else:
343  %donv = zext i16 %d to i32
344  %thr = lshr i32 %donv, %x
345  %thr1 = lshr i32 %thr, %x
346  %thr2 = lshr i32 %thr1, %x
347  %thr3 = lshr i32 %thr2, %x
348  %donv4 = trunc i32 %thr3 to i16
349  store i16 %donv4, ptr %p1, align 2
350  store i32 %thr3, ptr %p2, align 4
351  br label %exit
352
353exit:
354  ret void
355}
356