[AArch64][NFC] NFC for const vector as Instruction operand (#116790)
[llvm-project.git] / llvm / test / Transforms / LICM / hoist-deref-load.ll
blobc498e85ddd6c296d62799769cb582502ed8d1401
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)
11 ;     if (a[i] > 0)
12 ;       a[i] = c*b[i];
13 ; }
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(
19 ; CHECK-NEXT:  entry:
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:%.*]]
25 ; CHECK:       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]]
31 ; CHECK:       if.then:
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]]
37 ; CHECK:       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]]
44 ; CHECK:       for.end:
45 ; CHECK-NEXT:    ret void
47 entry:
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
64   br label %for.inc
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
73   ret void
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(
80 ; CHECK-NEXT:  entry:
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:%.*]]
85 ; CHECK:       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]]
91 ; CHECK:       if.then:
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]]
98 ; CHECK:       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]]
105 ; CHECK:       for.end:
106 ; CHECK-NEXT:    ret void
108 entry:
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
125   br label %for.inc
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
134   ret void
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)
140 ;     if (a[i] > 0)
141 ;       a[i] = cptr b[i];
142 ; }
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(
147 ; CHECK-NEXT:  entry:
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:%.*]]
154 ; CHECK:       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]]
160 ; CHECK:       if.then:
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]]
166 ; CHECK:       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]]
173 ; CHECK:       for.end:
174 ; CHECK-NEXT:    ret void
176 entry:
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
194   br label %for.inc
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
203   ret void
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(
210 ; CHECK-NEXT:  entry:
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:%.*]]
216 ; CHECK:       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]]
222 ; CHECK:       if.then:
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]]
229 ; CHECK:       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]]
236 ; CHECK:       for.end:
237 ; CHECK-NEXT:    ret void
239 entry:
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
257   br label %for.inc
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
266   ret void
269 ; This test represents the following function:
270 ; void test1(int * __restrict__ a, int *b, int &c, int n) {
271 ;   if (c != null)
272 ;     for (int i = 0; i < n; ++i)
273 ;       if (a[i] > 0)
274 ;         a[i] = c*b[i];
275 ; }
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
278 ; check on %c.
279 define void @test5(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) align 4 %c, i32 %n) #0 {
280 ; CHECK-LABEL: @test5(
281 ; CHECK-NEXT:  entry:
282 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp ne ptr [[C:%.*]], null
283 ; CHECK-NEXT:    br i1 [[NOT_NULL]], label [[NOT_NULL:%.*]], label [[FOR_END:%.*]]
284 ; CHECK:       not.null:
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:%.*]]
290 ; CHECK:       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]]
296 ; CHECK:       if.then:
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]]
302 ; CHECK:       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]]
309 ; CHECK:       for.end:
310 ; CHECK-NEXT:    ret void
312 entry:
313   %not_null = icmp ne ptr %c, null
314   br i1 %not_null, label %not.null, label %for.end
316 not.null:
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
333   br label %for.inc
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
342   ret void
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
349 ; not a branch.
350 define i1 @test6(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) %c, i32 %n) #0 {
351 ; CHECK-LABEL: @test6(
352 ; CHECK-NEXT:  entry:
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:%.*]]
358 ; CHECK:       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]]
364 ; CHECK:       if.then:
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]]
371 ; CHECK:       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]]
378 ; CHECK:       for.end:
379 ; CHECK-NEXT:    ret i1 [[NOT_NULL]]
381 entry:
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
399   br label %for.inc
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
408   ret i1 %not_null
411 ; This test represents the following function:
412 ; void test1(int * __restrict__ a, int *b, int **cptr, int n) {
413 ;   c = *cptr;
414 ;   for (int i = 0; i < n; ++i)
415 ;     if (a[i] > 0)
416 ;       a[i] = (*c)*b[i];
417 ; }
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(
422 ; CHECK-NEXT:  entry:
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:%.*]]
429 ; CHECK:       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]]
435 ; CHECK:       if.then:
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]]
441 ; CHECK:       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]]
448 ; CHECK:       for.end:
449 ; CHECK-NEXT:    ret void
451 entry:
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
469   br label %for.inc
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
478   ret void
481 ; This test represents the following function:
482 ; void test1(int * __restrict__ a, int *b, int **cptr, int n) {
483 ;   c = *cptr;
484 ;   if (c != null)
485 ;     for (int i = 0; i < n; ++i)
486 ;       if (a[i] > 0)
487 ;         a[i] = (*c)*b[i];
488 ; }
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(
494 ; CHECK-NEXT:  entry:
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:%.*]]
498 ; CHECK:       not.null:
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:%.*]]
504 ; CHECK:       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]]
510 ; CHECK:       if.then:
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]]
516 ; CHECK:       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]]
523 ; CHECK:       for.end:
524 ; CHECK-NEXT:    ret void
526 entry:
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
531 not.null:
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
548   br label %for.inc
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
557   ret void
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(
564 ; CHECK-NEXT:  entry:
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:%.*]]
570 ; CHECK:       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]]
576 ; CHECK:       if.then:
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]]
583 ; CHECK:       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]]
590 ; CHECK:       for.end:
591 ; CHECK-NEXT:    ret void
593 entry:
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
611   br label %for.inc
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
620   ret void
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(
631 ; CHECK-NEXT:  entry:
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:%.*]]
637 ; CHECK:       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]]
643 ; CHECK:       if.then:
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]]
650 ; CHECK:       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]]
657 ; CHECK:       for.end:
658 ; CHECK-NEXT:    ret void
660 entry:
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
678   br label %for.inc
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
687   ret void
690 define void @test11(ptr noalias %a, ptr %b, ptr dereferenceable(8) %cptr, i32 %n) #0 {
691 ; CHECK-LABEL: @test11(
692 ; CHECK-NEXT:  entry:
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:%.*]]
698 ; CHECK:       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]]
704 ; CHECK:       if.then:
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]]
711 ; CHECK:       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]]
718 ; CHECK:       for.end:
719 ; CHECK-NEXT:    ret void
721 entry:
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
741   br label %for.inc
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
750   ret void
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(
758 ; CHECK-NEXT:  entry:
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:%.*]]
766 ; CHECK:       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]]
772 ; CHECK:       if.then:
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]]
778 ; CHECK:       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]]
785 ; CHECK:       for.end:
786 ; CHECK-NEXT:    ret void
788 entry:
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
809   br label %for.inc
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
818   ret void
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(
825 ; CHECK-NEXT:  entry:
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:%.*]]
831 ; CHECK:       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]]
837 ; CHECK:       if.then:
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]]
844 ; CHECK:       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]]
851 ; CHECK:       for.end:
852 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[NOT_NULL]]) [ "deopt"() ]
853 ; CHECK-NEXT:    ret void
855 entry:
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
874   br label %for.inc
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"() ]
884   ret void
887 ; Check that branch by condition "null check AND something" allows to hoist the
888 ; load.
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(
891 ; CHECK-NEXT:  entry:
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:%.*]]
895 ; CHECK:       not.null:
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:%.*]]
901 ; CHECK:       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]]
907 ; CHECK:       if.then:
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]]
913 ; CHECK:       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]]
920 ; CHECK:       for.end:
921 ; CHECK-NEXT:    ret void
924 entry:
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
929 not.null:
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
946   br label %for.inc
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
955   ret void
958 ; Check that guard by condition "null check AND something" allows to hoist the
959 ; load.
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(
962 ; CHECK-NEXT:  entry:
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:%.*]]
971 ; CHECK:       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]]
977 ; CHECK:       if.then:
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]]
983 ; CHECK:       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]]
990 ; CHECK:       for.end:
991 ; CHECK-NEXT:    ret void
994 entry:
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
1014   br label %for.inc
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
1023   ret void
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:%.*]]
1035 ; CHECK:       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:%.*]]
1040 ; CHECK:       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]]
1046 ; CHECK:       if.then:
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]]
1053 ; CHECK:       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]]
1060 ; CHECK:       for.end:
1061 ; CHECK-NEXT:    ret void
1064 entry:
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
1069 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
1086   br label %for.inc
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
1095   ret void
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:%.*]]
1111 ; CHECK:       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]]
1117 ; CHECK:       if.then:
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]]
1124 ; CHECK:       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]]
1131 ; CHECK:       for.end:
1132 ; CHECK-NEXT:    ret void
1135 entry:
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
1155   br label %for.inc
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
1164   ret void
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:%.*]]
1174 ; CHECK:       loop:
1175 ; CHECK-NEXT:    br i1 [[C1:%.*]], label [[IF:%.*]], label [[LOOP_LATCH:%.*]]
1176 ; CHECK:       if:
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:%.*]]
1182 ; CHECK:       exit:
1183 ; CHECK-NEXT:    ret void
1185 entry:
1186   br label %loop
1188 loop:
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
1197 loop.latch:
1198   br i1 %c2, label %loop, label %exit
1200 exit:
1201   ret void
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:%.*]]
1210 ; CHECK:       loop:
1211 ; CHECK-NEXT:    br i1 [[C1:%.*]], label [[IF:%.*]], label [[LOOP_LATCH:%.*]]
1212 ; CHECK:       if:
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:%.*]]
1217 ; CHECK:       exit:
1218 ; CHECK-NEXT:    ret void
1220 entry:
1221   %p2 = load ptr, ptr %p1, align 8, !dereferenceable !1, !align !1
1222   br label %loop
1224 loop:
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
1232 loop.latch:
1233   br i1 %c2, label %loop, label %exit
1235 exit:
1236   ret void
1239 attributes #0 = { nounwind uwtable nofree nosync }
1240 !0 = !{i64 4}
1241 !1 = !{i64 8}