1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -loop-vectorize -force-vector-width=2 -S %s | FileCheck %s
3
4@src = external global [32 x i16], align 1
5@dst = external global [32 x i16], align 1
6
7; The load in the loop does not need predication, because the accessed memory
8; is de-referenceable for all loop iterations.
9define void @single_incoming_phi_no_blend_mask(i64 %a, i64 %b) {
10; CHECK-LABEL: @single_incoming_phi_no_blend_mask(
11; CHECK-NEXT:  entry:
12; CHECK-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
13; CHECK:       vector.ph:
14; CHECK-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[A:%.*]], i32 0
15; CHECK-NEXT:    [[BROADCAST_SPLAT:%.*]] = shufflevector <2 x i64> [[BROADCAST_SPLATINSERT]], <2 x i64> poison, <2 x i32> zeroinitializer
16; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
17; CHECK:       vector.body:
18; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
19; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <2 x i64> [ <i64 0, i64 1>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]
20; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
21; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[INDEX]], 1
22; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[INDEX]] to i16
23; CHECK-NEXT:    [[TMP3:%.*]] = add i16 [[TMP2]], 0
24; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [32 x i16], [32 x i16]* @src, i16 0, i16 [[TMP3]]
25; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds i16, i16* [[TMP4]], i32 0
26; CHECK-NEXT:    [[TMP6:%.*]] = bitcast i16* [[TMP5]] to <2 x i16>*
27; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i16>, <2 x i16>* [[TMP6]], align 1
28; CHECK-NEXT:    [[TMP7:%.*]] = icmp sgt <2 x i64> [[VEC_IND]], [[BROADCAST_SPLAT]]
29; CHECK-NEXT:    [[TMP8:%.*]] = xor <2 x i1> [[TMP7]], <i1 true, i1 true>
30; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP7]], <2 x i16> <i16 1, i16 1>, <2 x i16> [[WIDE_LOAD]]
31; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds [32 x i16], [32 x i16]* @dst, i16 0, i64 [[TMP0]]
32; CHECK-NEXT:    [[TMP10:%.*]] = getelementptr inbounds i16, i16* [[TMP9]], i32 0
33; CHECK-NEXT:    [[TMP11:%.*]] = bitcast i16* [[TMP10]] to <2 x i16>*
34; CHECK-NEXT:    store <2 x i16> [[PREDPHI]], <2 x i16>* [[TMP11]], align 2
35; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
36; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <2 x i64> [[VEC_IND]], <i64 2, i64 2>
37; CHECK-NEXT:    [[TMP12:%.*]] = icmp eq i64 [[INDEX_NEXT]], 32
38; CHECK-NEXT:    br i1 [[TMP12]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], [[LOOP0:!llvm.loop !.*]]
39; CHECK:       middle.block:
40; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i64 32, 32
41; CHECK-NEXT:    br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]]
42; CHECK:       scalar.ph:
43; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 32, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
44; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
45; CHECK:       loop.header:
46; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
47; CHECK-NEXT:    [[IV_TRUNC:%.*]] = trunc i64 [[IV]] to i16
48; CHECK-NEXT:    br label [[LOOP_COND:%.*]]
49; CHECK:       loop.cond:
50; CHECK-NEXT:    [[BLEND:%.*]] = phi i16 [ [[IV_TRUNC]], [[LOOP_HEADER]] ]
51; CHECK-NEXT:    [[SRC_PTR:%.*]] = getelementptr inbounds [32 x i16], [32 x i16]* @src, i16 0, i16 [[BLEND]]
52; CHECK-NEXT:    [[LV:%.*]] = load i16, i16* [[SRC_PTR]], align 1
53; CHECK-NEXT:    [[CMP_B:%.*]] = icmp sgt i64 [[IV]], [[A]]
54; CHECK-NEXT:    br i1 [[CMP_B]], label [[LOOP_NEXT:%.*]], label [[LOOP_LATCH]]
55; CHECK:       loop.next:
56; CHECK-NEXT:    br label [[LOOP_LATCH]]
57; CHECK:       loop.latch:
58; CHECK-NEXT:    [[RES:%.*]] = phi i16 [ [[LV]], [[LOOP_COND]] ], [ 1, [[LOOP_NEXT]] ]
59; CHECK-NEXT:    [[DST_PTR:%.*]] = getelementptr inbounds [32 x i16], [32 x i16]* @dst, i16 0, i64 [[IV]]
60; CHECK-NEXT:    store i16 [[RES]], i16* [[DST_PTR]], align 2
61; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
62; CHECK-NEXT:    [[CMP439:%.*]] = icmp ult i64 [[IV]], 31
63; CHECK-NEXT:    br i1 [[CMP439]], label [[LOOP_HEADER]], label [[EXIT]], [[LOOP2:!llvm.loop !.*]]
64; CHECK:       exit:
65; CHECK-NEXT:    ret void
66;
67entry:
68  br label %loop.header
69
70loop.header:
71  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
72  %iv.trunc = trunc i64 %iv to i16
73  br label %loop.cond
74
75loop.cond:
76  %blend = phi i16 [ %iv.trunc, %loop.header ]
77  %src.ptr = getelementptr inbounds [32 x i16], [32 x i16]* @src, i16 0, i16 %blend
78  %lv = load i16, i16* %src.ptr, align 1
79  %cmp.b = icmp sgt i64 %iv, %a
80  br i1 %cmp.b, label %loop.next, label %loop.latch
81
82loop.next:
83  br label %loop.latch
84
85loop.latch:
86  %res = phi i16 [ %lv, %loop.cond ], [ 1, %loop.next ]
87  %dst.ptr = getelementptr inbounds [32 x i16], [32 x i16]* @dst, i16 0, i64 %iv
88  store i16 %res, i16* %dst.ptr
89  %iv.next = add nuw nsw i64 %iv, 1
90  %cmp439 = icmp ult i64 %iv, 31
91  br i1 %cmp439, label %loop.header, label %exit
92
93exit:
94  ret void
95}
96
97; The load in the loop does not need predication, because the accessed memory
98; is de-referenceable for all loop iterations.
99define void @single_incoming_phi_with_blend_mask(i64 %a, i64 %b) {
100; CHECK-LABEL: @single_incoming_phi_with_blend_mask(
101; CHECK-NEXT:  entry:
102; CHECK-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
103; CHECK:       vector.ph:
104; CHECK-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[A:%.*]], i32 0
105; CHECK-NEXT:    [[BROADCAST_SPLAT:%.*]] = shufflevector <2 x i64> [[BROADCAST_SPLATINSERT]], <2 x i64> poison, <2 x i32> zeroinitializer
106; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
107; CHECK:       vector.body:
108; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
109; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <2 x i64> [ <i64 0, i64 1>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]
110; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
111; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[INDEX]], 1
112; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[INDEX]] to i16
113; CHECK-NEXT:    [[TMP3:%.*]] = add i16 [[TMP2]], 0
114; CHECK-NEXT:    [[TMP4:%.*]] = icmp ugt <2 x i64> [[VEC_IND]], [[BROADCAST_SPLAT]]
115; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr [32 x i16], [32 x i16]* @src, i16 0, i16 [[TMP3]]
116; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr i16, i16* [[TMP5]], i32 0
117; CHECK-NEXT:    [[TMP7:%.*]] = bitcast i16* [[TMP6]] to <2 x i16>*
118; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i16>, <2 x i16>* [[TMP7]], align 1
119; CHECK-NEXT:    [[TMP8:%.*]] = icmp sgt <2 x i64> [[VEC_IND]], [[BROADCAST_SPLAT]]
120; CHECK-NEXT:    [[TMP9:%.*]] = xor <2 x i1> [[TMP4]], <i1 true, i1 true>
121; CHECK-NEXT:    [[TMP10:%.*]] = xor <2 x i1> [[TMP8]], <i1 true, i1 true>
122; CHECK-NEXT:    [[TMP11:%.*]] = select <2 x i1> [[TMP4]], <2 x i1> [[TMP10]], <2 x i1> zeroinitializer
123; CHECK-NEXT:    [[TMP12:%.*]] = select <2 x i1> [[TMP4]], <2 x i1> [[TMP8]], <2 x i1> zeroinitializer
124; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP11]], <2 x i16> [[WIDE_LOAD]], <2 x i16> zeroinitializer
125; CHECK-NEXT:    [[PREDPHI1:%.*]] = select <2 x i1> [[TMP12]], <2 x i16> <i16 1, i16 1>, <2 x i16> [[PREDPHI]]
126; CHECK-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [32 x i16], [32 x i16]* @dst, i16 0, i64 [[TMP0]]
127; CHECK-NEXT:    [[TMP14:%.*]] = getelementptr inbounds i16, i16* [[TMP13]], i32 0
128; CHECK-NEXT:    [[TMP15:%.*]] = bitcast i16* [[TMP14]] to <2 x i16>*
129; CHECK-NEXT:    store <2 x i16> [[PREDPHI1]], <2 x i16>* [[TMP15]], align 2
130; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
131; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <2 x i64> [[VEC_IND]], <i64 2, i64 2>
132; CHECK-NEXT:    [[TMP16:%.*]] = icmp eq i64 [[INDEX_NEXT]], 32
133; CHECK-NEXT:    br i1 [[TMP16]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], [[LOOP4:!llvm.loop !.*]]
134; CHECK:       middle.block:
135; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i64 32, 32
136; CHECK-NEXT:    br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]]
137;
138entry:
139  br label %loop.header
140
141loop.header:
142  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
143  %iv.trunc = trunc i64 %iv to i16
144  %cmp.a = icmp ugt i64 %iv, %a
145  br i1 %cmp.a, label %loop.cond, label %loop.latch
146
147loop.cond:
148  %blend = phi i16 [ %iv.trunc, %loop.header ]
149  %src.ptr = getelementptr inbounds [32 x i16], [32 x i16]* @src, i16 0, i16 %blend
150  %lv = load i16, i16* %src.ptr, align 1
151  %cmp.b = icmp sgt i64 %iv, %a
152  br i1 %cmp.b, label %loop.next, label %loop.latch
153
154loop.next:
155  br label %loop.latch
156
157loop.latch:
158  %res = phi i16 [ 0, %loop.header ], [ %lv, %loop.cond ], [ 1, %loop.next ]
159  %dst.ptr = getelementptr inbounds [32 x i16], [32 x i16]* @dst, i16 0, i64 %iv
160  store i16 %res, i16* %dst.ptr
161  %iv.next = add nuw nsw i64 %iv, 1
162  %cmp439 = icmp ult i64 %iv, 31
163  br i1 %cmp439, label %loop.header, label %exit
164
165exit:
166  ret void
167}
168
169define void @multiple_incoming_phi_with_blend_mask(i64 %a, i16* noalias %dst) {
170; CHECK-LABEL: @multiple_incoming_phi_with_blend_mask(
171; CHECK-NEXT:  entry:
172; CHECK-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
173; CHECK:       vector.ph:
174; CHECK-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[A:%.*]], i32 0
175; CHECK-NEXT:    [[BROADCAST_SPLAT:%.*]] = shufflevector <2 x i64> [[BROADCAST_SPLATINSERT]], <2 x i64> poison, <2 x i32> zeroinitializer
176; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
177; CHECK:       vector.body:
178; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
179; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <2 x i64> [ <i64 0, i64 1>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]
180; CHECK-NEXT:    [[VEC_IND1:%.*]] = phi <2 x i16> [ <i16 0, i16 1>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT2:%.*]], [[VECTOR_BODY]] ]
181; CHECK-NEXT:    [[VEC_IND3:%.*]] = phi <2 x i16> [ <i16 0, i16 1>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT4:%.*]], [[VECTOR_BODY]] ]
182; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
183; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[INDEX]], 1
184; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt <2 x i64> [[VEC_IND]], [[BROADCAST_SPLAT]]
185; CHECK-NEXT:    [[TMP3:%.*]] = xor <2 x i1> [[TMP2]], <i1 true, i1 true>
186; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP2]], <2 x i16> [[VEC_IND3]], <2 x i16> [[VEC_IND1]]
187; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <2 x i16> [[PREDPHI]], i32 0
188; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [32 x i16], [32 x i16]* @src, i16 0, i16 [[TMP4]]
189; CHECK-NEXT:    [[TMP6:%.*]] = extractelement <2 x i16> [[PREDPHI]], i32 1
190; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds [32 x i16], [32 x i16]* @src, i16 0, i16 [[TMP6]]
191; CHECK-NEXT:    [[TMP8:%.*]] = load i16, i16* [[TMP5]], align 1
192; CHECK-NEXT:    [[TMP9:%.*]] = load i16, i16* [[TMP7]], align 1
193; CHECK-NEXT:    [[INS1:%.+]] = insertelement <2 x i16> poison, i16 [[TMP8]], i32 0
194; CHECK-NEXT:    [[INS2:%.+]] = insertelement <2 x i16> [[INS1]], i16 [[TMP9]], i32 1
195; CHECK-NEXT:    [[DST0:%.+]] = getelementptr inbounds i16, i16* %dst, i64 [[TMP0]]
196; CHECK-NEXT:    [[DST1:%.+]] = getelementptr inbounds i16, i16* [[DST0]], i32 0
197; CHECK-NEXT:    [[DST1_BC:%.+]] = bitcast i16* [[DST1]] to <2 x i16>*
198; CHECK-NEXT:    store <2 x i16> [[INS2]], <2 x i16>* [[DST1_BC]], align 2
199; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
200; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <2 x i64> [[VEC_IND]], <i64 2, i64 2>
201; CHECK-NEXT:    [[VEC_IND_NEXT2]] = add <2 x i16> [[VEC_IND1]], <i16 2, i16 2>
202; CHECK-NEXT:    [[VEC_IND_NEXT4]] = add <2 x i16> [[VEC_IND3]], <i16 2, i16 2>
203; CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], 32
204; CHECK-NEXT:    br i1 [[TMP10]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], [[LOOP6:!llvm.loop !.*]]
205; CHECK:       middle.block:
206; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i64 32, 32
207; CHECK-NEXT:    br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]]
208;
209entry:
210  br label %loop.header
211
212loop.header:
213  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
214  %iv.trunc = trunc i64 %iv to i16
215  %iv.trunc.2 = trunc i64 %iv to i16
216  %cmp.a = icmp ugt i64 %iv, %a
217  br i1 %cmp.a, label %loop.next, label %loop.latch
218
219loop.next:
220  br label %loop.latch
221
222loop.latch:
223  %blend = phi i16 [ %iv.trunc, %loop.header ], [ %iv.trunc.2, %loop.next ]
224  %src.ptr = getelementptr inbounds [32 x i16], [32 x i16]* @src, i16 0, i16 %blend
225  %lv = load i16, i16* %src.ptr, align 1
226  %dst.ptr = getelementptr inbounds i16, i16* %dst, i64 %iv
227  store i16 %lv, i16* %dst.ptr
228  %iv.next = add nuw nsw i64 %iv, 1
229  %cmp439 = icmp ult i64 %iv, 31
230  br i1 %cmp439, label %loop.header, label %exit
231
232exit:
233  ret void
234}
235
236; The load in the loop needs predication, because the accessed memory is not
237; de-referencable for all iterations of the loop.
238define void @single_incoming_needs_predication(i64 %a, i64 %b) {
239; CHECK-LABEL: @single_incoming_needs_predication(
240; CHECK-NEXT:  entry:
241; CHECK-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
242; CHECK:       vector.ph:
243; CHECK-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[A:%.*]], i32 0
244; CHECK-NEXT:    [[BROADCAST_SPLAT:%.*]] = shufflevector <2 x i64> [[BROADCAST_SPLATINSERT]], <2 x i64> poison, <2 x i32> zeroinitializer
245; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
246; CHECK:       vector.body:
247; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_LOAD_CONTINUE4:%.*]] ]
248; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <2 x i64> [ <i64 0, i64 1>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[PRED_LOAD_CONTINUE4]] ]
249; CHECK-NEXT:    [[VEC_IND1:%.*]] = phi <2 x i16> [ <i16 0, i16 1>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT2:%.*]], [[PRED_LOAD_CONTINUE4]] ]
250; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
251; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[INDEX]], 1
252; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt <2 x i64> [[VEC_IND]], [[BROADCAST_SPLAT]]
253; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <2 x i1> [[TMP2]], i32 0
254; CHECK-NEXT:    br i1 [[TMP3]], label [[PRED_LOAD_IF:%.*]], label [[PRED_LOAD_CONTINUE:%.*]]
255; CHECK:       pred.load.if:
256; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <2 x i16> [[VEC_IND1]], i32 0
257; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [32 x i16], [32 x i16]* @src, i16 0, i16 [[TMP4]]
258; CHECK-NEXT:    [[TMP6:%.*]] = load i16, i16* [[TMP5]], align 1
259; CHECK-NEXT:    [[TMP7:%.*]] = insertelement <2 x i16> poison, i16 [[TMP6]], i32 0
260; CHECK-NEXT:    br label [[PRED_LOAD_CONTINUE]]
261; CHECK:       pred.load.continue:
262; CHECK-NEXT:    [[TMP8:%.*]] = phi <2 x i16> [ poison, [[VECTOR_BODY]] ], [ [[TMP7]], [[PRED_LOAD_IF]] ]
263; CHECK-NEXT:    [[TMP9:%.*]] = extractelement <2 x i1> [[TMP2]], i32 1
264; CHECK-NEXT:    br i1 [[TMP9]], label [[PRED_LOAD_IF3:%.*]], label [[PRED_LOAD_CONTINUE4]]
265; CHECK:       pred.load.if3:
266; CHECK-NEXT:    [[TMP10:%.*]] = extractelement <2 x i16> [[VEC_IND1]], i32 1
267; CHECK-NEXT:    [[TMP11:%.*]] = getelementptr inbounds [32 x i16], [32 x i16]* @src, i16 0, i16 [[TMP10]]
268; CHECK-NEXT:    [[TMP12:%.*]] = load i16, i16* [[TMP11]], align 1
269; CHECK-NEXT:    [[TMP13:%.*]] = insertelement <2 x i16> [[TMP8]], i16 [[TMP12]], i32 1
270; CHECK-NEXT:    br label [[PRED_LOAD_CONTINUE4]]
271; CHECK:       pred.load.continue4:
272; CHECK-NEXT:    [[TMP14:%.*]] = phi <2 x i16> [ [[TMP8]], [[PRED_LOAD_CONTINUE]] ], [ [[TMP13]], [[PRED_LOAD_IF3]] ]
273; CHECK-NEXT:    [[TMP15:%.*]] = icmp sgt <2 x i64> [[VEC_IND]], [[BROADCAST_SPLAT]]
274; CHECK-NEXT:    [[TMP16:%.*]] = xor <2 x i1> [[TMP2]], <i1 true, i1 true>
275; CHECK-NEXT:    [[TMP17:%.*]] = xor <2 x i1> [[TMP15]], <i1 true, i1 true>
276; CHECK-NEXT:    [[TMP18:%.*]] = select <2 x i1> [[TMP2]], <2 x i1> [[TMP17]], <2 x i1> zeroinitializer
277; CHECK-NEXT:    [[TMP19:%.*]] = select <2 x i1> [[TMP2]], <2 x i1> [[TMP15]], <2 x i1> zeroinitializer
278; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP18]], <2 x i16> [[TMP14]], <2 x i16> zeroinitializer
279; CHECK-NEXT:    [[PREDPHI5:%.*]] = select <2 x i1> [[TMP19]], <2 x i16> <i16 1, i16 1>, <2 x i16> [[PREDPHI]]
280; CHECK-NEXT:    [[TMP20:%.*]] = getelementptr inbounds [32 x i16], [32 x i16]* @dst, i16 0, i64 [[TMP0]]
281; CHECK-NEXT:    [[TMP21:%.*]] = getelementptr inbounds i16, i16* [[TMP20]], i32 0
282; CHECK-NEXT:    [[TMP22:%.*]] = bitcast i16* [[TMP21]] to <2 x i16>*
283; CHECK-NEXT:    store <2 x i16> [[PREDPHI5]], <2 x i16>* [[TMP22]], align 2
284; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
285; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <2 x i64> [[VEC_IND]], <i64 2, i64 2>
286; CHECK-NEXT:    [[VEC_IND_NEXT2]] = add <2 x i16> [[VEC_IND1]], <i16 2, i16 2>
287; CHECK-NEXT:    [[TMP23:%.*]] = icmp eq i64 [[INDEX_NEXT]], 64
288; CHECK-NEXT:    br i1 [[TMP23]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], [[LOOP8:!llvm.loop !.*]]
289; CHECK:       middle.block:
290; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i64 64, 64
291; CHECK-NEXT:    br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]]
292;
293entry:
294  br label %loop.header
295
296loop.header:
297  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
298  %iv.trunc = trunc i64 %iv to i16
299  %cmp.a = icmp ugt i64 %iv, %a
300  br i1 %cmp.a, label %loop.cond, label %loop.latch
301
302loop.cond:
303  %blend = phi i16 [ %iv.trunc, %loop.header ]
304  %src.ptr = getelementptr inbounds [32 x i16], [32 x i16]* @src, i16 0, i16 %blend
305  %lv = load i16, i16* %src.ptr, align 1
306  %cmp.b = icmp sgt i64 %iv, %a
307  br i1 %cmp.b, label %loop.next, label %loop.latch
308
309loop.next:
310  br label %loop.latch
311
312loop.latch:
313  %res = phi i16 [ 0, %loop.header ], [ %lv, %loop.cond ], [ 1, %loop.next ]
314  %dst.ptr = getelementptr inbounds [32 x i16], [32 x i16]* @dst, i16 0, i64 %iv
315  store i16 %res, i16* %dst.ptr
316  %iv.next = add nuw nsw i64 %iv, 1
317  %cmp439 = icmp ult i64 %iv, 63
318  br i1 %cmp439, label %loop.header, label %exit
319
320exit:
321  ret void
322}
323
324; Test case for PR44800.
325define void @duplicated_incoming_blocks_blend(i32 %x, i32* %ptr) {
326; CHECK-LABEL: @duplicated_incoming_blocks_blend(
327; CHECK-NEXT:  entry:
328; CHECK-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
329; CHECK:       vector.ph:
330; CHECK-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <2 x i32> poison, i32 [[X:%.*]], i32 0
331; CHECK-NEXT:    [[BROADCAST_SPLAT:%.*]] = shufflevector <2 x i32> [[BROADCAST_SPLATINSERT]], <2 x i32> poison, <2 x i32> zeroinitializer
332; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
333; CHECK:       vector.body:
334; CHECK-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
335; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <2 x i32> [ <i32 0, i32 1>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]
336; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt <2 x i32> [[VEC_IND]], [[BROADCAST_SPLAT]]
337; CHECK-NEXT:    [[TMP1:%.*]] = extractelement <2 x i32> [[VEC_IND]], i32 0
338; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr i32, i32* [[PTR:%.*]], i32 [[TMP1]]
339; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr i32, i32* [[TMP2]], i32 0
340; CHECK-NEXT:    [[TMP4:%.*]] = bitcast i32* [[TMP3]] to <2 x i32>*
341; CHECK-NEXT:    store <2 x i32> [[VEC_IND]], <2 x i32>* [[TMP4]], align 4
342; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
343; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <2 x i32> [[VEC_IND]], <i32 2, i32 2>
344; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[INDEX_NEXT]], 1000
345; CHECK-NEXT:    br i1 [[TMP5]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], [[LOOP10:!llvm.loop !.*]]
346; CHECK:       middle.block:
347; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i32 1000, 1000
348; CHECK-NEXT:    br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]]
349;
350entry:
351  br label %loop.header
352
353loop.header:
354  %iv = phi i32 [ 0 , %entry ], [ %add.i, %loop.latch ]
355  %c.0 = icmp ugt i32 %iv, %x
356  br i1 %c.0, label %loop.latch, label %loop.latch
357
358loop.latch:
359  %p = phi i32 [ %iv, %loop.header ], [ %iv, %loop.header ]
360  %gep.ptr = getelementptr i32, i32* %ptr, i32 %p
361  store i32 %p, i32* %gep.ptr
362  %add.i = add nsw i32 %p, 1
363  %cmp = icmp slt i32 %add.i, 1000
364  br i1 %cmp, label %loop.header, label %exit
365
366exit:
367  ret void
368}
369