[TTI] getTypeBasedIntrinsicInstrCost - add basic handling for strided load/store...
[llvm-project.git] / llvm / test / Transforms / LoopVectorize / dereferenceable-info-from-assumption-constant-size.ll
blob90671689f1dce05c15bcda36e042cb9675d4501b
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
4 declare void @llvm.assume(i1)
6 define 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
79 entry:
80   br label %loop.header
82 loop.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
91 loop.then:
92   %l.a = load i32, ptr %gep.a, align 4
93   br label %loop.latch
95 loop.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
103 exit:
104   ret void
107 define 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
157 entry:
158   call void @llvm.assume(i1 true) [ "align"(ptr %a, i64 4), "dereferenceable"(ptr %a, i64 4) ]
159   br label %loop.header
161 loop.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
168 loop.then:
169   %l.a = load i32, ptr %a, align 4
170   br label %loop.latch
172 loop.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
180 exit:
181   ret void
184 define 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
257 entry:
258   br label %loop.header
260 loop.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
269 loop.then:
270   %l.a = load i32, ptr %gep.a, align 4
271   br label %loop.latch
273 loop.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
281 exit:
282   ret void
285 define 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
358 entry:
359   br label %loop.header
361 loop.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
370 loop.then:
371   %l.a = load i32, ptr %gep.a, align 1
372   br label %loop.latch
374 loop.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
382 exit:
383   ret void
386 define 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
459 entry:
460   br label %loop.header
462 loop.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
471 loop.then:
472   %l.a = load i32, ptr %gep.a, align 4
473   br label %loop.latch
475 loop.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
483 exit:
484   ret void
487 define 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
560 entry:
561   br label %loop.header
563 loop.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
572 loop.then:
573   %l.a = load i32, ptr %gep.a, align 4
574   br label %loop.latch
576 loop.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
584 exit:
585   ret void
588 define 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
657 entry:
658   br label %loop.header
660 loop.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
667 loop.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
673 loop.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
681 exit:
682   ret void
685 define 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
760 entry:
761   br label %loop.header
763 loop.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
771 loop.then:
772   %l.a = load i32, ptr %gep.a, align 4
773   br label %loop.latch
775 loop.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
784 exit:
785   ret void
788 define 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
865 entry:
866   br label %loop.header
868 loop.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
877 loop.then:
878   %l.a = load i32, ptr %gep.a, align 4
879   br label %loop.latch
881 loop.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
889 exit:
890   ret void
893 define 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
943 entry:
944   call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %a, i64 4000) ]
945   br label %loop.header
947 loop.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
954 loop.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
959 loop.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
967 exit:
968   ret void
971 define 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
1038 entry:
1039   call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %a, i64 3999) ]
1040   br label %loop.header
1042 loop.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
1049 loop.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
1054 loop.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
1062 exit:
1063   ret void
1066 define 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
1116 entry:
1117   call void @llvm.assume(i1 true) [ "align"(ptr %a, i64 4), "dereferenceable"(ptr %a, i64 4000) ]
1118   br label %loop.header
1120 loop.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
1127 loop.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
1132 loop.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
1140 exit:
1141   ret void
1145 define 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
1195 entry:
1196   call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %a, i64 4000) ]
1197   br label %loop.header
1199 loop.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
1206 loop.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
1211 loop.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
1219 exit:
1220   ret void
1223 define 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
1290 entry:
1291   call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %a, i64 4000) ]
1292   br label %loop.header
1294 loop.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
1301 loop.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
1306 loop.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
1314 exit:
1315   ret void
1318 define 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
1385 entry:
1386   call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %a, i64 3999) ]
1387   br label %loop.header
1389 loop.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
1396 loop.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
1401 loop.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
1409 exit:
1410   ret void
1413 ; %a may be freed between the dereferenceable assumption and accesses.
1414 ; It is not safe to use with -use-dereferenceable-at-point-semantics.
1415 define 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
1479 entry:
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
1484 loop.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
1491 loop.then:
1492   %l.a = load i32, ptr %a, align 4
1493   br label %loop.latch
1495 loop.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
1503 exit:
1504   ret void
1507 ; %a may be freed between the dereferenceable assumption and accesses.
1508 ; It is not safe to use with -use-dereferenceable-at-point-semantics.
1509 define 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
1574 entry:
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
1580 loop.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
1587 loop.then:
1588   %l.a = load i32, ptr %a, align 4
1589   br label %loop.latch
1591 loop.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
1599 exit:
1600   ret void
1603 declare ptr @get_ptr()
1604 declare void @may_free()
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]]}