1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2; RUN: opt -p loop-vectorize -force-vector-width=2 -use-dereferenceable-at-point-semantics -S %s | FileCheck %s
3
4declare void @llvm.assume(i1)
5
6define void @deref_assumption_in_header_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
7; CHECK-LABEL: define void @deref_assumption_in_header_constant_trip_count(
8; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1:[0-9]+]] {
9; CHECK-NEXT:  [[ENTRY:.*]]:
10; CHECK-NEXT:    br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
11; CHECK:       [[VECTOR_PH]]:
12; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
13; CHECK:       [[VECTOR_BODY]]:
14; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]
15; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <2 x i64> [ <i64 0, i64 1>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2]] ]
16; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
17; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i32, ptr [[A]], <2 x i64> [[VEC_IND]]
18; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 0
19; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[TMP4]], i64 4), "dereferenceable"(ptr [[TMP4]], i64 4) ]
20; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 1
21; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[TMP5]], i64 4), "dereferenceable"(ptr [[TMP5]], i64 4) ]
22; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
23; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i32 0
24; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP7]], align 4
25; CHECK-NEXT:    [[TMP9:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
26; CHECK-NEXT:    [[TMP10:%.*]] = xor <2 x i1> [[TMP9]], splat (i1 true)
27; CHECK-NEXT:    [[TMP8:%.*]] = extractelement <2 x i1> [[TMP10]], i32 0
28; CHECK-NEXT:    br i1 [[TMP8]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]
29; CHECK:       [[PRED_LOAD_IF]]:
30; CHECK-NEXT:    [[TMP21:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 0
31; CHECK-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
32; CHECK-NEXT:    [[TMP11:%.*]] = insertelement <2 x i32> poison, i32 [[TMP22]], i32 0
33; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE]]
34; CHECK:       [[PRED_LOAD_CONTINUE]]:
35; CHECK-NEXT:    [[TMP12:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP11]], %[[PRED_LOAD_IF]] ]
36; CHECK-NEXT:    [[TMP13:%.*]] = extractelement <2 x i1> [[TMP10]], i32 1
37; CHECK-NEXT:    br i1 [[TMP13]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]
38; CHECK:       [[PRED_LOAD_IF1]]:
39; CHECK-NEXT:    [[TMP26:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 1
40; CHECK-NEXT:    [[TMP27:%.*]] = load i32, ptr [[TMP26]], align 4
41; CHECK-NEXT:    [[TMP16:%.*]] = insertelement <2 x i32> [[TMP12]], i32 [[TMP27]], i32 1
42; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE2]]
43; CHECK:       [[PRED_LOAD_CONTINUE2]]:
44; CHECK-NEXT:    [[TMP17:%.*]] = phi <2 x i32> [ [[TMP12]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP16]], %[[PRED_LOAD_IF1]] ]
45; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP9]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP17]]
46; CHECK-NEXT:    [[TMP30:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
47; CHECK-NEXT:    [[TMP31:%.*]] = getelementptr inbounds i32, ptr [[TMP30]], i32 0
48; CHECK-NEXT:    store <2 x i32> [[PREDPHI]], ptr [[TMP31]], align 4
49; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
50; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <2 x i64> [[VEC_IND]], splat (i64 2)
51; CHECK-NEXT:    [[TMP32:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
52; CHECK-NEXT:    br i1 [[TMP32]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
53; CHECK:       [[MIDDLE_BLOCK]]:
54; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
55; CHECK:       [[SCALAR_PH]]:
56; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
57; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
58; CHECK:       [[LOOP_HEADER]]:
59; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
60; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]]
61; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[GEP_A]], i64 4), "dereferenceable"(ptr [[GEP_A]], i64 4) ]
62; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
63; CHECK-NEXT:    [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
64; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
65; CHECK-NEXT:    br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
66; CHECK:       [[LOOP_THEN]]:
67; CHECK-NEXT:    [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4
68; CHECK-NEXT:    br label %[[LOOP_LATCH]]
69; CHECK:       [[LOOP_LATCH]]:
70; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
71; CHECK-NEXT:    [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
72; CHECK-NEXT:    store i32 [[MERGE]], ptr [[GEP_C]], align 4
73; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
74; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
75; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP3:![0-9]+]]
76; CHECK:       [[EXIT]]:
77; CHECK-NEXT:    ret void
78;
79entry:
80  br label %loop.header
81
82loop.header:
83  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
84  %gep.a = getelementptr i32, ptr %a, i64 %iv
85  call void @llvm.assume(i1 true) [ "align"(ptr %gep.a, i64 4), "dereferenceable"(ptr %gep.a, i64 4) ]
86  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
87  %l.b = load i32, ptr %gep.b, align 4
88  %c.1 = icmp sge i32 %l.b, 0
89  br i1 %c.1, label %loop.latch, label %loop.then
90
91loop.then:
92  %l.a = load i32, ptr %gep.a, align 4
93  br label %loop.latch
94
95loop.latch:
96  %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
97  %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
98  store i32 %merge, ptr %gep.c, align 4
99  %iv.next = add nuw nsw i64 %iv, 1
100  %ec = icmp eq i64 %iv.next, 1000
101  br i1 %ec, label %exit, label %loop.header
102
103exit:
104  ret void
105}
106
107define void @align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
108; CHECK-LABEL: define void @align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(
109; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
110; CHECK-NEXT:  [[ENTRY:.*]]:
111; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 4), "dereferenceable"(ptr [[A]], i64 4) ]
112; CHECK-NEXT:    br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
113; CHECK:       [[VECTOR_PH]]:
114; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
115; CHECK:       [[VECTOR_BODY]]:
116; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
117; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
118; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
119; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0
120; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4
121; CHECK-NEXT:    [[TMP3:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
122; CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[A]], align 4
123; CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[A]], align 4
124; CHECK-NEXT:    [[TMP6:%.*]] = insertelement <2 x i32> poison, i32 [[TMP4]], i32 0
125; CHECK-NEXT:    [[TMP7:%.*]] = insertelement <2 x i32> [[TMP6]], i32 [[TMP5]], i32 1
126; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP7]]
127; CHECK-NEXT:    [[TMP8:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
128; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds i32, ptr [[TMP8]], i32 0
129; CHECK-NEXT:    store <2 x i32> [[PREDPHI]], ptr [[TMP9]], align 4
130; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
131; CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
132; CHECK-NEXT:    br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]
133; CHECK:       [[MIDDLE_BLOCK]]:
134; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
135; CHECK:       [[SCALAR_PH]]:
136; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
137; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
138; CHECK:       [[LOOP_HEADER]]:
139; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
140; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
141; CHECK-NEXT:    [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
142; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
143; CHECK-NEXT:    br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
144; CHECK:       [[LOOP_THEN]]:
145; CHECK-NEXT:    [[L_A:%.*]] = load i32, ptr [[A]], align 4
146; CHECK-NEXT:    br label %[[LOOP_LATCH]]
147; CHECK:       [[LOOP_LATCH]]:
148; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
149; CHECK-NEXT:    [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
150; CHECK-NEXT:    store i32 [[MERGE]], ptr [[GEP_C]], align 4
151; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
152; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
153; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP5:![0-9]+]]
154; CHECK:       [[EXIT]]:
155; CHECK-NEXT:    ret void
156;
157entry:
158  call void @llvm.assume(i1 true) [ "align"(ptr %a, i64 4), "dereferenceable"(ptr %a, i64 4) ]
159  br label %loop.header
160
161loop.header:
162  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
163  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
164  %l.b = load i32, ptr %gep.b, align 4
165  %c.1 = icmp sge i32 %l.b, 0
166  br i1 %c.1, label %loop.latch, label %loop.then
167
168loop.then:
169  %l.a = load i32, ptr %a, align 4
170  br label %loop.latch
171
172loop.latch:
173  %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
174  %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
175  store i32 %merge, ptr %gep.c, align 4
176  %iv.next = add nuw nsw i64 %iv, 1
177  %ec = icmp eq i64 %iv.next, 1000
178  br i1 %ec, label %exit, label %loop.header
179
180exit:
181  ret void
182}
183
184define void @deref_assumption_too_small_in_header_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
185; CHECK-LABEL: define void @deref_assumption_too_small_in_header_constant_trip_count(
186; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
187; CHECK-NEXT:  [[ENTRY:.*]]:
188; CHECK-NEXT:    br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
189; CHECK:       [[VECTOR_PH]]:
190; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
191; CHECK:       [[VECTOR_BODY]]:
192; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]
193; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <2 x i64> [ <i64 0, i64 1>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2]] ]
194; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
195; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i32, ptr [[A]], <2 x i64> [[VEC_IND]]
196; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 0
197; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[TMP4]], i64 4), "dereferenceable"(ptr [[TMP4]], i64 2) ]
198; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 1
199; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[TMP5]], i64 4), "dereferenceable"(ptr [[TMP5]], i64 2) ]
200; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
201; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i32 0
202; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP7]], align 4
203; CHECK-NEXT:    [[TMP9:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
204; CHECK-NEXT:    [[TMP10:%.*]] = xor <2 x i1> [[TMP9]], splat (i1 true)
205; CHECK-NEXT:    [[TMP8:%.*]] = extractelement <2 x i1> [[TMP10]], i32 0
206; CHECK-NEXT:    br i1 [[TMP8]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]
207; CHECK:       [[PRED_LOAD_IF]]:
208; CHECK-NEXT:    [[TMP21:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 0
209; CHECK-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
210; CHECK-NEXT:    [[TMP11:%.*]] = insertelement <2 x i32> poison, i32 [[TMP22]], i32 0
211; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE]]
212; CHECK:       [[PRED_LOAD_CONTINUE]]:
213; CHECK-NEXT:    [[TMP12:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP11]], %[[PRED_LOAD_IF]] ]
214; CHECK-NEXT:    [[TMP13:%.*]] = extractelement <2 x i1> [[TMP10]], i32 1
215; CHECK-NEXT:    br i1 [[TMP13]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]
216; CHECK:       [[PRED_LOAD_IF1]]:
217; CHECK-NEXT:    [[TMP26:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 1
218; CHECK-NEXT:    [[TMP27:%.*]] = load i32, ptr [[TMP26]], align 4
219; CHECK-NEXT:    [[TMP16:%.*]] = insertelement <2 x i32> [[TMP12]], i32 [[TMP27]], i32 1
220; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE2]]
221; CHECK:       [[PRED_LOAD_CONTINUE2]]:
222; CHECK-NEXT:    [[TMP17:%.*]] = phi <2 x i32> [ [[TMP12]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP16]], %[[PRED_LOAD_IF1]] ]
223; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP9]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP17]]
224; CHECK-NEXT:    [[TMP30:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
225; CHECK-NEXT:    [[TMP31:%.*]] = getelementptr inbounds i32, ptr [[TMP30]], i32 0
226; CHECK-NEXT:    store <2 x i32> [[PREDPHI]], ptr [[TMP31]], align 4
227; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
228; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <2 x i64> [[VEC_IND]], splat (i64 2)
229; CHECK-NEXT:    [[TMP32:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
230; CHECK-NEXT:    br i1 [[TMP32]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]]
231; CHECK:       [[MIDDLE_BLOCK]]:
232; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
233; CHECK:       [[SCALAR_PH]]:
234; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
235; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
236; CHECK:       [[LOOP_HEADER]]:
237; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
238; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]]
239; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[GEP_A]], i64 4), "dereferenceable"(ptr [[GEP_A]], i64 2) ]
240; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
241; CHECK-NEXT:    [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
242; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
243; CHECK-NEXT:    br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
244; CHECK:       [[LOOP_THEN]]:
245; CHECK-NEXT:    [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4
246; CHECK-NEXT:    br label %[[LOOP_LATCH]]
247; CHECK:       [[LOOP_LATCH]]:
248; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
249; CHECK-NEXT:    [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
250; CHECK-NEXT:    store i32 [[MERGE]], ptr [[GEP_C]], align 4
251; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
252; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
253; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP7:![0-9]+]]
254; CHECK:       [[EXIT]]:
255; CHECK-NEXT:    ret void
256;
257entry:
258  br label %loop.header
259
260loop.header:
261  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
262  %gep.a = getelementptr i32, ptr %a, i64 %iv
263  call void @llvm.assume(i1 true) [ "align"(ptr %gep.a, i64 4), "dereferenceable"(ptr %gep.a, i64 2) ]
264  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
265  %l.b = load i32, ptr %gep.b, align 4
266  %c.1 = icmp sge i32 %l.b, 0
267  br i1 %c.1, label %loop.latch, label %loop.then
268
269loop.then:
270  %l.a = load i32, ptr %gep.a, align 4
271  br label %loop.latch
272
273loop.latch:
274  %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
275  %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
276  store i32 %merge, ptr %gep.c, align 4
277  %iv.next = add nuw nsw i64 %iv, 1
278  %ec = icmp eq i64 %iv.next, 1000
279  br i1 %ec, label %exit, label %loop.header
280
281exit:
282  ret void
283}
284
285define void @deref_assumption_in_header_constant_trip_count_align_1(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
286; CHECK-LABEL: define void @deref_assumption_in_header_constant_trip_count_align_1(
287; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
288; CHECK-NEXT:  [[ENTRY:.*]]:
289; CHECK-NEXT:    br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
290; CHECK:       [[VECTOR_PH]]:
291; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
292; CHECK:       [[VECTOR_BODY]]:
293; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]
294; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <2 x i64> [ <i64 0, i64 1>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2]] ]
295; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
296; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i32, ptr [[A]], <2 x i64> [[VEC_IND]]
297; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 0
298; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP2]], i64 4) ]
299; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 1
300; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP3]], i64 4) ]
301; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
302; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[TMP4]], i32 0
303; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP5]], align 4
304; CHECK-NEXT:    [[TMP6:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
305; CHECK-NEXT:    [[TMP7:%.*]] = xor <2 x i1> [[TMP6]], splat (i1 true)
306; CHECK-NEXT:    [[TMP8:%.*]] = extractelement <2 x i1> [[TMP7]], i32 0
307; CHECK-NEXT:    br i1 [[TMP8]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]
308; CHECK:       [[PRED_LOAD_IF]]:
309; CHECK-NEXT:    [[TMP9:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 0
310; CHECK-NEXT:    [[TMP10:%.*]] = load i32, ptr [[TMP9]], align 1
311; CHECK-NEXT:    [[TMP11:%.*]] = insertelement <2 x i32> poison, i32 [[TMP10]], i32 0
312; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE]]
313; CHECK:       [[PRED_LOAD_CONTINUE]]:
314; CHECK-NEXT:    [[TMP12:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP11]], %[[PRED_LOAD_IF]] ]
315; CHECK-NEXT:    [[TMP13:%.*]] = extractelement <2 x i1> [[TMP7]], i32 1
316; CHECK-NEXT:    br i1 [[TMP13]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]
317; CHECK:       [[PRED_LOAD_IF1]]:
318; CHECK-NEXT:    [[TMP14:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 1
319; CHECK-NEXT:    [[TMP15:%.*]] = load i32, ptr [[TMP14]], align 1
320; CHECK-NEXT:    [[TMP16:%.*]] = insertelement <2 x i32> [[TMP12]], i32 [[TMP15]], i32 1
321; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE2]]
322; CHECK:       [[PRED_LOAD_CONTINUE2]]:
323; CHECK-NEXT:    [[TMP17:%.*]] = phi <2 x i32> [ [[TMP12]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP16]], %[[PRED_LOAD_IF1]] ]
324; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP6]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP17]]
325; CHECK-NEXT:    [[TMP18:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
326; CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds i32, ptr [[TMP18]], i32 0
327; CHECK-NEXT:    store <2 x i32> [[PREDPHI]], ptr [[TMP19]], align 4
328; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
329; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <2 x i64> [[VEC_IND]], splat (i64 2)
330; CHECK-NEXT:    [[TMP20:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
331; CHECK-NEXT:    br i1 [[TMP20]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]]
332; CHECK:       [[MIDDLE_BLOCK]]:
333; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
334; CHECK:       [[SCALAR_PH]]:
335; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
336; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
337; CHECK:       [[LOOP_HEADER]]:
338; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
339; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]]
340; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[GEP_A]], i64 4) ]
341; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
342; CHECK-NEXT:    [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
343; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
344; CHECK-NEXT:    br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
345; CHECK:       [[LOOP_THEN]]:
346; CHECK-NEXT:    [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 1
347; CHECK-NEXT:    br label %[[LOOP_LATCH]]
348; CHECK:       [[LOOP_LATCH]]:
349; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
350; CHECK-NEXT:    [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
351; CHECK-NEXT:    store i32 [[MERGE]], ptr [[GEP_C]], align 4
352; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
353; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
354; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP9:![0-9]+]]
355; CHECK:       [[EXIT]]:
356; CHECK-NEXT:    ret void
357;
358entry:
359  br label %loop.header
360
361loop.header:
362  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
363  %gep.a = getelementptr i32, ptr %a, i64 %iv
364  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %gep.a, i64 4) ]
365  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
366  %l.b = load i32, ptr %gep.b, align 4
367  %c.1 = icmp sge i32 %l.b, 0
368  br i1 %c.1, label %loop.latch, label %loop.then
369
370loop.then:
371  %l.a = load i32, ptr %gep.a, align 1
372  br label %loop.latch
373
374loop.latch:
375  %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
376  %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
377  store i32 %merge, ptr %gep.c, align 4
378  %iv.next = add nuw nsw i64 %iv, 1
379  %ec = icmp eq i64 %iv.next, 1000
380  br i1 %ec, label %exit, label %loop.header
381
382exit:
383  ret void
384}
385
386define void @deref_assumption_in_header_constant_trip_count_align_via_arg_attribute(ptr noalias align 4 %a, ptr noalias %b, ptr noalias %c) nofree nosync{
387; CHECK-LABEL: define void @deref_assumption_in_header_constant_trip_count_align_via_arg_attribute(
388; CHECK-SAME: ptr noalias align 4 [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
389; CHECK-NEXT:  [[ENTRY:.*]]:
390; CHECK-NEXT:    br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
391; CHECK:       [[VECTOR_PH]]:
392; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
393; CHECK:       [[VECTOR_BODY]]:
394; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]
395; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <2 x i64> [ <i64 0, i64 1>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2]] ]
396; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
397; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i32, ptr [[A]], <2 x i64> [[VEC_IND]]
398; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 0
399; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP2]], i64 4) ]
400; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 1
401; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP3]], i64 4) ]
402; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
403; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[TMP4]], i32 0
404; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP5]], align 4
405; CHECK-NEXT:    [[TMP6:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
406; CHECK-NEXT:    [[TMP7:%.*]] = xor <2 x i1> [[TMP6]], splat (i1 true)
407; CHECK-NEXT:    [[TMP8:%.*]] = extractelement <2 x i1> [[TMP7]], i32 0
408; CHECK-NEXT:    br i1 [[TMP8]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]
409; CHECK:       [[PRED_LOAD_IF]]:
410; CHECK-NEXT:    [[TMP9:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 0
411; CHECK-NEXT:    [[TMP10:%.*]] = load i32, ptr [[TMP9]], align 4
412; CHECK-NEXT:    [[TMP11:%.*]] = insertelement <2 x i32> poison, i32 [[TMP10]], i32 0
413; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE]]
414; CHECK:       [[PRED_LOAD_CONTINUE]]:
415; CHECK-NEXT:    [[TMP12:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP11]], %[[PRED_LOAD_IF]] ]
416; CHECK-NEXT:    [[TMP13:%.*]] = extractelement <2 x i1> [[TMP7]], i32 1
417; CHECK-NEXT:    br i1 [[TMP13]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]
418; CHECK:       [[PRED_LOAD_IF1]]:
419; CHECK-NEXT:    [[TMP14:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 1
420; CHECK-NEXT:    [[TMP15:%.*]] = load i32, ptr [[TMP14]], align 4
421; CHECK-NEXT:    [[TMP16:%.*]] = insertelement <2 x i32> [[TMP12]], i32 [[TMP15]], i32 1
422; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE2]]
423; CHECK:       [[PRED_LOAD_CONTINUE2]]:
424; CHECK-NEXT:    [[TMP17:%.*]] = phi <2 x i32> [ [[TMP12]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP16]], %[[PRED_LOAD_IF1]] ]
425; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP6]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP17]]
426; CHECK-NEXT:    [[TMP18:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
427; CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds i32, ptr [[TMP18]], i32 0
428; CHECK-NEXT:    store <2 x i32> [[PREDPHI]], ptr [[TMP19]], align 4
429; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
430; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <2 x i64> [[VEC_IND]], splat (i64 2)
431; CHECK-NEXT:    [[TMP20:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
432; CHECK-NEXT:    br i1 [[TMP20]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]]
433; CHECK:       [[MIDDLE_BLOCK]]:
434; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
435; CHECK:       [[SCALAR_PH]]:
436; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
437; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
438; CHECK:       [[LOOP_HEADER]]:
439; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
440; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]]
441; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[GEP_A]], i64 4) ]
442; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
443; CHECK-NEXT:    [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
444; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
445; CHECK-NEXT:    br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
446; CHECK:       [[LOOP_THEN]]:
447; CHECK-NEXT:    [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4
448; CHECK-NEXT:    br label %[[LOOP_LATCH]]
449; CHECK:       [[LOOP_LATCH]]:
450; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
451; CHECK-NEXT:    [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
452; CHECK-NEXT:    store i32 [[MERGE]], ptr [[GEP_C]], align 4
453; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
454; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
455; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP11:![0-9]+]]
456; CHECK:       [[EXIT]]:
457; CHECK-NEXT:    ret void
458;
459entry:
460  br label %loop.header
461
462loop.header:
463  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
464  %gep.a = getelementptr i32, ptr %a, i64 %iv
465  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %gep.a, i64 4) ]
466  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
467  %l.b = load i32, ptr %gep.b, align 4
468  %c.1 = icmp sge i32 %l.b, 0
469  br i1 %c.1, label %loop.latch, label %loop.then
470
471loop.then:
472  %l.a = load i32, ptr %gep.a, align 4
473  br label %loop.latch
474
475loop.latch:
476  %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
477  %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
478  store i32 %merge, ptr %gep.c, align 4
479  %iv.next = add nuw nsw i64 %iv, 1
480  %ec = icmp eq i64 %iv.next, 1000
481  br i1 %ec, label %exit, label %loop.header
482
483exit:
484  ret void
485}
486
487define void @deref_assumption_in_header_constant_trip_count_align_not_known(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
488; CHECK-LABEL: define void @deref_assumption_in_header_constant_trip_count_align_not_known(
489; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
490; CHECK-NEXT:  [[ENTRY:.*]]:
491; CHECK-NEXT:    br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
492; CHECK:       [[VECTOR_PH]]:
493; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
494; CHECK:       [[VECTOR_BODY]]:
495; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]
496; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <2 x i64> [ <i64 0, i64 1>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2]] ]
497; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
498; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i32, ptr [[A]], <2 x i64> [[VEC_IND]]
499; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 0
500; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP2]], i64 4) ]
501; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 1
502; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP3]], i64 4) ]
503; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
504; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[TMP4]], i32 0
505; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP5]], align 4
506; CHECK-NEXT:    [[TMP6:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
507; CHECK-NEXT:    [[TMP7:%.*]] = xor <2 x i1> [[TMP6]], splat (i1 true)
508; CHECK-NEXT:    [[TMP8:%.*]] = extractelement <2 x i1> [[TMP7]], i32 0
509; CHECK-NEXT:    br i1 [[TMP8]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]
510; CHECK:       [[PRED_LOAD_IF]]:
511; CHECK-NEXT:    [[TMP9:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 0
512; CHECK-NEXT:    [[TMP10:%.*]] = load i32, ptr [[TMP9]], align 4
513; CHECK-NEXT:    [[TMP11:%.*]] = insertelement <2 x i32> poison, i32 [[TMP10]], i32 0
514; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE]]
515; CHECK:       [[PRED_LOAD_CONTINUE]]:
516; CHECK-NEXT:    [[TMP12:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP11]], %[[PRED_LOAD_IF]] ]
517; CHECK-NEXT:    [[TMP13:%.*]] = extractelement <2 x i1> [[TMP7]], i32 1
518; CHECK-NEXT:    br i1 [[TMP13]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]
519; CHECK:       [[PRED_LOAD_IF1]]:
520; CHECK-NEXT:    [[TMP14:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 1
521; CHECK-NEXT:    [[TMP15:%.*]] = load i32, ptr [[TMP14]], align 4
522; CHECK-NEXT:    [[TMP16:%.*]] = insertelement <2 x i32> [[TMP12]], i32 [[TMP15]], i32 1
523; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE2]]
524; CHECK:       [[PRED_LOAD_CONTINUE2]]:
525; CHECK-NEXT:    [[TMP17:%.*]] = phi <2 x i32> [ [[TMP12]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP16]], %[[PRED_LOAD_IF1]] ]
526; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP6]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP17]]
527; CHECK-NEXT:    [[TMP18:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
528; CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds i32, ptr [[TMP18]], i32 0
529; CHECK-NEXT:    store <2 x i32> [[PREDPHI]], ptr [[TMP19]], align 4
530; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
531; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <2 x i64> [[VEC_IND]], splat (i64 2)
532; CHECK-NEXT:    [[TMP20:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
533; CHECK-NEXT:    br i1 [[TMP20]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP12:![0-9]+]]
534; CHECK:       [[MIDDLE_BLOCK]]:
535; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
536; CHECK:       [[SCALAR_PH]]:
537; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
538; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
539; CHECK:       [[LOOP_HEADER]]:
540; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
541; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]]
542; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[GEP_A]], i64 4) ]
543; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
544; CHECK-NEXT:    [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
545; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
546; CHECK-NEXT:    br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
547; CHECK:       [[LOOP_THEN]]:
548; CHECK-NEXT:    [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4
549; CHECK-NEXT:    br label %[[LOOP_LATCH]]
550; CHECK:       [[LOOP_LATCH]]:
551; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
552; CHECK-NEXT:    [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
553; CHECK-NEXT:    store i32 [[MERGE]], ptr [[GEP_C]], align 4
554; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
555; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
556; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP13:![0-9]+]]
557; CHECK:       [[EXIT]]:
558; CHECK-NEXT:    ret void
559;
560entry:
561  br label %loop.header
562
563loop.header:
564  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
565  %gep.a = getelementptr i32, ptr %a, i64 %iv
566  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %gep.a, i64 4) ]
567  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
568  %l.b = load i32, ptr %gep.b, align 4
569  %c.1 = icmp sge i32 %l.b, 0
570  br i1 %c.1, label %loop.latch, label %loop.then
571
572loop.then:
573  %l.a = load i32, ptr %gep.a, align 4
574  br label %loop.latch
575
576loop.latch:
577  %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
578  %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
579  store i32 %merge, ptr %gep.c, align 4
580  %iv.next = add nuw nsw i64 %iv, 1
581  %ec = icmp eq i64 %iv.next, 1000
582  br i1 %ec, label %exit, label %loop.header
583
584exit:
585  ret void
586}
587
588define void @deref_assumption_in_then_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
589; CHECK-LABEL: define void @deref_assumption_in_then_constant_trip_count(
590; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
591; CHECK-NEXT:  [[ENTRY:.*]]:
592; CHECK-NEXT:    br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
593; CHECK:       [[VECTOR_PH]]:
594; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
595; CHECK:       [[VECTOR_BODY]]:
596; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]
597; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <2 x i64> [ <i64 0, i64 1>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2]] ]
598; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
599; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
600; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0
601; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4
602; CHECK-NEXT:    [[TMP3:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
603; CHECK-NEXT:    [[TMP4:%.*]] = xor <2 x i1> [[TMP3]], splat (i1 true)
604; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr i32, ptr [[A]], <2 x i64> [[VEC_IND]]
605; CHECK-NEXT:    [[TMP6:%.*]] = extractelement <2 x i1> [[TMP4]], i32 0
606; CHECK-NEXT:    br i1 [[TMP6]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]
607; CHECK:       [[PRED_LOAD_IF]]:
608; CHECK-NEXT:    [[TMP17:%.*]] = extractelement <2 x ptr> [[TMP5]], i32 0
609; CHECK-NEXT:    [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4
610; CHECK-NEXT:    [[TMP9:%.*]] = insertelement <2 x i32> poison, i32 [[TMP18]], i32 0
611; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE]]
612; CHECK:       [[PRED_LOAD_CONTINUE]]:
613; CHECK-NEXT:    [[TMP10:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP9]], %[[PRED_LOAD_IF]] ]
614; CHECK-NEXT:    [[TMP11:%.*]] = extractelement <2 x i1> [[TMP4]], i32 1
615; CHECK-NEXT:    br i1 [[TMP11]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]
616; CHECK:       [[PRED_LOAD_IF1]]:
617; CHECK-NEXT:    [[TMP22:%.*]] = extractelement <2 x ptr> [[TMP5]], i32 1
618; CHECK-NEXT:    [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4
619; CHECK-NEXT:    [[TMP14:%.*]] = insertelement <2 x i32> [[TMP10]], i32 [[TMP23]], i32 1
620; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE2]]
621; CHECK:       [[PRED_LOAD_CONTINUE2]]:
622; CHECK-NEXT:    [[TMP15:%.*]] = phi <2 x i32> [ [[TMP10]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP14]], %[[PRED_LOAD_IF1]] ]
623; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP15]]
624; CHECK-NEXT:    [[TMP26:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
625; CHECK-NEXT:    [[TMP27:%.*]] = getelementptr inbounds i32, ptr [[TMP26]], i32 0
626; CHECK-NEXT:    store <2 x i32> [[PREDPHI]], ptr [[TMP27]], align 4
627; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
628; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <2 x i64> [[VEC_IND]], splat (i64 2)
629; CHECK-NEXT:    [[TMP28:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
630; CHECK-NEXT:    br i1 [[TMP28]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP14:![0-9]+]]
631; CHECK:       [[MIDDLE_BLOCK]]:
632; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
633; CHECK:       [[SCALAR_PH]]:
634; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
635; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
636; CHECK:       [[LOOP_HEADER]]:
637; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
638; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
639; CHECK-NEXT:    [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
640; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
641; CHECK-NEXT:    br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
642; CHECK:       [[LOOP_THEN]]:
643; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]]
644; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[GEP_A]], i64 4), "dereferenceable"(ptr [[GEP_A]], i64 4) ]
645; CHECK-NEXT:    [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4
646; CHECK-NEXT:    br label %[[LOOP_LATCH]]
647; CHECK:       [[LOOP_LATCH]]:
648; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
649; CHECK-NEXT:    [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
650; CHECK-NEXT:    store i32 [[MERGE]], ptr [[GEP_C]], align 4
651; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
652; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
653; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP15:![0-9]+]]
654; CHECK:       [[EXIT]]:
655; CHECK-NEXT:    ret void
656;
657entry:
658  br label %loop.header
659
660loop.header:
661  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
662  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
663  %l.b = load i32, ptr %gep.b, align 4
664  %c.1 = icmp sge i32 %l.b, 0
665  br i1 %c.1, label %loop.latch, label %loop.then
666
667loop.then:
668  %gep.a = getelementptr i32, ptr %a, i64 %iv
669  call void @llvm.assume(i1 true) [ "align"(ptr %gep.a, i64 4), "dereferenceable"(ptr %gep.a, i64 4) ]
670  %l.a = load i32, ptr %gep.a, align 4
671  br label %loop.latch
672
673loop.latch:
674  %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
675  %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
676  store i32 %merge, ptr %gep.c, align 4
677  %iv.next = add nuw nsw i64 %iv, 1
678  %ec = icmp eq i64 %iv.next, 1000
679  br i1 %ec, label %exit, label %loop.header
680
681exit:
682  ret void
683}
684
685define void @deref_assumption_in_latch_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
686; CHECK-LABEL: define void @deref_assumption_in_latch_constant_trip_count(
687; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
688; CHECK-NEXT:  [[ENTRY:.*]]:
689; CHECK-NEXT:    br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
690; CHECK:       [[VECTOR_PH]]:
691; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
692; CHECK:       [[VECTOR_BODY]]:
693; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]
694; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <2 x i64> [ <i64 0, i64 1>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2]] ]
695; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
696; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i32, ptr [[A]], <2 x i64> [[VEC_IND]]
697; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
698; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i32 0
699; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP3]], align 4
700; CHECK-NEXT:    [[TMP4:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
701; CHECK-NEXT:    [[TMP5:%.*]] = xor <2 x i1> [[TMP4]], splat (i1 true)
702; CHECK-NEXT:    [[TMP6:%.*]] = extractelement <2 x i1> [[TMP5]], i32 0
703; CHECK-NEXT:    br i1 [[TMP6]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]
704; CHECK:       [[PRED_LOAD_IF]]:
705; CHECK-NEXT:    [[TMP17:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 0
706; CHECK-NEXT:    [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4
707; CHECK-NEXT:    [[TMP9:%.*]] = insertelement <2 x i32> poison, i32 [[TMP18]], i32 0
708; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE]]
709; CHECK:       [[PRED_LOAD_CONTINUE]]:
710; CHECK-NEXT:    [[TMP10:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP9]], %[[PRED_LOAD_IF]] ]
711; CHECK-NEXT:    [[TMP11:%.*]] = extractelement <2 x i1> [[TMP5]], i32 1
712; CHECK-NEXT:    br i1 [[TMP11]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]
713; CHECK:       [[PRED_LOAD_IF1]]:
714; CHECK-NEXT:    [[TMP22:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 1
715; CHECK-NEXT:    [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4
716; CHECK-NEXT:    [[TMP14:%.*]] = insertelement <2 x i32> [[TMP10]], i32 [[TMP23]], i32 1
717; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE2]]
718; CHECK:       [[PRED_LOAD_CONTINUE2]]:
719; CHECK-NEXT:    [[TMP15:%.*]] = phi <2 x i32> [ [[TMP10]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP14]], %[[PRED_LOAD_IF1]] ]
720; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP4]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP15]]
721; CHECK-NEXT:    [[TMP28:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 0
722; CHECK-NEXT:    [[TMP20:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 0
723; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[TMP28]], i64 4), "dereferenceable"(ptr [[TMP20]], i64 4) ]
724; CHECK-NEXT:    [[TMP29:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 1
725; CHECK-NEXT:    [[TMP19:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 1
726; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[TMP29]], i64 4), "dereferenceable"(ptr [[TMP19]], i64 4) ]
727; CHECK-NEXT:    [[TMP30:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
728; CHECK-NEXT:    [[TMP31:%.*]] = getelementptr inbounds i32, ptr [[TMP30]], i32 0
729; CHECK-NEXT:    store <2 x i32> [[PREDPHI]], ptr [[TMP31]], align 4
730; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
731; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <2 x i64> [[VEC_IND]], splat (i64 2)
732; CHECK-NEXT:    [[TMP32:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
733; CHECK-NEXT:    br i1 [[TMP32]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]]
734; CHECK:       [[MIDDLE_BLOCK]]:
735; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
736; CHECK:       [[SCALAR_PH]]:
737; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
738; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
739; CHECK:       [[LOOP_HEADER]]:
740; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
741; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]]
742; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
743; CHECK-NEXT:    [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
744; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
745; CHECK-NEXT:    br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
746; CHECK:       [[LOOP_THEN]]:
747; CHECK-NEXT:    [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4
748; CHECK-NEXT:    br label %[[LOOP_LATCH]]
749; CHECK:       [[LOOP_LATCH]]:
750; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
751; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[GEP_A]], i64 4), "dereferenceable"(ptr [[GEP_A]], i64 4) ]
752; CHECK-NEXT:    [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
753; CHECK-NEXT:    store i32 [[MERGE]], ptr [[GEP_C]], align 4
754; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
755; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
756; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP17:![0-9]+]]
757; CHECK:       [[EXIT]]:
758; CHECK-NEXT:    ret void
759;
760entry:
761  br label %loop.header
762
763loop.header:
764  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
765  %gep.a = getelementptr i32, ptr %a, i64 %iv
766  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
767  %l.b = load i32, ptr %gep.b, align 4
768  %c.1 = icmp sge i32 %l.b, 0
769  br i1 %c.1, label %loop.latch, label %loop.then
770
771loop.then:
772  %l.a = load i32, ptr %gep.a, align 4
773  br label %loop.latch
774
775loop.latch:
776  %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
777  call void @llvm.assume(i1 true) [ "align"(ptr %gep.a, i64 4), "dereferenceable"(ptr %gep.a, i64 4) ]
778  %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
779  store i32 %merge, ptr %gep.c, align 4
780  %iv.next = add nuw nsw i64 %iv, 1
781  %ec = icmp eq i64 %iv.next, 1000
782  br i1 %ec, label %exit, label %loop.header
783
784exit:
785  ret void
786}
787
788define void @deref_assumption_in_header_variable_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c, i64 %N) nofree nosync{
789; CHECK-LABEL: define void @deref_assumption_in_header_variable_trip_count(
790; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]], i64 [[N:%.*]]) #[[ATTR1]] {
791; CHECK-NEXT:  [[ENTRY:.*]]:
792; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 2
793; CHECK-NEXT:    br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
794; CHECK:       [[VECTOR_PH]]:
795; CHECK-NEXT:    [[N_MOD_VF:%.*]] = urem i64 [[N]], 2
796; CHECK-NEXT:    [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]]
797; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
798; CHECK:       [[VECTOR_BODY]]:
799; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]
800; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <2 x i64> [ <i64 0, i64 1>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2]] ]
801; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
802; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i32, ptr [[A]], <2 x i64> [[VEC_IND]]
803; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 0
804; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[TMP4]], i64 4), "dereferenceable"(ptr [[TMP4]], i64 4) ]
805; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 1
806; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[TMP5]], i64 4), "dereferenceable"(ptr [[TMP5]], i64 4) ]
807; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
808; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i32 0
809; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP7]], align 4
810; CHECK-NEXT:    [[TMP9:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
811; CHECK-NEXT:    [[TMP10:%.*]] = xor <2 x i1> [[TMP9]], splat (i1 true)
812; CHECK-NEXT:    [[TMP8:%.*]] = extractelement <2 x i1> [[TMP10]], i32 0
813; CHECK-NEXT:    br i1 [[TMP8]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]
814; CHECK:       [[PRED_LOAD_IF]]:
815; CHECK-NEXT:    [[TMP21:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 0
816; CHECK-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
817; CHECK-NEXT:    [[TMP11:%.*]] = insertelement <2 x i32> poison, i32 [[TMP22]], i32 0
818; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE]]
819; CHECK:       [[PRED_LOAD_CONTINUE]]:
820; CHECK-NEXT:    [[TMP12:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP11]], %[[PRED_LOAD_IF]] ]
821; CHECK-NEXT:    [[TMP13:%.*]] = extractelement <2 x i1> [[TMP10]], i32 1
822; CHECK-NEXT:    br i1 [[TMP13]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]
823; CHECK:       [[PRED_LOAD_IF1]]:
824; CHECK-NEXT:    [[TMP26:%.*]] = extractelement <2 x ptr> [[TMP1]], i32 1
825; CHECK-NEXT:    [[TMP27:%.*]] = load i32, ptr [[TMP26]], align 4
826; CHECK-NEXT:    [[TMP16:%.*]] = insertelement <2 x i32> [[TMP12]], i32 [[TMP27]], i32 1
827; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE2]]
828; CHECK:       [[PRED_LOAD_CONTINUE2]]:
829; CHECK-NEXT:    [[TMP17:%.*]] = phi <2 x i32> [ [[TMP12]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP16]], %[[PRED_LOAD_IF1]] ]
830; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP9]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP17]]
831; CHECK-NEXT:    [[TMP30:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
832; CHECK-NEXT:    [[TMP31:%.*]] = getelementptr inbounds i32, ptr [[TMP30]], i32 0
833; CHECK-NEXT:    store <2 x i32> [[PREDPHI]], ptr [[TMP31]], align 4
834; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
835; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <2 x i64> [[VEC_IND]], splat (i64 2)
836; CHECK-NEXT:    [[TMP32:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
837; CHECK-NEXT:    br i1 [[TMP32]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP18:![0-9]+]]
838; CHECK:       [[MIDDLE_BLOCK]]:
839; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]]
840; CHECK-NEXT:    br i1 [[CMP_N]], label %[[EXIT:.*]], label %[[SCALAR_PH]]
841; CHECK:       [[SCALAR_PH]]:
842; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
843; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
844; CHECK:       [[LOOP_HEADER]]:
845; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
846; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]]
847; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[GEP_A]], i64 4), "dereferenceable"(ptr [[GEP_A]], i64 4) ]
848; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
849; CHECK-NEXT:    [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
850; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
851; CHECK-NEXT:    br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
852; CHECK:       [[LOOP_THEN]]:
853; CHECK-NEXT:    [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4
854; CHECK-NEXT:    br label %[[LOOP_LATCH]]
855; CHECK:       [[LOOP_LATCH]]:
856; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
857; CHECK-NEXT:    [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
858; CHECK-NEXT:    store i32 [[MERGE]], ptr [[GEP_C]], align 4
859; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
860; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]
861; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP19:![0-9]+]]
862; CHECK:       [[EXIT]]:
863; CHECK-NEXT:    ret void
864;
865entry:
866  br label %loop.header
867
868loop.header:
869  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
870  %gep.a = getelementptr i32, ptr %a, i64 %iv
871  call void @llvm.assume(i1 true) [ "align"(ptr %gep.a, i64 4), "dereferenceable"(ptr %gep.a, i64 4) ]
872  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
873  %l.b = load i32, ptr %gep.b, align 4
874  %c.1 = icmp sge i32 %l.b, 0
875  br i1 %c.1, label %loop.latch, label %loop.then
876
877loop.then:
878  %l.a = load i32, ptr %gep.a, align 4
879  br label %loop.latch
880
881loop.latch:
882  %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
883  %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
884  store i32 %merge, ptr %gep.c, align 4
885  %iv.next = add nuw nsw i64 %iv, 1
886  %ec = icmp eq i64 %iv.next, %N
887  br i1 %ec, label %exit, label %loop.header
888
889exit:
890  ret void
891}
892
893define void @deref_assumption_in_preheader_constant_trip_count_align_1(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
894; CHECK-LABEL: define void @deref_assumption_in_preheader_constant_trip_count_align_1(
895; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
896; CHECK-NEXT:  [[ENTRY:.*]]:
897; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A]], i64 4000) ]
898; CHECK-NEXT:    br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
899; CHECK:       [[VECTOR_PH]]:
900; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
901; CHECK:       [[VECTOR_BODY]]:
902; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
903; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
904; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
905; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0
906; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4
907; CHECK-NEXT:    [[TMP3:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
908; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr i32, ptr [[A]], i64 [[TMP0]]
909; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr i32, ptr [[TMP6]], i32 0
910; CHECK-NEXT:    [[TMP15:%.*]] = load <2 x i32>, ptr [[TMP5]], align 1
911; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP15]]
912; CHECK-NEXT:    [[TMP16:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
913; CHECK-NEXT:    [[TMP17:%.*]] = getelementptr inbounds i32, ptr [[TMP16]], i32 0
914; CHECK-NEXT:    store <2 x i32> [[PREDPHI]], ptr [[TMP17]], align 4
915; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
916; CHECK-NEXT:    [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
917; CHECK-NEXT:    br i1 [[TMP18]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP20:![0-9]+]]
918; CHECK:       [[MIDDLE_BLOCK]]:
919; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
920; CHECK:       [[SCALAR_PH]]:
921; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
922; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
923; CHECK:       [[LOOP_HEADER]]:
924; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
925; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
926; CHECK-NEXT:    [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
927; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
928; CHECK-NEXT:    br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
929; CHECK:       [[LOOP_THEN]]:
930; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]]
931; CHECK-NEXT:    [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 1
932; CHECK-NEXT:    br label %[[LOOP_LATCH]]
933; CHECK:       [[LOOP_LATCH]]:
934; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
935; CHECK-NEXT:    [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
936; CHECK-NEXT:    store i32 [[MERGE]], ptr [[GEP_C]], align 4
937; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
938; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
939; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP21:![0-9]+]]
940; CHECK:       [[EXIT]]:
941; CHECK-NEXT:    ret void
942;
943entry:
944  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %a, i64 4000) ]
945  br label %loop.header
946
947loop.header:
948  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
949  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
950  %l.b = load i32, ptr %gep.b, align 4
951  %c.1 = icmp sge i32 %l.b, 0
952  br i1 %c.1, label %loop.latch, label %loop.then
953
954loop.then:
955  %gep.a = getelementptr i32, ptr %a, i64 %iv
956  %l.a = load i32, ptr %gep.a, align 1
957  br label %loop.latch
958
959loop.latch:
960  %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
961  %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
962  store i32 %merge, ptr %gep.c, align 4
963  %iv.next = add nuw nsw i64 %iv, 1
964  %ec = icmp eq i64 %iv.next, 1000
965  br i1 %ec, label %exit, label %loop.header
966
967exit:
968  ret void
969}
970
971define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_1(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
972; CHECK-LABEL: define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_1(
973; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
974; CHECK-NEXT:  [[ENTRY:.*]]:
975; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A]], i64 3999) ]
976; CHECK-NEXT:    br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
977; CHECK:       [[VECTOR_PH]]:
978; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
979; CHECK:       [[VECTOR_BODY]]:
980; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]
981; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
982; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
983; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0
984; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4
985; CHECK-NEXT:    [[TMP3:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
986; CHECK-NEXT:    [[TMP4:%.*]] = xor <2 x i1> [[TMP3]], splat (i1 true)
987; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <2 x i1> [[TMP4]], i32 0
988; CHECK-NEXT:    br i1 [[TMP5]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]
989; CHECK:       [[PRED_LOAD_IF]]:
990; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr i32, ptr [[A]], i64 [[TMP0]]
991; CHECK-NEXT:    [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 1
992; CHECK-NEXT:    [[TMP8:%.*]] = insertelement <2 x i32> poison, i32 [[TMP7]], i32 0
993; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE]]
994; CHECK:       [[PRED_LOAD_CONTINUE]]:
995; CHECK-NEXT:    [[TMP9:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP8]], %[[PRED_LOAD_IF]] ]
996; CHECK-NEXT:    [[TMP10:%.*]] = extractelement <2 x i1> [[TMP4]], i32 1
997; CHECK-NEXT:    br i1 [[TMP10]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]
998; CHECK:       [[PRED_LOAD_IF1]]:
999; CHECK-NEXT:    [[TMP11:%.*]] = add i64 [[INDEX]], 1
1000; CHECK-NEXT:    [[TMP12:%.*]] = getelementptr i32, ptr [[A]], i64 [[TMP11]]
1001; CHECK-NEXT:    [[TMP13:%.*]] = load i32, ptr [[TMP12]], align 1
1002; CHECK-NEXT:    [[TMP14:%.*]] = insertelement <2 x i32> [[TMP9]], i32 [[TMP13]], i32 1
1003; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE2]]
1004; CHECK:       [[PRED_LOAD_CONTINUE2]]:
1005; CHECK-NEXT:    [[TMP15:%.*]] = phi <2 x i32> [ [[TMP9]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP14]], %[[PRED_LOAD_IF1]] ]
1006; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP15]]
1007; CHECK-NEXT:    [[TMP16:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
1008; CHECK-NEXT:    [[TMP17:%.*]] = getelementptr inbounds i32, ptr [[TMP16]], i32 0
1009; CHECK-NEXT:    store <2 x i32> [[PREDPHI]], ptr [[TMP17]], align 4
1010; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
1011; CHECK-NEXT:    [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
1012; CHECK-NEXT:    br i1 [[TMP18]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP22:![0-9]+]]
1013; CHECK:       [[MIDDLE_BLOCK]]:
1014; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
1015; CHECK:       [[SCALAR_PH]]:
1016; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
1017; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
1018; CHECK:       [[LOOP_HEADER]]:
1019; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
1020; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
1021; CHECK-NEXT:    [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
1022; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
1023; CHECK-NEXT:    br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
1024; CHECK:       [[LOOP_THEN]]:
1025; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]]
1026; CHECK-NEXT:    [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 1
1027; CHECK-NEXT:    br label %[[LOOP_LATCH]]
1028; CHECK:       [[LOOP_LATCH]]:
1029; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
1030; CHECK-NEXT:    [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
1031; CHECK-NEXT:    store i32 [[MERGE]], ptr [[GEP_C]], align 4
1032; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
1033; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
1034; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP23:![0-9]+]]
1035; CHECK:       [[EXIT]]:
1036; CHECK-NEXT:    ret void
1037;
1038entry:
1039  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %a, i64 3999) ]
1040  br label %loop.header
1041
1042loop.header:
1043  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
1044  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
1045  %l.b = load i32, ptr %gep.b, align 4
1046  %c.1 = icmp sge i32 %l.b, 0
1047  br i1 %c.1, label %loop.latch, label %loop.then
1048
1049loop.then:
1050  %gep.a = getelementptr i32, ptr %a, i64 %iv
1051  %l.a = load i32, ptr %gep.a, align 1
1052  br label %loop.latch
1053
1054loop.latch:
1055  %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
1056  %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
1057  store i32 %merge, ptr %gep.c, align 4
1058  %iv.next = add nuw nsw i64 %iv, 1
1059  %ec = icmp eq i64 %iv.next, 1000
1060  br i1 %ec, label %exit, label %loop.header
1061
1062exit:
1063  ret void
1064}
1065
1066define void @align_and_deref_assumption_in_preheader_constant_trip_count_align_4(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
1067; CHECK-LABEL: define void @align_and_deref_assumption_in_preheader_constant_trip_count_align_4(
1068; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
1069; CHECK-NEXT:  [[ENTRY:.*]]:
1070; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 4), "dereferenceable"(ptr [[A]], i64 4000) ]
1071; CHECK-NEXT:    br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
1072; CHECK:       [[VECTOR_PH]]:
1073; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
1074; CHECK:       [[VECTOR_BODY]]:
1075; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
1076; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
1077; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
1078; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0
1079; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4
1080; CHECK-NEXT:    [[TMP3:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
1081; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr i32, ptr [[A]], i64 [[TMP0]]
1082; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr i32, ptr [[TMP4]], i32 0
1083; CHECK-NEXT:    [[WIDE_LOAD1:%.*]] = load <2 x i32>, ptr [[TMP5]], align 4
1084; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[WIDE_LOAD1]]
1085; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
1086; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i32 0
1087; CHECK-NEXT:    store <2 x i32> [[PREDPHI]], ptr [[TMP7]], align 4
1088; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
1089; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
1090; CHECK-NEXT:    br i1 [[TMP8]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP24:![0-9]+]]
1091; CHECK:       [[MIDDLE_BLOCK]]:
1092; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
1093; CHECK:       [[SCALAR_PH]]:
1094; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
1095; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
1096; CHECK:       [[LOOP_HEADER]]:
1097; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
1098; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
1099; CHECK-NEXT:    [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
1100; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
1101; CHECK-NEXT:    br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
1102; CHECK:       [[LOOP_THEN]]:
1103; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]]
1104; CHECK-NEXT:    [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4
1105; CHECK-NEXT:    br label %[[LOOP_LATCH]]
1106; CHECK:       [[LOOP_LATCH]]:
1107; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
1108; CHECK-NEXT:    [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
1109; CHECK-NEXT:    store i32 [[MERGE]], ptr [[GEP_C]], align 4
1110; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
1111; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
1112; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP25:![0-9]+]]
1113; CHECK:       [[EXIT]]:
1114; CHECK-NEXT:    ret void
1115;
1116entry:
1117  call void @llvm.assume(i1 true) [ "align"(ptr %a, i64 4), "dereferenceable"(ptr %a, i64 4000) ]
1118  br label %loop.header
1119
1120loop.header:
1121  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
1122  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
1123  %l.b = load i32, ptr %gep.b, align 4
1124  %c.1 = icmp sge i32 %l.b, 0
1125  br i1 %c.1, label %loop.latch, label %loop.then
1126
1127loop.then:
1128  %gep.a = getelementptr i32, ptr %a, i64 %iv
1129  %l.a = load i32, ptr %gep.a, align 4
1130  br label %loop.latch
1131
1132loop.latch:
1133  %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
1134  %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
1135  store i32 %merge, ptr %gep.c, align 4
1136  %iv.next = add nuw nsw i64 %iv, 1
1137  %ec = icmp eq i64 %iv.next, 1000
1138  br i1 %ec, label %exit, label %loop.header
1139
1140exit:
1141  ret void
1142}
1143
1144
1145define void @deref_assumption_in_preheader_constant_trip_count_align_4_known_via_argument_attr(ptr noalias align 4 %a, ptr noalias %b, ptr noalias %c) nofree nosync{
1146; CHECK-LABEL: define void @deref_assumption_in_preheader_constant_trip_count_align_4_known_via_argument_attr(
1147; CHECK-SAME: ptr noalias align 4 [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
1148; CHECK-NEXT:  [[ENTRY:.*]]:
1149; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A]], i64 4000) ]
1150; CHECK-NEXT:    br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
1151; CHECK:       [[VECTOR_PH]]:
1152; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
1153; CHECK:       [[VECTOR_BODY]]:
1154; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
1155; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
1156; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
1157; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0
1158; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4
1159; CHECK-NEXT:    [[TMP3:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
1160; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr i32, ptr [[A]], i64 [[TMP0]]
1161; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr i32, ptr [[TMP6]], i32 0
1162; CHECK-NEXT:    [[TMP15:%.*]] = load <2 x i32>, ptr [[TMP5]], align 4
1163; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP15]]
1164; CHECK-NEXT:    [[TMP16:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
1165; CHECK-NEXT:    [[TMP17:%.*]] = getelementptr inbounds i32, ptr [[TMP16]], i32 0
1166; CHECK-NEXT:    store <2 x i32> [[PREDPHI]], ptr [[TMP17]], align 4
1167; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
1168; CHECK-NEXT:    [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
1169; CHECK-NEXT:    br i1 [[TMP18]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP26:![0-9]+]]
1170; CHECK:       [[MIDDLE_BLOCK]]:
1171; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
1172; CHECK:       [[SCALAR_PH]]:
1173; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
1174; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
1175; CHECK:       [[LOOP_HEADER]]:
1176; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
1177; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
1178; CHECK-NEXT:    [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
1179; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
1180; CHECK-NEXT:    br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
1181; CHECK:       [[LOOP_THEN]]:
1182; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]]
1183; CHECK-NEXT:    [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4
1184; CHECK-NEXT:    br label %[[LOOP_LATCH]]
1185; CHECK:       [[LOOP_LATCH]]:
1186; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
1187; CHECK-NEXT:    [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
1188; CHECK-NEXT:    store i32 [[MERGE]], ptr [[GEP_C]], align 4
1189; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
1190; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
1191; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP27:![0-9]+]]
1192; CHECK:       [[EXIT]]:
1193; CHECK-NEXT:    ret void
1194;
1195entry:
1196  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %a, i64 4000) ]
1197  br label %loop.header
1198
1199loop.header:
1200  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
1201  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
1202  %l.b = load i32, ptr %gep.b, align 4
1203  %c.1 = icmp sge i32 %l.b, 0
1204  br i1 %c.1, label %loop.latch, label %loop.then
1205
1206loop.then:
1207  %gep.a = getelementptr i32, ptr %a, i64 %iv
1208  %l.a = load i32, ptr %gep.a, align 4
1209  br label %loop.latch
1210
1211loop.latch:
1212  %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
1213  %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
1214  store i32 %merge, ptr %gep.c, align 4
1215  %iv.next = add nuw nsw i64 %iv, 1
1216  %ec = icmp eq i64 %iv.next, 1000
1217  br i1 %ec, label %exit, label %loop.header
1218
1219exit:
1220  ret void
1221}
1222
1223define void @deref_assumption_in_preheader_constant_trip_count_align_4_not_known(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
1224; CHECK-LABEL: define void @deref_assumption_in_preheader_constant_trip_count_align_4_not_known(
1225; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
1226; CHECK-NEXT:  [[ENTRY:.*]]:
1227; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A]], i64 4000) ]
1228; CHECK-NEXT:    br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
1229; CHECK:       [[VECTOR_PH]]:
1230; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
1231; CHECK:       [[VECTOR_BODY]]:
1232; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]
1233; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
1234; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
1235; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0
1236; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4
1237; CHECK-NEXT:    [[TMP3:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
1238; CHECK-NEXT:    [[TMP4:%.*]] = xor <2 x i1> [[TMP3]], splat (i1 true)
1239; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <2 x i1> [[TMP4]], i32 0
1240; CHECK-NEXT:    br i1 [[TMP5]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]
1241; CHECK:       [[PRED_LOAD_IF]]:
1242; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr i32, ptr [[A]], i64 [[TMP0]]
1243; CHECK-NEXT:    [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 4
1244; CHECK-NEXT:    [[TMP8:%.*]] = insertelement <2 x i32> poison, i32 [[TMP7]], i32 0
1245; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE]]
1246; CHECK:       [[PRED_LOAD_CONTINUE]]:
1247; CHECK-NEXT:    [[TMP9:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP8]], %[[PRED_LOAD_IF]] ]
1248; CHECK-NEXT:    [[TMP10:%.*]] = extractelement <2 x i1> [[TMP4]], i32 1
1249; CHECK-NEXT:    br i1 [[TMP10]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]
1250; CHECK:       [[PRED_LOAD_IF1]]:
1251; CHECK-NEXT:    [[TMP11:%.*]] = add i64 [[INDEX]], 1
1252; CHECK-NEXT:    [[TMP12:%.*]] = getelementptr i32, ptr [[A]], i64 [[TMP11]]
1253; CHECK-NEXT:    [[TMP13:%.*]] = load i32, ptr [[TMP12]], align 4
1254; CHECK-NEXT:    [[TMP14:%.*]] = insertelement <2 x i32> [[TMP9]], i32 [[TMP13]], i32 1
1255; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE2]]
1256; CHECK:       [[PRED_LOAD_CONTINUE2]]:
1257; CHECK-NEXT:    [[TMP15:%.*]] = phi <2 x i32> [ [[TMP9]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP14]], %[[PRED_LOAD_IF1]] ]
1258; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP15]]
1259; CHECK-NEXT:    [[TMP16:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
1260; CHECK-NEXT:    [[TMP17:%.*]] = getelementptr inbounds i32, ptr [[TMP16]], i32 0
1261; CHECK-NEXT:    store <2 x i32> [[PREDPHI]], ptr [[TMP17]], align 4
1262; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
1263; CHECK-NEXT:    [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
1264; CHECK-NEXT:    br i1 [[TMP18]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP28:![0-9]+]]
1265; CHECK:       [[MIDDLE_BLOCK]]:
1266; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
1267; CHECK:       [[SCALAR_PH]]:
1268; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
1269; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
1270; CHECK:       [[LOOP_HEADER]]:
1271; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
1272; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
1273; CHECK-NEXT:    [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
1274; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
1275; CHECK-NEXT:    br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
1276; CHECK:       [[LOOP_THEN]]:
1277; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]]
1278; CHECK-NEXT:    [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4
1279; CHECK-NEXT:    br label %[[LOOP_LATCH]]
1280; CHECK:       [[LOOP_LATCH]]:
1281; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
1282; CHECK-NEXT:    [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
1283; CHECK-NEXT:    store i32 [[MERGE]], ptr [[GEP_C]], align 4
1284; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
1285; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
1286; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP29:![0-9]+]]
1287; CHECK:       [[EXIT]]:
1288; CHECK-NEXT:    ret void
1289;
1290entry:
1291  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %a, i64 4000) ]
1292  br label %loop.header
1293
1294loop.header:
1295  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
1296  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
1297  %l.b = load i32, ptr %gep.b, align 4
1298  %c.1 = icmp sge i32 %l.b, 0
1299  br i1 %c.1, label %loop.latch, label %loop.then
1300
1301loop.then:
1302  %gep.a = getelementptr i32, ptr %a, i64 %iv
1303  %l.a = load i32, ptr %gep.a, align 4
1304  br label %loop.latch
1305
1306loop.latch:
1307  %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
1308  %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
1309  store i32 %merge, ptr %gep.c, align 4
1310  %iv.next = add nuw nsw i64 %iv, 1
1311  %ec = icmp eq i64 %iv.next, 1000
1312  br i1 %ec, label %exit, label %loop.header
1313
1314exit:
1315  ret void
1316}
1317
1318define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_4(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{
1319; CHECK-LABEL: define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_4(
1320; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
1321; CHECK-NEXT:  [[ENTRY:.*]]:
1322; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A]], i64 3999) ]
1323; CHECK-NEXT:    br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
1324; CHECK:       [[VECTOR_PH]]:
1325; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
1326; CHECK:       [[VECTOR_BODY]]:
1327; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]
1328; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
1329; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
1330; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0
1331; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4
1332; CHECK-NEXT:    [[TMP3:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
1333; CHECK-NEXT:    [[TMP4:%.*]] = xor <2 x i1> [[TMP3]], splat (i1 true)
1334; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <2 x i1> [[TMP4]], i32 0
1335; CHECK-NEXT:    br i1 [[TMP5]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]
1336; CHECK:       [[PRED_LOAD_IF]]:
1337; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr i32, ptr [[A]], i64 [[TMP0]]
1338; CHECK-NEXT:    [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 4
1339; CHECK-NEXT:    [[TMP8:%.*]] = insertelement <2 x i32> poison, i32 [[TMP7]], i32 0
1340; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE]]
1341; CHECK:       [[PRED_LOAD_CONTINUE]]:
1342; CHECK-NEXT:    [[TMP9:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP8]], %[[PRED_LOAD_IF]] ]
1343; CHECK-NEXT:    [[TMP10:%.*]] = extractelement <2 x i1> [[TMP4]], i32 1
1344; CHECK-NEXT:    br i1 [[TMP10]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]
1345; CHECK:       [[PRED_LOAD_IF1]]:
1346; CHECK-NEXT:    [[TMP11:%.*]] = add i64 [[INDEX]], 1
1347; CHECK-NEXT:    [[TMP12:%.*]] = getelementptr i32, ptr [[A]], i64 [[TMP11]]
1348; CHECK-NEXT:    [[TMP13:%.*]] = load i32, ptr [[TMP12]], align 4
1349; CHECK-NEXT:    [[TMP14:%.*]] = insertelement <2 x i32> [[TMP9]], i32 [[TMP13]], i32 1
1350; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE2]]
1351; CHECK:       [[PRED_LOAD_CONTINUE2]]:
1352; CHECK-NEXT:    [[TMP15:%.*]] = phi <2 x i32> [ [[TMP9]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP14]], %[[PRED_LOAD_IF1]] ]
1353; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP15]]
1354; CHECK-NEXT:    [[TMP16:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
1355; CHECK-NEXT:    [[TMP17:%.*]] = getelementptr inbounds i32, ptr [[TMP16]], i32 0
1356; CHECK-NEXT:    store <2 x i32> [[PREDPHI]], ptr [[TMP17]], align 4
1357; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
1358; CHECK-NEXT:    [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
1359; CHECK-NEXT:    br i1 [[TMP18]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP30:![0-9]+]]
1360; CHECK:       [[MIDDLE_BLOCK]]:
1361; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
1362; CHECK:       [[SCALAR_PH]]:
1363; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
1364; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
1365; CHECK:       [[LOOP_HEADER]]:
1366; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
1367; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
1368; CHECK-NEXT:    [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
1369; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
1370; CHECK-NEXT:    br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
1371; CHECK:       [[LOOP_THEN]]:
1372; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]]
1373; CHECK-NEXT:    [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4
1374; CHECK-NEXT:    br label %[[LOOP_LATCH]]
1375; CHECK:       [[LOOP_LATCH]]:
1376; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
1377; CHECK-NEXT:    [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
1378; CHECK-NEXT:    store i32 [[MERGE]], ptr [[GEP_C]], align 4
1379; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
1380; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
1381; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP31:![0-9]+]]
1382; CHECK:       [[EXIT]]:
1383; CHECK-NEXT:    ret void
1384;
1385entry:
1386  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %a, i64 3999) ]
1387  br label %loop.header
1388
1389loop.header:
1390  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
1391  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
1392  %l.b = load i32, ptr %gep.b, align 4
1393  %c.1 = icmp sge i32 %l.b, 0
1394  br i1 %c.1, label %loop.latch, label %loop.then
1395
1396loop.then:
1397  %gep.a = getelementptr i32, ptr %a, i64 %iv
1398  %l.a = load i32, ptr %gep.a, align 4
1399  br label %loop.latch
1400
1401loop.latch:
1402  %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
1403  %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
1404  store i32 %merge, ptr %gep.c, align 4
1405  %iv.next = add nuw nsw i64 %iv, 1
1406  %ec = icmp eq i64 %iv.next, 1000
1407  br i1 %ec, label %exit, label %loop.header
1408
1409exit:
1410  ret void
1411}
1412
1413; %a may be freed between the dereferenceable assumption and accesses.
1414; It is not safe to use with -use-dereferenceable-at-point-semantics.
1415define void @may_free_align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(ptr noalias %a, ptr noalias %b, ptr noalias %c) {
1416; CHECK-LABEL: define void @may_free_align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(
1417; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) {
1418; CHECK-NEXT:  [[ENTRY:.*]]:
1419; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 4), "dereferenceable"(ptr [[A]], i64 4) ]
1420; CHECK-NEXT:    call void @may_free()
1421; CHECK-NEXT:    br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
1422; CHECK:       [[VECTOR_PH]]:
1423; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
1424; CHECK:       [[VECTOR_BODY]]:
1425; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]
1426; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
1427; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
1428; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0
1429; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4
1430; CHECK-NEXT:    [[TMP3:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
1431; CHECK-NEXT:    [[TMP4:%.*]] = xor <2 x i1> [[TMP3]], splat (i1 true)
1432; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <2 x i1> [[TMP4]], i32 0
1433; CHECK-NEXT:    br i1 [[TMP5]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]
1434; CHECK:       [[PRED_LOAD_IF]]:
1435; CHECK-NEXT:    [[TMP15:%.*]] = load i32, ptr [[A]], align 4
1436; CHECK-NEXT:    [[TMP7:%.*]] = insertelement <2 x i32> poison, i32 [[TMP15]], i32 0
1437; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE]]
1438; CHECK:       [[PRED_LOAD_CONTINUE]]:
1439; CHECK-NEXT:    [[TMP12:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP7]], %[[PRED_LOAD_IF]] ]
1440; CHECK-NEXT:    [[TMP13:%.*]] = extractelement <2 x i1> [[TMP4]], i32 1
1441; CHECK-NEXT:    br i1 [[TMP13]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]
1442; CHECK:       [[PRED_LOAD_IF1]]:
1443; CHECK-NEXT:    [[TMP14:%.*]] = load i32, ptr [[A]], align 4
1444; CHECK-NEXT:    [[TMP16:%.*]] = insertelement <2 x i32> [[TMP12]], i32 [[TMP14]], i32 1
1445; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE2]]
1446; CHECK:       [[PRED_LOAD_CONTINUE2]]:
1447; CHECK-NEXT:    [[TMP11:%.*]] = phi <2 x i32> [ [[TMP12]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP16]], %[[PRED_LOAD_IF1]] ]
1448; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP11]]
1449; CHECK-NEXT:    [[TMP8:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
1450; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds i32, ptr [[TMP8]], i32 0
1451; CHECK-NEXT:    store <2 x i32> [[PREDPHI]], ptr [[TMP9]], align 4
1452; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
1453; CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
1454; CHECK-NEXT:    br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP32:![0-9]+]]
1455; CHECK:       [[MIDDLE_BLOCK]]:
1456; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
1457; CHECK:       [[SCALAR_PH]]:
1458; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
1459; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
1460; CHECK:       [[LOOP_HEADER]]:
1461; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
1462; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
1463; CHECK-NEXT:    [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
1464; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
1465; CHECK-NEXT:    br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
1466; CHECK:       [[LOOP_THEN]]:
1467; CHECK-NEXT:    [[L_A:%.*]] = load i32, ptr [[A]], align 4
1468; CHECK-NEXT:    br label %[[LOOP_LATCH]]
1469; CHECK:       [[LOOP_LATCH]]:
1470; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
1471; CHECK-NEXT:    [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
1472; CHECK-NEXT:    store i32 [[MERGE]], ptr [[GEP_C]], align 4
1473; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
1474; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
1475; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP33:![0-9]+]]
1476; CHECK:       [[EXIT]]:
1477; CHECK-NEXT:    ret void
1478;
1479entry:
1480  call void @llvm.assume(i1 true) [ "align"(ptr %a, i64 4), "dereferenceable"(ptr %a, i64 4) ]
1481  call void @may_free()
1482  br label %loop.header
1483
1484loop.header:
1485  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
1486  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
1487  %l.b = load i32, ptr %gep.b, align 4
1488  %c.1 = icmp sge i32 %l.b, 0
1489  br i1 %c.1, label %loop.latch, label %loop.then
1490
1491loop.then:
1492  %l.a = load i32, ptr %a, align 4
1493  br label %loop.latch
1494
1495loop.latch:
1496  %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
1497  %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
1498  store i32 %merge, ptr %gep.c, align 4
1499  %iv.next = add nuw nsw i64 %iv, 1
1500  %ec = icmp eq i64 %iv.next, 1000
1501  br i1 %ec, label %exit, label %loop.header
1502
1503exit:
1504  ret void
1505}
1506
1507; %a may be freed between the dereferenceable assumption and accesses.
1508; It is not safe to use with -use-dereferenceable-at-point-semantics.
1509define void @may_free_local_ptr_align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(ptr noalias %b, ptr noalias %c) nofree nosync {
1510; CHECK-LABEL: define void @may_free_local_ptr_align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(
1511; CHECK-SAME: ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] {
1512; CHECK-NEXT:  [[ENTRY:.*]]:
1513; CHECK-NEXT:    [[A:%.*]] = call ptr @get_ptr()
1514; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 4), "dereferenceable"(ptr [[A]], i64 4) ]
1515; CHECK-NEXT:    call void @may_free()
1516; CHECK-NEXT:    br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
1517; CHECK:       [[VECTOR_PH]]:
1518; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
1519; CHECK:       [[VECTOR_BODY]]:
1520; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ]
1521; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
1522; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]]
1523; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0
1524; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4
1525; CHECK-NEXT:    [[TMP3:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer
1526; CHECK-NEXT:    [[TMP4:%.*]] = xor <2 x i1> [[TMP3]], splat (i1 true)
1527; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <2 x i1> [[TMP4]], i32 0
1528; CHECK-NEXT:    br i1 [[TMP5]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]]
1529; CHECK:       [[PRED_LOAD_IF]]:
1530; CHECK-NEXT:    [[TMP6:%.*]] = load i32, ptr [[A]], align 4
1531; CHECK-NEXT:    [[TMP7:%.*]] = insertelement <2 x i32> poison, i32 [[TMP6]], i32 0
1532; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE]]
1533; CHECK:       [[PRED_LOAD_CONTINUE]]:
1534; CHECK-NEXT:    [[TMP8:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP7]], %[[PRED_LOAD_IF]] ]
1535; CHECK-NEXT:    [[TMP9:%.*]] = extractelement <2 x i1> [[TMP4]], i32 1
1536; CHECK-NEXT:    br i1 [[TMP9]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]]
1537; CHECK:       [[PRED_LOAD_IF1]]:
1538; CHECK-NEXT:    [[TMP10:%.*]] = load i32, ptr [[A]], align 4
1539; CHECK-NEXT:    [[TMP11:%.*]] = insertelement <2 x i32> [[TMP8]], i32 [[TMP10]], i32 1
1540; CHECK-NEXT:    br label %[[PRED_LOAD_CONTINUE2]]
1541; CHECK:       [[PRED_LOAD_CONTINUE2]]:
1542; CHECK-NEXT:    [[TMP12:%.*]] = phi <2 x i32> [ [[TMP8]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP11]], %[[PRED_LOAD_IF1]] ]
1543; CHECK-NEXT:    [[PREDPHI:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP12]]
1544; CHECK-NEXT:    [[TMP13:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]]
1545; CHECK-NEXT:    [[TMP14:%.*]] = getelementptr inbounds i32, ptr [[TMP13]], i32 0
1546; CHECK-NEXT:    store <2 x i32> [[PREDPHI]], ptr [[TMP14]], align 4
1547; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
1548; CHECK-NEXT:    [[TMP15:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
1549; CHECK-NEXT:    br i1 [[TMP15]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP34:![0-9]+]]
1550; CHECK:       [[MIDDLE_BLOCK]]:
1551; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
1552; CHECK:       [[SCALAR_PH]]:
1553; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
1554; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
1555; CHECK:       [[LOOP_HEADER]]:
1556; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
1557; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
1558; CHECK-NEXT:    [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4
1559; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i32 [[L_B]], 0
1560; CHECK-NEXT:    br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]]
1561; CHECK:       [[LOOP_THEN]]:
1562; CHECK-NEXT:    [[L_A:%.*]] = load i32, ptr [[A]], align 4
1563; CHECK-NEXT:    br label %[[LOOP_LATCH]]
1564; CHECK:       [[LOOP_LATCH]]:
1565; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ]
1566; CHECK-NEXT:    [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]]
1567; CHECK-NEXT:    store i32 [[MERGE]], ptr [[GEP_C]], align 4
1568; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
1569; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000
1570; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP35:![0-9]+]]
1571; CHECK:       [[EXIT]]:
1572; CHECK-NEXT:    ret void
1573;
1574entry:
1575  %a = call ptr @get_ptr()
1576  call void @llvm.assume(i1 true) [ "align"(ptr %a, i64 4), "dereferenceable"(ptr %a, i64 4) ]
1577  call void @may_free()
1578  br label %loop.header
1579
1580loop.header:
1581  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
1582  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
1583  %l.b = load i32, ptr %gep.b, align 4
1584  %c.1 = icmp sge i32 %l.b, 0
1585  br i1 %c.1, label %loop.latch, label %loop.then
1586
1587loop.then:
1588  %l.a = load i32, ptr %a, align 4
1589  br label %loop.latch
1590
1591loop.latch:
1592  %merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ]
1593  %gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
1594  store i32 %merge, ptr %gep.c, align 4
1595  %iv.next = add nuw nsw i64 %iv, 1
1596  %ec = icmp eq i64 %iv.next, 1000
1597  br i1 %ec, label %exit, label %loop.header
1598
1599exit:
1600  ret void
1601}
1602
1603declare ptr @get_ptr()
1604declare void @may_free()
1605
1606;.
1607; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]}
1608; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1}
1609; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"}
1610; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META2]], [[META1]]}
1611; CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[META1]], [[META2]]}
1612; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[META2]], [[META1]]}
1613; CHECK: [[LOOP6]] = distinct !{[[LOOP6]], [[META1]], [[META2]]}
1614; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META2]], [[META1]]}
1615; CHECK: [[LOOP8]] = distinct !{[[LOOP8]], [[META1]], [[META2]]}
1616; CHECK: [[LOOP9]] = distinct !{[[LOOP9]], [[META2]], [[META1]]}
1617; CHECK: [[LOOP10]] = distinct !{[[LOOP10]], [[META1]], [[META2]]}
1618; CHECK: [[LOOP11]] = distinct !{[[LOOP11]], [[META2]], [[META1]]}
1619; CHECK: [[LOOP12]] = distinct !{[[LOOP12]], [[META1]], [[META2]]}
1620; CHECK: [[LOOP13]] = distinct !{[[LOOP13]], [[META2]], [[META1]]}
1621; CHECK: [[LOOP14]] = distinct !{[[LOOP14]], [[META1]], [[META2]]}
1622; CHECK: [[LOOP15]] = distinct !{[[LOOP15]], [[META2]], [[META1]]}
1623; CHECK: [[LOOP16]] = distinct !{[[LOOP16]], [[META1]], [[META2]]}
1624; CHECK: [[LOOP17]] = distinct !{[[LOOP17]], [[META2]], [[META1]]}
1625; CHECK: [[LOOP18]] = distinct !{[[LOOP18]], [[META1]], [[META2]]}
1626; CHECK: [[LOOP19]] = distinct !{[[LOOP19]], [[META2]], [[META1]]}
1627; CHECK: [[LOOP20]] = distinct !{[[LOOP20]], [[META1]], [[META2]]}
1628; CHECK: [[LOOP21]] = distinct !{[[LOOP21]], [[META2]], [[META1]]}
1629; CHECK: [[LOOP22]] = distinct !{[[LOOP22]], [[META1]], [[META2]]}
1630; CHECK: [[LOOP23]] = distinct !{[[LOOP23]], [[META2]], [[META1]]}
1631; CHECK: [[LOOP24]] = distinct !{[[LOOP24]], [[META1]], [[META2]]}
1632; CHECK: [[LOOP25]] = distinct !{[[LOOP25]], [[META2]], [[META1]]}
1633; CHECK: [[LOOP26]] = distinct !{[[LOOP26]], [[META1]], [[META2]]}
1634; CHECK: [[LOOP27]] = distinct !{[[LOOP27]], [[META2]], [[META1]]}
1635; CHECK: [[LOOP28]] = distinct !{[[LOOP28]], [[META1]], [[META2]]}
1636; CHECK: [[LOOP29]] = distinct !{[[LOOP29]], [[META2]], [[META1]]}
1637; CHECK: [[LOOP30]] = distinct !{[[LOOP30]], [[META1]], [[META2]]}
1638; CHECK: [[LOOP31]] = distinct !{[[LOOP31]], [[META2]], [[META1]]}
1639; CHECK: [[LOOP32]] = distinct !{[[LOOP32]], [[META1]], [[META2]]}
1640; CHECK: [[LOOP33]] = distinct !{[[LOOP33]], [[META2]], [[META1]]}
1641; CHECK: [[LOOP34]] = distinct !{[[LOOP34]], [[META1]], [[META2]]}
1642; CHECK: [[LOOP35]] = distinct !{[[LOOP35]], [[META2]], [[META1]]}
1643;.
1644