1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=licm -verify-memoryssa < %s | FileCheck %s
3 ; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop-mssa(loop-simplifycfg,licm)' -verify-memoryssa -S < %s | FileCheck %s
5 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
6 target triple = "x86_64-unknown-linux-gnu"
8 ; This test represents the following function:
9 ; void test1(int * __restrict__ a, int * __restrict__ b, int &c, int n) {
10 ; for (int i = 0; i < n; ++i)
14 ; and we want to hoist the load of %c out of the loop. This can be done only
15 ; because the dereferenceable attribute is on %c.
17 define void @test1(ptr noalias nocapture %a, ptr noalias nocapture readonly %b, ptr nocapture readonly nonnull dereferenceable(4) align 4 %c, i32 %n) #0 {
18 ; CHECK-LABEL: @test1(
20 ; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
21 ; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
22 ; CHECK: for.body.preheader:
23 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[C:%.*]], align 4
24 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
26 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
27 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
28 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
29 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP1]], 0
30 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
32 ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]
33 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4
34 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP0]]
35 ; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4
36 ; CHECK-NEXT: br label [[FOR_INC]]
38 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
39 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
40 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
41 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
42 ; CHECK: for.end.loopexit:
43 ; CHECK-NEXT: br label [[FOR_END]]
45 ; CHECK-NEXT: ret void
48 %cmp11 = icmp sgt i32 %n, 0
49 br i1 %cmp11, label %for.body, label %for.end
51 for.body: ; preds = %entry, %for.inc
52 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
53 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
54 %0 = load i32, ptr %arrayidx, align 4
55 %cmp1 = icmp sgt i32 %0, 0
56 br i1 %cmp1, label %if.then, label %for.inc
58 if.then: ; preds = %for.body
59 %1 = load i32, ptr %c, align 4
60 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv
61 %2 = load i32, ptr %arrayidx3, align 4
62 %mul = mul nsw i32 %2, %1
63 store i32 %mul, ptr %arrayidx, align 4
66 for.inc: ; preds = %for.body, %if.then
67 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
68 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
69 %exitcond = icmp eq i32 %lftr.wideiv, %n
70 br i1 %exitcond, label %for.end, label %for.body
72 for.end: ; preds = %for.inc, %entry
76 ; This is the same as @test1, but without the dereferenceable attribute on %c.
77 ; Without this attribute, we should not hoist the load of %c.
78 define void @test2(ptr noalias nocapture %a, ptr noalias nocapture readonly %b, ptr nocapture readonly nonnull %c, i32 %n) #0 {
79 ; CHECK-LABEL: @test2(
81 ; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
82 ; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
83 ; CHECK: for.body.preheader:
84 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
86 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
87 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
88 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
89 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 0
90 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
92 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[C:%.*]], align 4
93 ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]
94 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4
95 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP1]]
96 ; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4
97 ; CHECK-NEXT: br label [[FOR_INC]]
99 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
100 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
101 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
102 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
103 ; CHECK: for.end.loopexit:
104 ; CHECK-NEXT: br label [[FOR_END]]
106 ; CHECK-NEXT: ret void
109 %cmp11 = icmp sgt i32 %n, 0
110 br i1 %cmp11, label %for.body, label %for.end
112 for.body: ; preds = %entry, %for.inc
113 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
114 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
115 %0 = load i32, ptr %arrayidx, align 4
116 %cmp1 = icmp sgt i32 %0, 0
117 br i1 %cmp1, label %if.then, label %for.inc
119 if.then: ; preds = %for.body
120 %1 = load i32, ptr %c, align 4
121 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv
122 %2 = load i32, ptr %arrayidx3, align 4
123 %mul = mul nsw i32 %2, %1
124 store i32 %mul, ptr %arrayidx, align 4
127 for.inc: ; preds = %for.body, %if.then
128 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
129 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
130 %exitcond = icmp eq i32 %lftr.wideiv, %n
131 br i1 %exitcond, label %for.end, label %for.body
133 for.end: ; preds = %for.inc, %entry
137 ; This test represents the following function:
138 ; void test3(int * restrict a, int * restrict b, int c[static 3], int n) {
139 ; for (int i = 0; i < n; ++i)
143 ; and we want to hoist the load of c[2] out of the loop. This can be done only
144 ; because the dereferenceable attribute is on %c.
145 define void @test3(ptr noalias nocapture %a, ptr noalias nocapture readonly %b, ptr nocapture readonly dereferenceable(12) align 4 %c, i32 %n) #0 {
146 ; CHECK-LABEL: @test3(
148 ; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
149 ; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
150 ; CHECK: for.body.preheader:
151 ; CHECK-NEXT: [[C2:%.*]] = getelementptr inbounds i32, ptr [[C:%.*]], i64 2
152 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[C2]], align 4
153 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
155 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
156 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
157 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
158 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP1]], 0
159 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
161 ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]
162 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4
163 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP0]]
164 ; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4
165 ; CHECK-NEXT: br label [[FOR_INC]]
167 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
168 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
169 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
170 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
171 ; CHECK: for.end.loopexit:
172 ; CHECK-NEXT: br label [[FOR_END]]
174 ; CHECK-NEXT: ret void
177 %cmp11 = icmp sgt i32 %n, 0
178 br i1 %cmp11, label %for.body, label %for.end
180 for.body: ; preds = %entry, %for.inc
181 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
182 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
183 %0 = load i32, ptr %arrayidx, align 4
184 %cmp1 = icmp sgt i32 %0, 0
185 br i1 %cmp1, label %if.then, label %for.inc
187 if.then: ; preds = %for.body
188 %c2 = getelementptr inbounds i32, ptr %c, i64 2
189 %1 = load i32, ptr %c2, align 4
190 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv
191 %2 = load i32, ptr %arrayidx3, align 4
192 %mul = mul nsw i32 %2, %1
193 store i32 %mul, ptr %arrayidx, align 4
196 for.inc: ; preds = %for.body, %if.then
197 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
198 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
199 %exitcond = icmp eq i32 %lftr.wideiv, %n
200 br i1 %exitcond, label %for.end, label %for.body
202 for.end: ; preds = %for.inc, %entry
206 ; This is the same as @test3, but with a dereferenceable attribute on %c with a
207 ; size too small to cover c[2] (and so we should not hoist it).
208 define void @test4(ptr noalias nocapture %a, ptr noalias nocapture readonly %b, ptr nocapture readonly dereferenceable(11) %c, i32 %n) #0 {
209 ; CHECK-LABEL: @test4(
211 ; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
212 ; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
213 ; CHECK: for.body.preheader:
214 ; CHECK-NEXT: [[C2:%.*]] = getelementptr inbounds i32, ptr [[C:%.*]], i64 2
215 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
217 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
218 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
219 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
220 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 0
221 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
223 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[C2]], align 4
224 ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]
225 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4
226 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP1]]
227 ; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4
228 ; CHECK-NEXT: br label [[FOR_INC]]
230 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
231 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
232 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
233 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
234 ; CHECK: for.end.loopexit:
235 ; CHECK-NEXT: br label [[FOR_END]]
237 ; CHECK-NEXT: ret void
240 %cmp11 = icmp sgt i32 %n, 0
241 br i1 %cmp11, label %for.body, label %for.end
243 for.body: ; preds = %entry, %for.inc
244 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
245 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
246 %0 = load i32, ptr %arrayidx, align 4
247 %cmp1 = icmp sgt i32 %0, 0
248 br i1 %cmp1, label %if.then, label %for.inc
250 if.then: ; preds = %for.body
251 %c2 = getelementptr inbounds i32, ptr %c, i64 2
252 %1 = load i32, ptr %c2, align 4
253 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv
254 %2 = load i32, ptr %arrayidx3, align 4
255 %mul = mul nsw i32 %2, %1
256 store i32 %mul, ptr %arrayidx, align 4
259 for.inc: ; preds = %for.body, %if.then
260 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
261 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
262 %exitcond = icmp eq i32 %lftr.wideiv, %n
263 br i1 %exitcond, label %for.end, label %for.body
265 for.end: ; preds = %for.inc, %entry
269 ; This test represents the following function:
270 ; void test1(int * __restrict__ a, int *b, int &c, int n) {
272 ; for (int i = 0; i < n; ++i)
276 ; and we want to hoist the load of %c out of the loop. This can be done only
277 ; because the dereferenceable_or_null attribute is on %c and there is a null
279 define void @test5(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) align 4 %c, i32 %n) #0 {
280 ; CHECK-LABEL: @test5(
282 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne ptr [[C:%.*]], null
283 ; CHECK-NEXT: br i1 [[NOT_NULL]], label [[NOT_NULL:%.*]], label [[FOR_END:%.*]]
285 ; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
286 ; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END]]
287 ; CHECK: for.body.preheader:
288 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[C]], align 4
289 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
291 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
292 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
293 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
294 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP1]], 0
295 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
297 ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]
298 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4
299 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP0]]
300 ; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4
301 ; CHECK-NEXT: br label [[FOR_INC]]
303 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
304 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
305 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
306 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
307 ; CHECK: for.end.loopexit:
308 ; CHECK-NEXT: br label [[FOR_END]]
310 ; CHECK-NEXT: ret void
313 %not_null = icmp ne ptr %c, null
314 br i1 %not_null, label %not.null, label %for.end
317 %cmp11 = icmp sgt i32 %n, 0
318 br i1 %cmp11, label %for.body, label %for.end
320 for.body: ; preds = %not.null, %for.inc
321 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %not.null ]
322 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
323 %0 = load i32, ptr %arrayidx, align 4
324 %cmp1 = icmp sgt i32 %0, 0
325 br i1 %cmp1, label %if.then, label %for.inc
327 if.then: ; preds = %for.body
328 %1 = load i32, ptr %c, align 4
329 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv
330 %2 = load i32, ptr %arrayidx3, align 4
331 %mul = mul nsw i32 %2, %1
332 store i32 %mul, ptr %arrayidx, align 4
335 for.inc: ; preds = %for.body, %if.then
336 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
337 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
338 %exitcond = icmp eq i32 %lftr.wideiv, %n
339 br i1 %exitcond, label %for.end, label %for.body
341 for.end: ; preds = %for.inc, %entry, %not.null
345 ; This is the same as @test5, but without the null check on %c.
346 ; Without this check, we should not hoist the load of %c.
348 ; This test case has an icmp on c but the use of this comparison is
350 define i1 @test6(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) %c, i32 %n) #0 {
351 ; CHECK-LABEL: @test6(
353 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne ptr [[C:%.*]], null
354 ; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
355 ; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
356 ; CHECK: for.body.preheader:
357 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
359 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
360 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
361 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
362 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 0
363 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
365 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[C]], align 4
366 ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]
367 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4
368 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP1]]
369 ; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4
370 ; CHECK-NEXT: br label [[FOR_INC]]
372 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
373 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
374 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
375 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
376 ; CHECK: for.end.loopexit:
377 ; CHECK-NEXT: br label [[FOR_END]]
379 ; CHECK-NEXT: ret i1 [[NOT_NULL]]
382 %not_null = icmp ne ptr %c, null
383 %cmp11 = icmp sgt i32 %n, 0
384 br i1 %cmp11, label %for.body, label %for.end
386 for.body: ; preds = %entry, %for.inc
387 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
388 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
389 %0 = load i32, ptr %arrayidx, align 4
390 %cmp1 = icmp sgt i32 %0, 0
391 br i1 %cmp1, label %if.then, label %for.inc
393 if.then: ; preds = %for.body
394 %1 = load i32, ptr %c, align 4
395 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv
396 %2 = load i32, ptr %arrayidx3, align 4
397 %mul = mul nsw i32 %2, %1
398 store i32 %mul, ptr %arrayidx, align 4
401 for.inc: ; preds = %for.body, %if.then
402 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
403 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
404 %exitcond = icmp eq i32 %lftr.wideiv, %n
405 br i1 %exitcond, label %for.end, label %for.body
407 for.end: ; preds = %for.inc, %entry
411 ; This test represents the following function:
412 ; void test1(int * __restrict__ a, int *b, int **cptr, int n) {
414 ; for (int i = 0; i < n; ++i)
418 ; and we want to hoist the load of %c out of the loop. This can be done only
419 ; because the dereferenceable meatdata on the c = *cptr load.
420 define void @test7(ptr noalias %a, ptr %b, ptr %cptr, i32 %n) #0 {
421 ; CHECK-LABEL: @test7(
423 ; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable [[META0:![0-9]+]], !align [[META0]]
424 ; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
425 ; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
426 ; CHECK: for.body.preheader:
427 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[C]], align 4
428 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
430 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
431 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
432 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
433 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP1]], 0
434 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
436 ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]
437 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4
438 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP0]]
439 ; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4
440 ; CHECK-NEXT: br label [[FOR_INC]]
442 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
443 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
444 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
445 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
446 ; CHECK: for.end.loopexit:
447 ; CHECK-NEXT: br label [[FOR_END]]
449 ; CHECK-NEXT: ret void
452 %c = load ptr, ptr %cptr, !dereferenceable !0, !align !{i64 4}
453 %cmp11 = icmp sgt i32 %n, 0
454 br i1 %cmp11, label %for.body, label %for.end
456 for.body: ; preds = %entry, %for.inc
457 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
458 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
459 %0 = load i32, ptr %arrayidx, align 4
460 %cmp1 = icmp sgt i32 %0, 0
461 br i1 %cmp1, label %if.then, label %for.inc
463 if.then: ; preds = %for.body
464 %1 = load i32, ptr %c, align 4
465 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv
466 %2 = load i32, ptr %arrayidx3, align 4
467 %mul = mul nsw i32 %2, %1
468 store i32 %mul, ptr %arrayidx, align 4
471 for.inc: ; preds = %for.body, %if.then
472 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
473 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
474 %exitcond = icmp eq i32 %lftr.wideiv, %n
475 br i1 %exitcond, label %for.end, label %for.body
477 for.end: ; preds = %for.inc, %entry
481 ; This test represents the following function:
482 ; void test1(int * __restrict__ a, int *b, int **cptr, int n) {
485 ; for (int i = 0; i < n; ++i)
489 ; and we want to hoist the load of %c out of the loop. This can be done only
490 ; because the dereferenceable_or_null meatdata on the c = *cptr load and there
491 ; is a null check on %c.
492 define void @test8(ptr noalias %a, ptr %b, ptr %cptr, i32 %n) #0 {
493 ; CHECK-LABEL: @test8(
495 ; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable_or_null [[META0]], !align [[META0]]
496 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne ptr [[C]], null
497 ; CHECK-NEXT: br i1 [[NOT_NULL]], label [[NOT_NULL:%.*]], label [[FOR_END:%.*]]
499 ; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
500 ; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END]]
501 ; CHECK: for.body.preheader:
502 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[C]], align 4
503 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
505 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
506 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
507 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
508 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP1]], 0
509 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
511 ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]
512 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4
513 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP0]]
514 ; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4
515 ; CHECK-NEXT: br label [[FOR_INC]]
517 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
518 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
519 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
520 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
521 ; CHECK: for.end.loopexit:
522 ; CHECK-NEXT: br label [[FOR_END]]
524 ; CHECK-NEXT: ret void
527 %c = load ptr, ptr %cptr, !dereferenceable_or_null !0, !align !{i64 4}
528 %not_null = icmp ne ptr %c, null
529 br i1 %not_null, label %not.null, label %for.end
532 %cmp11 = icmp sgt i32 %n, 0
533 br i1 %cmp11, label %for.body, label %for.end
535 for.body: ; preds = %not.null, %for.inc
536 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %not.null ]
537 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
538 %0 = load i32, ptr %arrayidx, align 4
539 %cmp1 = icmp sgt i32 %0, 0
540 br i1 %cmp1, label %if.then, label %for.inc
542 if.then: ; preds = %for.body
543 %1 = load i32, ptr %c, align 4
544 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv
545 %2 = load i32, ptr %arrayidx3, align 4
546 %mul = mul nsw i32 %2, %1
547 store i32 %mul, ptr %arrayidx, align 4
550 for.inc: ; preds = %for.body, %if.then
551 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
552 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
553 %exitcond = icmp eq i32 %lftr.wideiv, %n
554 br i1 %exitcond, label %for.end, label %for.body
556 for.end: ; preds = %for.inc, %entry, %not.null
560 ; This is the same as @test8, but without the null check on %c.
561 ; Without this check, we should not hoist the load of %c.
562 define void @test9(ptr noalias %a, ptr %b, ptr %cptr, i32 %n) #0 {
563 ; CHECK-LABEL: @test9(
565 ; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable_or_null [[META0]]
566 ; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
567 ; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
568 ; CHECK: for.body.preheader:
569 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
571 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
572 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
573 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
574 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 0
575 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
577 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[C]], align 4
578 ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]
579 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4
580 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP1]]
581 ; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4
582 ; CHECK-NEXT: br label [[FOR_INC]]
584 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
585 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
586 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
587 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
588 ; CHECK: for.end.loopexit:
589 ; CHECK-NEXT: br label [[FOR_END]]
591 ; CHECK-NEXT: ret void
594 %c = load ptr, ptr %cptr, !dereferenceable_or_null !0
595 %cmp11 = icmp sgt i32 %n, 0
596 br i1 %cmp11, label %for.body, label %for.end
598 for.body: ; preds = %entry, %for.inc
599 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
600 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
601 %0 = load i32, ptr %arrayidx, align 4
602 %cmp1 = icmp sgt i32 %0, 0
603 br i1 %cmp1, label %if.then, label %for.inc
605 if.then: ; preds = %for.body
606 %1 = load i32, ptr %c, align 4
607 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv
608 %2 = load i32, ptr %arrayidx3, align 4
609 %mul = mul nsw i32 %2, %1
610 store i32 %mul, ptr %arrayidx, align 4
613 for.inc: ; preds = %for.body, %if.then
614 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
615 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
616 %exitcond = icmp eq i32 %lftr.wideiv, %n
617 br i1 %exitcond, label %for.end, label %for.body
619 for.end: ; preds = %for.inc, %entry
623 ; In this test we should be able to only hoist load from %cptr. We can't hoist
624 ; load from %c because it's dereferenceability can depend on %cmp1 condition.
625 ; By moving it out of the loop we break this dependency and can not rely
626 ; on the dereferenceability anymore.
627 ; In other words this test checks that we strip dereferenceability metadata
628 ; after hoisting an instruction.
629 define void @test10(ptr noalias %a, ptr %b, ptr dereferenceable(8) align 8 %cptr, i32 %n) #0 {
630 ; CHECK-LABEL: @test10(
632 ; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
633 ; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
634 ; CHECK: for.body.preheader:
635 ; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8
636 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
638 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
639 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
640 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
641 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 0
642 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
644 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[C]], align 4
645 ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]
646 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4
647 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP1]]
648 ; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4
649 ; CHECK-NEXT: br label [[FOR_INC]]
651 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
652 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
653 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
654 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
655 ; CHECK: for.end.loopexit:
656 ; CHECK-NEXT: br label [[FOR_END]]
658 ; CHECK-NEXT: ret void
661 %cmp11 = icmp sgt i32 %n, 0
662 br i1 %cmp11, label %for.body, label %for.end
664 for.body: ; preds = %entry, %for.inc
665 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
666 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
667 %0 = load i32, ptr %arrayidx, align 4
668 %cmp1 = icmp sgt i32 %0, 0
669 br i1 %cmp1, label %if.then, label %for.inc
671 if.then: ; preds = %for.body
672 %c = load ptr, ptr %cptr, !dereferenceable !0
673 %1 = load i32, ptr %c, align 4
674 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv
675 %2 = load i32, ptr %arrayidx3, align 4
676 %mul = mul nsw i32 %2, %1
677 store i32 %mul, ptr %arrayidx, align 4
680 for.inc: ; preds = %for.body, %if.then
681 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
682 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
683 %exitcond = icmp eq i32 %lftr.wideiv, %n
684 br i1 %exitcond, label %for.end, label %for.body
686 for.end: ; preds = %for.inc, %entry
690 define void @test11(ptr noalias %a, ptr %b, ptr dereferenceable(8) %cptr, i32 %n) #0 {
691 ; CHECK-LABEL: @test11(
693 ; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
694 ; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
695 ; CHECK: for.body.preheader:
696 ; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable [[META0]]
697 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
699 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
700 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
701 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
702 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 0
703 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
705 ; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[C]], align 4
706 ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]
707 ; CHECK-NEXT: [[E:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4
708 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[E]], [[D]]
709 ; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4
710 ; CHECK-NEXT: br label [[FOR_INC]]
712 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
713 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
714 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
715 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
716 ; CHECK: for.end.loopexit:
717 ; CHECK-NEXT: br label [[FOR_END]]
719 ; CHECK-NEXT: ret void
722 %cmp11 = icmp sgt i32 %n, 0
723 br i1 %cmp11, label %for.body, label %for.end
727 for.body: ; preds = %entry, %for.inc
728 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
729 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
730 %0 = load i32, ptr %arrayidx, align 4
731 %cmp1 = icmp sgt i32 %0, 0
732 %c = load ptr, ptr %cptr, !dereferenceable !0
733 br i1 %cmp1, label %if.then, label %for.inc
735 if.then: ; preds = %for.body
736 %d = load i32, ptr %c, align 4
737 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv
738 %e = load i32, ptr %arrayidx3, align 4
739 %mul = mul nsw i32 %e, %d
740 store i32 %mul, ptr %arrayidx, align 4
743 for.inc: ; preds = %for.body, %if.then
744 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
745 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
746 %exitcond = icmp eq i32 %lftr.wideiv, %n
747 br i1 %exitcond, label %for.end, label %for.body
749 for.end: ; preds = %for.inc, %entry
753 declare void @llvm.experimental.guard(i1, ...)
755 ; Prove non-null ness of %c via a guard, not a branch.
756 define void @test12(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) align 4 %c, i32 %n) #0 {
757 ; CHECK-LABEL: @test12(
759 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne ptr [[C:%.*]], null
760 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[NOT_NULL]]) [ "deopt"() ]
761 ; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
762 ; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
763 ; CHECK: for.body.preheader:
764 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[C]], align 4
765 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
767 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
768 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
769 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
770 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP1]], 0
771 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
773 ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]
774 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4
775 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP0]]
776 ; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4
777 ; CHECK-NEXT: br label [[FOR_INC]]
779 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
780 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
781 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
782 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
783 ; CHECK: for.end.loopexit:
784 ; CHECK-NEXT: br label [[FOR_END]]
786 ; CHECK-NEXT: ret void
789 %not_null = icmp ne ptr %c, null
790 call void(i1, ...) @llvm.experimental.guard(i1 %not_null) [ "deopt"() ]
791 %cmp11 = icmp sgt i32 %n, 0
792 br i1 %cmp11, label %for.body, label %for.end
796 for.body: ; preds = %entry, %for.inc
797 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
798 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
799 %0 = load i32, ptr %arrayidx, align 4
800 %cmp1 = icmp sgt i32 %0, 0
801 br i1 %cmp1, label %if.then, label %for.inc
803 if.then: ; preds = %for.body
804 %1 = load i32, ptr %c, align 4
805 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv
806 %2 = load i32, ptr %arrayidx3, align 4
807 %mul = mul nsw i32 %2, %1
808 store i32 %mul, ptr %arrayidx, align 4
811 for.inc: ; preds = %for.body, %if.then
812 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
813 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
814 %exitcond = icmp eq i32 %lftr.wideiv, %n
815 br i1 %exitcond, label %for.end, label %for.body
817 for.end: ; preds = %for.inc, %entry, %entry
821 ; Like @test12, but has a post-dominating guard, which cannot be used
822 ; to prove %c is nonnull at the point of the load.
823 define void @test13(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) %c, i32 %n) #0 {
824 ; CHECK-LABEL: @test13(
826 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne ptr [[C:%.*]], null
827 ; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
828 ; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
829 ; CHECK: for.body.preheader:
830 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
832 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
833 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
834 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
835 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 0
836 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
838 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[C]], align 4
839 ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]
840 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4
841 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP1]]
842 ; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4
843 ; CHECK-NEXT: br label [[FOR_INC]]
845 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
846 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
847 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
848 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
849 ; CHECK: for.end.loopexit:
850 ; CHECK-NEXT: br label [[FOR_END]]
852 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[NOT_NULL]]) [ "deopt"() ]
853 ; CHECK-NEXT: ret void
856 %not_null = icmp ne ptr %c, null
857 %cmp11 = icmp sgt i32 %n, 0
858 br i1 %cmp11, label %for.body, label %for.end
861 for.body: ; preds = %entry, %for.inc
862 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
863 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
864 %0 = load i32, ptr %arrayidx, align 4
865 %cmp1 = icmp sgt i32 %0, 0
866 br i1 %cmp1, label %if.then, label %for.inc
868 if.then: ; preds = %for.body
869 %1 = load i32, ptr %c, align 4
870 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv
871 %2 = load i32, ptr %arrayidx3, align 4
872 %mul = mul nsw i32 %2, %1
873 store i32 %mul, ptr %arrayidx, align 4
876 for.inc: ; preds = %for.body, %if.then
877 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
878 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
879 %exitcond = icmp eq i32 %lftr.wideiv, %n
880 br i1 %exitcond, label %for.end, label %for.body
882 for.end: ; preds = %for.inc, %entry, %entry
883 call void(i1, ...) @llvm.experimental.guard(i1 %not_null) [ "deopt"() ]
887 ; Check that branch by condition "null check AND something" allows to hoist the
889 define void @test14(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) align 4 %c, i32 %n, i1 %dummy_cond) #0 {
890 ; CHECK-LABEL: @test14(
892 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne ptr [[C:%.*]], null
893 ; CHECK-NEXT: [[DUMMY_AND:%.*]] = and i1 [[NOT_NULL]], [[DUMMY_COND:%.*]]
894 ; CHECK-NEXT: br i1 [[DUMMY_AND]], label [[NOT_NULL:%.*]], label [[FOR_END:%.*]]
896 ; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
897 ; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END]]
898 ; CHECK: for.body.preheader:
899 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[C]], align 4
900 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
902 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
903 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
904 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
905 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP1]], 0
906 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
908 ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]
909 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4
910 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP0]]
911 ; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4
912 ; CHECK-NEXT: br label [[FOR_INC]]
914 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
915 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
916 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
917 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
918 ; CHECK: for.end.loopexit:
919 ; CHECK-NEXT: br label [[FOR_END]]
921 ; CHECK-NEXT: ret void
925 %not_null = icmp ne ptr %c, null
926 %dummy_and = and i1 %not_null, %dummy_cond
927 br i1 %dummy_and, label %not.null, label %for.end
930 %cmp11 = icmp sgt i32 %n, 0
931 br i1 %cmp11, label %for.body, label %for.end
933 for.body: ; preds = %not.null, %for.inc
934 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %not.null ]
935 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
936 %0 = load i32, ptr %arrayidx, align 4
937 %cmp1 = icmp sgt i32 %0, 0
938 br i1 %cmp1, label %if.then, label %for.inc
940 if.then: ; preds = %for.body
941 %1 = load i32, ptr %c, align 4
942 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv
943 %2 = load i32, ptr %arrayidx3, align 4
944 %mul = mul nsw i32 %2, %1
945 store i32 %mul, ptr %arrayidx, align 4
948 for.inc: ; preds = %for.body, %if.then
949 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
950 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
951 %exitcond = icmp eq i32 %lftr.wideiv, %n
952 br i1 %exitcond, label %for.end, label %for.body
954 for.end: ; preds = %for.inc, %entry, %not.null
958 ; Check that guard by condition "null check AND something" allows to hoist the
960 define void @test15(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) align 4 %c, i32 %n, i1 %dummy_cond) #0 {
961 ; CHECK-LABEL: @test15(
963 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne ptr [[C:%.*]], null
964 ; CHECK-NEXT: [[DUMMY_AND:%.*]] = and i1 [[NOT_NULL]], [[DUMMY_COND:%.*]]
965 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[DUMMY_AND]]) [ "deopt"() ]
966 ; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
967 ; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
968 ; CHECK: for.body.preheader:
969 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[C]], align 4
970 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
972 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
973 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
974 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
975 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP1]], 0
976 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
978 ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]
979 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4
980 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP0]]
981 ; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4
982 ; CHECK-NEXT: br label [[FOR_INC]]
984 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
985 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
986 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
987 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
988 ; CHECK: for.end.loopexit:
989 ; CHECK-NEXT: br label [[FOR_END]]
991 ; CHECK-NEXT: ret void
995 %not_null = icmp ne ptr %c, null
996 %dummy_and = and i1 %not_null, %dummy_cond
997 call void(i1, ...) @llvm.experimental.guard(i1 %dummy_and) [ "deopt"() ]
998 %cmp11 = icmp sgt i32 %n, 0
999 br i1 %cmp11, label %for.body, label %for.end
1001 for.body: ; preds = %entry, %for.inc
1002 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
1003 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
1004 %0 = load i32, ptr %arrayidx, align 4
1005 %cmp1 = icmp sgt i32 %0, 0
1006 br i1 %cmp1, label %if.then, label %for.inc
1008 if.then: ; preds = %for.body
1009 %1 = load i32, ptr %c, align 4
1010 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv
1011 %2 = load i32, ptr %arrayidx3, align 4
1012 %mul = mul nsw i32 %2, %1
1013 store i32 %mul, ptr %arrayidx, align 4
1016 for.inc: ; preds = %for.body, %if.then
1017 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
1018 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
1019 %exitcond = icmp eq i32 %lftr.wideiv, %n
1020 br i1 %exitcond, label %for.end, label %for.body
1022 for.end: ; preds = %for.inc, %entry
1026 ; Ensure that (c == null && other_cond) does not automatically mean that c is
1027 ; non-null in false branch. So the condition ((c == null && other_cond) == false)
1028 ; is not sufficient to conclude that c != null.
1029 define void @test16(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) %c, i32 %n, i1 %dummy_cond) #0 {
1030 ; CHECK-LABEL: @test16(
1031 ; CHECK-NEXT: entry:
1032 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp eq ptr [[C:%.*]], null
1033 ; CHECK-NEXT: [[DUMMY_AND:%.*]] = and i1 [[NOT_NULL]], [[DUMMY_COND:%.*]]
1034 ; CHECK-NEXT: br i1 [[DUMMY_AND]], label [[FOR_END:%.*]], label [[NOT_NULL:%.*]]
1036 ; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
1037 ; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END]]
1038 ; CHECK: for.body.preheader:
1039 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
1041 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
1042 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
1043 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
1044 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 0
1045 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
1047 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[C]], align 4
1048 ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]
1049 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4
1050 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP1]]
1051 ; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4
1052 ; CHECK-NEXT: br label [[FOR_INC]]
1054 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
1055 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
1056 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
1057 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
1058 ; CHECK: for.end.loopexit:
1059 ; CHECK-NEXT: br label [[FOR_END]]
1061 ; CHECK-NEXT: ret void
1065 %not_null = icmp eq ptr %c, null
1066 %dummy_and = and i1 %not_null, %dummy_cond
1067 br i1 %dummy_and, label %for.end, label %not.null
1070 %cmp11 = icmp sgt i32 %n, 0
1071 br i1 %cmp11, label %for.body, label %for.end
1073 for.body: ; preds = %not.null, %for.inc
1074 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %not.null ]
1075 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
1076 %0 = load i32, ptr %arrayidx, align 4
1077 %cmp1 = icmp sgt i32 %0, 0
1078 br i1 %cmp1, label %if.then, label %for.inc
1080 if.then: ; preds = %for.body
1081 %1 = load i32, ptr %c, align 4
1082 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv
1083 %2 = load i32, ptr %arrayidx3, align 4
1084 %mul = mul nsw i32 %2, %1
1085 store i32 %mul, ptr %arrayidx, align 4
1088 for.inc: ; preds = %for.body, %if.then
1089 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
1090 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
1091 %exitcond = icmp eq i32 %lftr.wideiv, %n
1092 br i1 %exitcond, label %for.end, label %for.body
1094 for.end: ; preds = %for.inc, %entry, %not.null
1098 ; Ensure that (c == null && other_cond) does not automatically mean that c is
1099 ; non-null in false branch. So the condition ((c == null && other_cond) == false)
1100 ; is not sufficient to conclude that c != null.
1101 define void @test17(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) %c, i32 %n, i1 %dummy_cond) #0 {
1102 ; CHECK-LABEL: @test17(
1103 ; CHECK-NEXT: entry:
1104 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp eq ptr [[C:%.*]], null
1105 ; CHECK-NEXT: [[DUMMY_AND:%.*]] = and i1 [[NOT_NULL]], [[DUMMY_COND:%.*]]
1106 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[DUMMY_AND]]) [ "deopt"() ]
1107 ; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
1108 ; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
1109 ; CHECK: for.body.preheader:
1110 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
1112 ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
1113 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
1114 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
1115 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 0
1116 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
1118 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[C]], align 4
1119 ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]
1120 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4
1121 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP1]]
1122 ; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4
1123 ; CHECK-NEXT: br label [[FOR_INC]]
1125 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
1126 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
1127 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
1128 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
1129 ; CHECK: for.end.loopexit:
1130 ; CHECK-NEXT: br label [[FOR_END]]
1132 ; CHECK-NEXT: ret void
1136 %not_null = icmp eq ptr %c, null
1137 %dummy_and = and i1 %not_null, %dummy_cond
1138 call void(i1, ...) @llvm.experimental.guard(i1 %dummy_and) [ "deopt"() ]
1139 %cmp11 = icmp sgt i32 %n, 0
1140 br i1 %cmp11, label %for.end, label %for.body
1142 for.body: ; preds = %entry, %for.inc
1143 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
1144 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv
1145 %0 = load i32, ptr %arrayidx, align 4
1146 %cmp1 = icmp sgt i32 %0, 0
1147 br i1 %cmp1, label %if.then, label %for.inc
1149 if.then: ; preds = %for.body
1150 %1 = load i32, ptr %c, align 4
1151 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv
1152 %2 = load i32, ptr %arrayidx3, align 4
1153 %mul = mul nsw i32 %2, %1
1154 store i32 %mul, ptr %arrayidx, align 4
1157 for.inc: ; preds = %for.body, %if.then
1158 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
1159 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
1160 %exitcond = icmp eq i32 %lftr.wideiv, %n
1161 br i1 %exitcond, label %for.end, label %for.body
1163 for.end: ; preds = %for.inc, %entry
1167 declare void @use(i64)
1169 define void @licm_deref_no_hoist(i1 %c1, i1 %c2, ptr align 8 dereferenceable(8) %p1) {
1170 ; CHECK-LABEL: @licm_deref_no_hoist(
1171 ; CHECK-NEXT: entry:
1172 ; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P1:%.*]], align 8, !align [[META1:![0-9]+]]
1173 ; CHECK-NEXT: br label [[LOOP:%.*]]
1175 ; CHECK-NEXT: br i1 [[C1:%.*]], label [[IF:%.*]], label [[LOOP_LATCH:%.*]]
1177 ; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[P2]], align 8
1178 ; CHECK-NEXT: call void @use(i64 [[V]]) #[[ATTR1:[0-9]+]]
1179 ; CHECK-NEXT: br label [[LOOP_LATCH]]
1180 ; CHECK: loop.latch:
1181 ; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP]], label [[EXIT:%.*]]
1183 ; CHECK-NEXT: ret void
1189 br i1 %c1, label %if, label %loop.latch
1192 %p2 = load ptr, ptr %p1, align 8, !dereferenceable !1, !align !1
1193 %v = load i64, ptr %p2, align 8
1194 call void @use(i64 %v) memory(none)
1195 br label %loop.latch
1198 br i1 %c2, label %loop, label %exit
1204 define void @licm_deref_hoist(i1 %c1, i1 %c2, ptr align 8 dereferenceable(8) %p1) {
1205 ; CHECK-LABEL: @licm_deref_hoist(
1206 ; CHECK-NEXT: entry:
1207 ; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P1:%.*]], align 8, !dereferenceable [[META1]], !align [[META1]]
1208 ; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[P2]], align 8
1209 ; CHECK-NEXT: br label [[LOOP:%.*]]
1211 ; CHECK-NEXT: br i1 [[C1:%.*]], label [[IF:%.*]], label [[LOOP_LATCH:%.*]]
1213 ; CHECK-NEXT: call void @use(i64 [[V]]) #[[ATTR1]]
1214 ; CHECK-NEXT: br label [[LOOP_LATCH]]
1215 ; CHECK: loop.latch:
1216 ; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP]], label [[EXIT:%.*]]
1218 ; CHECK-NEXT: ret void
1221 %p2 = load ptr, ptr %p1, align 8, !dereferenceable !1, !align !1
1225 br i1 %c1, label %if, label %loop.latch
1228 %v = load i64, ptr %p2, align 8
1229 call void @use(i64 %v) memory(none)
1230 br label %loop.latch
1233 br i1 %c2, label %loop, label %exit
1239 attributes #0 = { nounwind uwtable nofree nosync }