Follow up to d0858bffa11, add missing REQUIRES x86
[llvm-project.git] / llvm / test / Transforms / IndVarSimplify / widen-nonnegative.ll
blob612e9452c6373dc2e1bcf3339cba033c76756d07
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -S -passes='indvars' -verify-loop-info -verify-dom-info -verify-scev | FileCheck %s
4 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
6 ; Simple case of direct extend of index
7 ; --------------------------------------
9 define void @sext_no_offset(ptr %A, i32 %M) {
10 ; CHECK-LABEL: @sext_no_offset(
11 ; CHECK-NEXT:  entry:
12 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
13 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
14 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
15 ; CHECK:       for.body:
16 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
17 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
18 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
19 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
20 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
21 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
22 ; CHECK:       exit:
23 ; CHECK-NEXT:    ret void
25 entry:
26   br label %for.body
28 for.body:
29   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
30   %idxprom.us = sext i32 %j.016.us to i64
31   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
32   tail call void @use_ptr(ptr %arrayidx.us)
33   %inc.us = add nuw nsw i32 %j.016.us, 1
34   %cmp2.us = icmp slt i32 %inc.us, %M
35   br i1 %cmp2.us, label %for.body, label %exit
37 exit:
38   ret void
41 define void @zext_no_offset(ptr %A, i32 %M) {
42 ; CHECK-LABEL: @zext_no_offset(
43 ; CHECK-NEXT:  entry:
44 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
45 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
46 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
47 ; CHECK:       for.body:
48 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
49 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
50 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
51 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
52 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
53 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
54 ; CHECK:       exit:
55 ; CHECK-NEXT:    ret void
57 entry:
58   br label %for.body
60 for.body:
61   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
62   %idxprom.us = zext i32 %j.016.us to i64
63   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
64   tail call void @use_ptr(ptr %arrayidx.us)
65   %inc.us = add nuw nsw i32 %j.016.us, 1
66   %cmp2.us = icmp slt i32 %inc.us, %M
67   br i1 %cmp2.us, label %for.body, label %exit
69 exit:
70   ret void
73 define void @zext_nneg_no_offset(ptr %A, i32 %M) {
74 ; CHECK-LABEL: @zext_nneg_no_offset(
75 ; CHECK-NEXT:  entry:
76 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
77 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
78 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
79 ; CHECK:       for.body:
80 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
81 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]
82 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
83 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
84 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
85 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
86 ; CHECK:       exit:
87 ; CHECK-NEXT:    ret void
89 entry:
90   br label %for.body
92 for.body:
93   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
94   %idxprom.us = zext nneg i32 %j.016.us to i64
95   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
96   tail call void @use_ptr(ptr %arrayidx.us)
97   %inc.us = add nuw nsw i32 %j.016.us, 1
98   %cmp2.us = icmp slt i32 %inc.us, %M
99   br i1 %cmp2.us, label %for.body, label %exit
101 exit:
102   ret void
105 ; Offset with a loop invariant value, various combinations
106 ; --------------------------------------
108 define void @sext_add_nsw(ptr %A, i32 %offset, i32 %M) {
109 ; CHECK-LABEL: @sext_add_nsw(
110 ; CHECK-NEXT:  entry:
111 ; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[OFFSET:%.*]] to i64
112 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
113 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
114 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
115 ; CHECK:       for.body:
116 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
117 ; CHECK-NEXT:    [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], [[TMP0]]
118 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]]
119 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
120 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
121 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
122 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
123 ; CHECK:       exit:
124 ; CHECK-NEXT:    ret void
126 entry:
127   br label %for.body
129 for.body:
130   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
131   %add.us = add nsw i32 %j.016.us, %offset
132   %idxprom.us = sext i32 %add.us to i64
133   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
134   tail call void @use_ptr(ptr %arrayidx.us)
135   %inc.us = add nuw nsw i32 %j.016.us, 1
136   %cmp2.us = icmp slt i32 %inc.us, %M
137   br i1 %cmp2.us, label %for.body, label %exit
139 exit:
140   ret void
143 define void @sext_add_nuw(ptr %A, i32 %offset, i32 %M) {
144 ; CHECK-LABEL: @sext_add_nuw(
145 ; CHECK-NEXT:  entry:
146 ; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[OFFSET:%.*]] to i64
147 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
148 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
149 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
150 ; CHECK:       for.body:
151 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
152 ; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i64 [[INDVARS_IV]], [[TMP0]]
153 ; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
154 ; CHECK-NEXT:    [[IDXPROM_US:%.*]] = sext i32 [[TMP2]] to i64
155 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
156 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
157 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
158 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
159 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
160 ; CHECK:       exit:
161 ; CHECK-NEXT:    ret void
163 entry:
164   br label %for.body
166 for.body:
167   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
168   %add.us = add nuw i32 %j.016.us, %offset
169   %idxprom.us = sext i32 %add.us to i64
170   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
171   tail call void @use_ptr(ptr %arrayidx.us)
172   %inc.us = add nuw nsw i32 %j.016.us, 1
173   %cmp2.us = icmp slt i32 %inc.us, %M
174   br i1 %cmp2.us, label %for.body, label %exit
176 exit:
177   ret void
180 define void @sext_add_noflags(ptr %A, i32 %offset, i32 %M) {
181 ; CHECK-LABEL: @sext_add_noflags(
182 ; CHECK-NEXT:  entry:
183 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
184 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
185 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
186 ; CHECK:       for.body:
187 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
188 ; CHECK-NEXT:    [[TMP0:%.*]] = trunc i64 [[INDVARS_IV]] to i32
189 ; CHECK-NEXT:    [[ADD_US:%.*]] = add i32 [[TMP0]], [[OFFSET:%.*]]
190 ; CHECK-NEXT:    [[IDXPROM_US:%.*]] = sext i32 [[ADD_US]] to i64
191 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
192 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
193 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
194 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
195 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
196 ; CHECK:       exit:
197 ; CHECK-NEXT:    ret void
199 entry:
200   br label %for.body
202 for.body:
203   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
204   %add.us = add i32 %j.016.us, %offset
205   %idxprom.us = sext i32 %add.us to i64
206   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
207   tail call void @use_ptr(ptr %arrayidx.us)
208   %inc.us = add nuw nsw i32 %j.016.us, 1
209   %cmp2.us = icmp slt i32 %inc.us, %M
210   br i1 %cmp2.us, label %for.body, label %exit
212 exit:
213   ret void
216 define void @zext_add_nsw(ptr %A, i32 %offset, i32 %M) {
217 ; CHECK-LABEL: @zext_add_nsw(
218 ; CHECK-NEXT:  entry:
219 ; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[OFFSET:%.*]] to i64
220 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
221 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
222 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
223 ; CHECK:       for.body:
224 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
225 ; CHECK-NEXT:    [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], [[TMP0]]
226 ; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
227 ; CHECK-NEXT:    [[IDXPROM_US:%.*]] = zext i32 [[TMP2]] to i64
228 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
229 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
230 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
231 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
232 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
233 ; CHECK:       exit:
234 ; CHECK-NEXT:    ret void
236 entry:
237   br label %for.body
239 for.body:
240   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
241   %add.us = add nsw i32 %j.016.us, %offset
242   %idxprom.us = zext i32 %add.us to i64
243   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
244   tail call void @use_ptr(ptr %arrayidx.us)
245   %inc.us = add nuw nsw i32 %j.016.us, 1
246   %cmp2.us = icmp slt i32 %inc.us, %M
247   br i1 %cmp2.us, label %for.body, label %exit
249 exit:
250   ret void
253 define void @zext_add_nuw(ptr %A, i32 %offset, i32 %M) {
254 ; CHECK-LABEL: @zext_add_nuw(
255 ; CHECK-NEXT:  entry:
256 ; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[OFFSET:%.*]] to i64
257 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
258 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
259 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
260 ; CHECK:       for.body:
261 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
262 ; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i64 [[INDVARS_IV]], [[TMP0]]
263 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]]
264 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
265 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
266 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
267 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
268 ; CHECK:       exit:
269 ; CHECK-NEXT:    ret void
271 entry:
272   br label %for.body
274 for.body:
275   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
276   %add.us = add nuw i32 %j.016.us, %offset
277   %idxprom.us = zext i32 %add.us to i64
278   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
279   tail call void @use_ptr(ptr %arrayidx.us)
280   %inc.us = add nuw nsw i32 %j.016.us, 1
281   %cmp2.us = icmp slt i32 %inc.us, %M
282   br i1 %cmp2.us, label %for.body, label %exit
284 exit:
285   ret void
288 define void @zext_add_noflags(ptr %A, i32 %offset, i32 %M) {
289 ; CHECK-LABEL: @zext_add_noflags(
290 ; CHECK-NEXT:  entry:
291 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
292 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
293 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
294 ; CHECK:       for.body:
295 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
296 ; CHECK-NEXT:    [[TMP0:%.*]] = trunc i64 [[INDVARS_IV]] to i32
297 ; CHECK-NEXT:    [[ADD_US:%.*]] = add i32 [[TMP0]], [[OFFSET:%.*]]
298 ; CHECK-NEXT:    [[IDXPROM_US:%.*]] = zext i32 [[ADD_US]] to i64
299 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
300 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
301 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
302 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
303 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
304 ; CHECK:       exit:
305 ; CHECK-NEXT:    ret void
307 entry:
308   br label %for.body
310 for.body:
311   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
312   %add.us = add i32 %j.016.us, %offset
313   %idxprom.us = zext i32 %add.us to i64
314   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
315   tail call void @use_ptr(ptr %arrayidx.us)
316   %inc.us = add nuw nsw i32 %j.016.us, 1
317   %cmp2.us = icmp slt i32 %inc.us, %M
318   br i1 %cmp2.us, label %for.body, label %exit
320 exit:
321   ret void
324 define void @zext_nneg_add_nsw(ptr %A, i32 %offset, i32 %M) {
325 ; CHECK-LABEL: @zext_nneg_add_nsw(
326 ; CHECK-NEXT:  entry:
327 ; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[OFFSET:%.*]] to i64
328 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
329 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
330 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
331 ; CHECK:       for.body:
332 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
333 ; CHECK-NEXT:    [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], [[TMP0]]
334 ; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
335 ; CHECK-NEXT:    [[IDXPROM_US:%.*]] = zext nneg i32 [[TMP2]] to i64
336 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
337 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
338 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
339 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
340 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
341 ; CHECK:       exit:
342 ; CHECK-NEXT:    ret void
344 entry:
345   br label %for.body
347 for.body:
348   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
349   %add.us = add nsw i32 %j.016.us, %offset
350   %idxprom.us = zext nneg i32 %add.us to i64
351   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
352   tail call void @use_ptr(ptr %arrayidx.us)
353   %inc.us = add nuw nsw i32 %j.016.us, 1
354   %cmp2.us = icmp slt i32 %inc.us, %M
355   br i1 %cmp2.us, label %for.body, label %exit
357 exit:
358   ret void
361 define void @zext_nneg_add_nuw(ptr %A, i32 %offset, i32 %M) {
362 ; CHECK-LABEL: @zext_nneg_add_nuw(
363 ; CHECK-NEXT:  entry:
364 ; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[OFFSET:%.*]] to i64
365 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
366 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
367 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
368 ; CHECK:       for.body:
369 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
370 ; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i64 [[INDVARS_IV]], [[TMP0]]
371 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]]
372 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
373 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
374 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
375 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
376 ; CHECK:       exit:
377 ; CHECK-NEXT:    ret void
379 entry:
380   br label %for.body
382 for.body:
383   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
384   %add.us = add nuw i32 %j.016.us, %offset
385   %idxprom.us = zext nneg i32 %add.us to i64
386   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
387   tail call void @use_ptr(ptr %arrayidx.us)
388   %inc.us = add nuw nsw i32 %j.016.us, 1
389   %cmp2.us = icmp slt i32 %inc.us, %M
390   br i1 %cmp2.us, label %for.body, label %exit
392 exit:
393   ret void
396 define void @zext_nneg_add_noflags(ptr %A, i32 %offset, i32 %M) {
397 ; CHECK-LABEL: @zext_nneg_add_noflags(
398 ; CHECK-NEXT:  entry:
399 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
400 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
401 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
402 ; CHECK:       for.body:
403 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
404 ; CHECK-NEXT:    [[TMP0:%.*]] = trunc i64 [[INDVARS_IV]] to i32
405 ; CHECK-NEXT:    [[ADD_US:%.*]] = add i32 [[TMP0]], [[OFFSET:%.*]]
406 ; CHECK-NEXT:    [[IDXPROM_US:%.*]] = zext nneg i32 [[ADD_US]] to i64
407 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
408 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
409 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
410 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
411 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
412 ; CHECK:       exit:
413 ; CHECK-NEXT:    ret void
415 entry:
416   br label %for.body
418 for.body:
419   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
420   %add.us = add i32 %j.016.us, %offset
421   %idxprom.us = zext nneg i32 %add.us to i64
422   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
423   tail call void @use_ptr(ptr %arrayidx.us)
424   %inc.us = add nuw nsw i32 %j.016.us, 1
425   %cmp2.us = icmp slt i32 %inc.us, %M
426   br i1 %cmp2.us, label %for.body, label %exit
428 exit:
429   ret void
432 ; Offset is multiplied by a multiple
433 ; --------------------------------------
435 define void @sext_mul_nsw(ptr %A, i32 %multiple, i32 %M) {
436 ; CHECK-LABEL: @sext_mul_nsw(
437 ; CHECK-NEXT:  entry:
438 ; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[MULTIPLE:%.*]] to i64
439 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
440 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
441 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
442 ; CHECK:       for.body:
443 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
444 ; CHECK-NEXT:    [[TMP1:%.*]] = mul nsw i64 [[INDVARS_IV]], [[TMP0]]
445 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]]
446 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
447 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
448 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
449 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
450 ; CHECK:       exit:
451 ; CHECK-NEXT:    ret void
453 entry:
454   br label %for.body
456 for.body:
457   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
458   %mul.us = mul nsw i32 %j.016.us, %multiple
459   %idxprom.us = sext i32 %mul.us to i64
460   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
461   tail call void @use_ptr(ptr %arrayidx.us)
462   %inc.us = add nuw nsw i32 %j.016.us, 1
463   %cmp2.us = icmp slt i32 %inc.us, %M
464   br i1 %cmp2.us, label %for.body, label %exit
466 exit:
467   ret void
470 define void @sext_mul_nuw(ptr %A, i32 %multiple, i32 %M) {
471 ; CHECK-LABEL: @sext_mul_nuw(
472 ; CHECK-NEXT:  entry:
473 ; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[MULTIPLE:%.*]] to i64
474 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
475 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
476 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
477 ; CHECK:       for.body:
478 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
479 ; CHECK-NEXT:    [[TMP1:%.*]] = mul nuw nsw i64 [[INDVARS_IV]], [[TMP0]]
480 ; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
481 ; CHECK-NEXT:    [[IDXPROM_US:%.*]] = sext i32 [[TMP2]] to i64
482 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
483 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
484 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
485 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
486 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
487 ; CHECK:       exit:
488 ; CHECK-NEXT:    ret void
490 entry:
491   br label %for.body
493 for.body:
494   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
495   %mul.us = mul nuw i32 %j.016.us, %multiple
496   %idxprom.us = sext i32 %mul.us to i64
497   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
498   tail call void @use_ptr(ptr %arrayidx.us)
499   %inc.us = add nuw nsw i32 %j.016.us, 1
500   %cmp2.us = icmp slt i32 %inc.us, %M
501   br i1 %cmp2.us, label %for.body, label %exit
503 exit:
504   ret void
507 define void @sext_mul_noflags(ptr %A, i32 %multiple, i32 %M) {
508 ; CHECK-LABEL: @sext_mul_noflags(
509 ; CHECK-NEXT:  entry:
510 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
511 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
512 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
513 ; CHECK:       for.body:
514 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
515 ; CHECK-NEXT:    [[TMP0:%.*]] = trunc i64 [[INDVARS_IV]] to i32
516 ; CHECK-NEXT:    [[MUL_US:%.*]] = mul i32 [[TMP0]], [[MULTIPLE:%.*]]
517 ; CHECK-NEXT:    [[IDXPROM_US:%.*]] = sext i32 [[MUL_US]] to i64
518 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
519 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
520 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
521 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
522 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
523 ; CHECK:       exit:
524 ; CHECK-NEXT:    ret void
526 entry:
527   br label %for.body
529 for.body:
530   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
531   %mul.us = mul i32 %j.016.us, %multiple
532   %idxprom.us = sext i32 %mul.us to i64
533   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
534   tail call void @use_ptr(ptr %arrayidx.us)
535   %inc.us = add nuw nsw i32 %j.016.us, 1
536   %cmp2.us = icmp slt i32 %inc.us, %M
537   br i1 %cmp2.us, label %for.body, label %exit
539 exit:
540   ret void
543 define void @zext_mul_nsw(ptr %A, i32 %multiple, i32 %M) {
544 ; CHECK-LABEL: @zext_mul_nsw(
545 ; CHECK-NEXT:  entry:
546 ; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[MULTIPLE:%.*]] to i64
547 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
548 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
549 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
550 ; CHECK:       for.body:
551 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
552 ; CHECK-NEXT:    [[TMP1:%.*]] = mul nsw i64 [[INDVARS_IV]], [[TMP0]]
553 ; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
554 ; CHECK-NEXT:    [[IDXPROM_US:%.*]] = zext i32 [[TMP2]] to i64
555 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
556 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
557 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
558 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
559 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
560 ; CHECK:       exit:
561 ; CHECK-NEXT:    ret void
563 entry:
564   br label %for.body
566 for.body:
567   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
568   %mul.us = mul nsw i32 %j.016.us, %multiple
569   %idxprom.us = zext i32 %mul.us to i64
570   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
571   tail call void @use_ptr(ptr %arrayidx.us)
572   %inc.us = add nuw nsw i32 %j.016.us, 1
573   %cmp2.us = icmp slt i32 %inc.us, %M
574   br i1 %cmp2.us, label %for.body, label %exit
576 exit:
577   ret void
580 define void @zext_mul_nuw(ptr %A, i32 %multiple, i32 %M) {
581 ; CHECK-LABEL: @zext_mul_nuw(
582 ; CHECK-NEXT:  entry:
583 ; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[MULTIPLE:%.*]] to i64
584 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
585 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
586 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
587 ; CHECK:       for.body:
588 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
589 ; CHECK-NEXT:    [[TMP1:%.*]] = mul nuw nsw i64 [[INDVARS_IV]], [[TMP0]]
590 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]]
591 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
592 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
593 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
594 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
595 ; CHECK:       exit:
596 ; CHECK-NEXT:    ret void
598 entry:
599   br label %for.body
601 for.body:
602   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
603   %mul.us = mul nuw i32 %j.016.us, %multiple
604   %idxprom.us = zext i32 %mul.us to i64
605   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
606   tail call void @use_ptr(ptr %arrayidx.us)
607   %inc.us = add nuw nsw i32 %j.016.us, 1
608   %cmp2.us = icmp slt i32 %inc.us, %M
609   br i1 %cmp2.us, label %for.body, label %exit
611 exit:
612   ret void
615 define void @zext_mul_noflags(ptr %A, i32 %multiple, i32 %M) {
616 ; CHECK-LABEL: @zext_mul_noflags(
617 ; CHECK-NEXT:  entry:
618 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
619 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
620 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
621 ; CHECK:       for.body:
622 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
623 ; CHECK-NEXT:    [[TMP0:%.*]] = trunc i64 [[INDVARS_IV]] to i32
624 ; CHECK-NEXT:    [[MUL_US:%.*]] = mul i32 [[TMP0]], [[MULTIPLE:%.*]]
625 ; CHECK-NEXT:    [[IDXPROM_US:%.*]] = zext i32 [[MUL_US]] to i64
626 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
627 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
628 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
629 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
630 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
631 ; CHECK:       exit:
632 ; CHECK-NEXT:    ret void
634 entry:
635   br label %for.body
637 for.body:
638   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
639   %mul.us = mul i32 %j.016.us, %multiple
640   %idxprom.us = zext i32 %mul.us to i64
641   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
642   tail call void @use_ptr(ptr %arrayidx.us)
643   %inc.us = add nuw nsw i32 %j.016.us, 1
644   %cmp2.us = icmp slt i32 %inc.us, %M
645   br i1 %cmp2.us, label %for.body, label %exit
647 exit:
648   ret void
651 define void @zext_nneg_mul_nsw(ptr %A, i32 %multiple, i32 %M) {
652 ; CHECK-LABEL: @zext_nneg_mul_nsw(
653 ; CHECK-NEXT:  entry:
654 ; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[MULTIPLE:%.*]] to i64
655 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
656 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
657 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
658 ; CHECK:       for.body:
659 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
660 ; CHECK-NEXT:    [[TMP1:%.*]] = mul nsw i64 [[INDVARS_IV]], [[TMP0]]
661 ; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
662 ; CHECK-NEXT:    [[IDXPROM_US:%.*]] = zext nneg i32 [[TMP2]] to i64
663 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
664 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
665 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
666 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
667 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
668 ; CHECK:       exit:
669 ; CHECK-NEXT:    ret void
671 entry:
672   br label %for.body
674 for.body:
675   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
676   %mul.us = mul nsw i32 %j.016.us, %multiple
677   %idxprom.us = zext nneg i32 %mul.us to i64
678   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
679   tail call void @use_ptr(ptr %arrayidx.us)
680   %inc.us = add nuw nsw i32 %j.016.us, 1
681   %cmp2.us = icmp slt i32 %inc.us, %M
682   br i1 %cmp2.us, label %for.body, label %exit
684 exit:
685   ret void
688 define void @zext_nneg_mul_nuw(ptr %A, i32 %multiple, i32 %M) {
689 ; CHECK-LABEL: @zext_nneg_mul_nuw(
690 ; CHECK-NEXT:  entry:
691 ; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[MULTIPLE:%.*]] to i64
692 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
693 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
694 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
695 ; CHECK:       for.body:
696 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
697 ; CHECK-NEXT:    [[TMP1:%.*]] = mul nuw nsw i64 [[INDVARS_IV]], [[TMP0]]
698 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]]
699 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
700 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
701 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
702 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
703 ; CHECK:       exit:
704 ; CHECK-NEXT:    ret void
706 entry:
707   br label %for.body
709 for.body:
710   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
711   %mul.us = mul nuw i32 %j.016.us, %multiple
712   %idxprom.us = zext nneg i32 %mul.us to i64
713   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
714   tail call void @use_ptr(ptr %arrayidx.us)
715   %inc.us = add nuw nsw i32 %j.016.us, 1
716   %cmp2.us = icmp slt i32 %inc.us, %M
717   br i1 %cmp2.us, label %for.body, label %exit
719 exit:
720   ret void
723 define void @zext_nneg_mul_noflags(ptr %A, i32 %multiple, i32 %M) {
724 ; CHECK-LABEL: @zext_nneg_mul_noflags(
725 ; CHECK-NEXT:  entry:
726 ; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
727 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
728 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
729 ; CHECK:       for.body:
730 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
731 ; CHECK-NEXT:    [[TMP0:%.*]] = trunc i64 [[INDVARS_IV]] to i32
732 ; CHECK-NEXT:    [[MUL_US:%.*]] = mul i32 [[TMP0]], [[MULTIPLE:%.*]]
733 ; CHECK-NEXT:    [[IDXPROM_US:%.*]] = zext nneg i32 [[MUL_US]] to i64
734 ; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
735 ; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
736 ; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
737 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
738 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
739 ; CHECK:       exit:
740 ; CHECK-NEXT:    ret void
742 entry:
743   br label %for.body
745 for.body:
746   %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
747   %mul.us = mul i32 %j.016.us, %multiple
748   %idxprom.us = zext nneg i32 %mul.us to i64
749   %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
750   tail call void @use_ptr(ptr %arrayidx.us)
751   %inc.us = add nuw nsw i32 %j.016.us, 1
752   %cmp2.us = icmp slt i32 %inc.us, %M
753   br i1 %cmp2.us, label %for.body, label %exit
755 exit:
756   ret void
759 declare dso_local void @use_ptr(ptr %0)