xref: /llvm-project/llvm/test/Transforms/IndVarSimplify/widen-nonnegative.ll (revision 4b22a923c4bfd0aa1d483149f84b6787263c2d76)
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
3
4target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
5
6; Simple case of direct extend of index
7; --------------------------------------
8
9define 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
24;
25entry:
26  br label %for.body
27
28for.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
36
37exit:
38  ret void
39}
40
41define 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
56;
57entry:
58  br label %for.body
59
60for.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
68
69exit:
70  ret void
71}
72
73define 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
88;
89entry:
90  br label %for.body
91
92for.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
100
101exit:
102  ret void
103}
104
105; Offset with a loop invariant value, various combinations
106; --------------------------------------
107
108define 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
125;
126entry:
127  br label %for.body
128
129for.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
138
139exit:
140  ret void
141}
142
143define 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 nuw 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
162;
163entry:
164  br label %for.body
165
166for.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
175
176exit:
177  ret void
178}
179
180define 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 nuw nsw 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
198;
199entry:
200  br label %for.body
201
202for.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
211
212exit:
213  ret void
214}
215
216define 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 nsw 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
235;
236entry:
237  br label %for.body
238
239for.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
248
249exit:
250  ret void
251}
252
253define 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
270;
271entry:
272  br label %for.body
273
274for.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
283
284exit:
285  ret void
286}
287
288define 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 nuw nsw 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
306;
307entry:
308  br label %for.body
309
310for.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
319
320exit:
321  ret void
322}
323
324define 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:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]]
335; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
336; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
337; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
338; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
339; CHECK:       exit:
340; CHECK-NEXT:    ret void
341;
342entry:
343  br label %for.body
344
345for.body:
346  %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
347  %add.us = add nsw i32 %j.016.us, %offset
348  %idxprom.us = zext nneg i32 %add.us to i64
349  %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
350  tail call void @use_ptr(ptr %arrayidx.us)
351  %inc.us = add nuw nsw i32 %j.016.us, 1
352  %cmp2.us = icmp slt i32 %inc.us, %M
353  br i1 %cmp2.us, label %for.body, label %exit
354
355exit:
356  ret void
357}
358
359define void @zext_nneg_add_nuw(ptr %A, i32 %offset, i32 %M) {
360; CHECK-LABEL: @zext_nneg_add_nuw(
361; CHECK-NEXT:  entry:
362; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[OFFSET:%.*]] to i64
363; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
364; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
365; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
366; CHECK:       for.body:
367; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
368; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i64 [[INDVARS_IV]], [[TMP0]]
369; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]]
370; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
371; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
372; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
373; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
374; CHECK:       exit:
375; CHECK-NEXT:    ret void
376;
377entry:
378  br label %for.body
379
380for.body:
381  %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
382  %add.us = add nuw i32 %j.016.us, %offset
383  %idxprom.us = zext nneg i32 %add.us to i64
384  %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
385  tail call void @use_ptr(ptr %arrayidx.us)
386  %inc.us = add nuw nsw i32 %j.016.us, 1
387  %cmp2.us = icmp slt i32 %inc.us, %M
388  br i1 %cmp2.us, label %for.body, label %exit
389
390exit:
391  ret void
392}
393
394define void @zext_nneg_add_noflags(ptr %A, i32 %offset, i32 %M) {
395; CHECK-LABEL: @zext_nneg_add_noflags(
396; CHECK-NEXT:  entry:
397; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
398; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
399; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
400; CHECK:       for.body:
401; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
402; CHECK-NEXT:    [[TMP0:%.*]] = trunc nuw nsw i64 [[INDVARS_IV]] to i32
403; CHECK-NEXT:    [[ADD_US:%.*]] = add i32 [[TMP0]], [[OFFSET:%.*]]
404; CHECK-NEXT:    [[IDXPROM_US:%.*]] = zext nneg i32 [[ADD_US]] to i64
405; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
406; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
407; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
408; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
409; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
410; CHECK:       exit:
411; CHECK-NEXT:    ret void
412;
413entry:
414  br label %for.body
415
416for.body:
417  %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
418  %add.us = add i32 %j.016.us, %offset
419  %idxprom.us = zext nneg i32 %add.us to i64
420  %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
421  tail call void @use_ptr(ptr %arrayidx.us)
422  %inc.us = add nuw nsw i32 %j.016.us, 1
423  %cmp2.us = icmp slt i32 %inc.us, %M
424  br i1 %cmp2.us, label %for.body, label %exit
425
426exit:
427  ret void
428}
429
430; Offset is multiplied by a multiple
431; --------------------------------------
432
433define void @sext_mul_nsw(ptr %A, i32 %multiple, i32 %M) {
434; CHECK-LABEL: @sext_mul_nsw(
435; CHECK-NEXT:  entry:
436; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[MULTIPLE:%.*]] to i64
437; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
438; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
439; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
440; CHECK:       for.body:
441; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
442; CHECK-NEXT:    [[TMP1:%.*]] = mul nsw i64 [[INDVARS_IV]], [[TMP0]]
443; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]]
444; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
445; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
446; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
447; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
448; CHECK:       exit:
449; CHECK-NEXT:    ret void
450;
451entry:
452  br label %for.body
453
454for.body:
455  %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
456  %mul.us = mul nsw i32 %j.016.us, %multiple
457  %idxprom.us = sext i32 %mul.us to i64
458  %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
459  tail call void @use_ptr(ptr %arrayidx.us)
460  %inc.us = add nuw nsw i32 %j.016.us, 1
461  %cmp2.us = icmp slt i32 %inc.us, %M
462  br i1 %cmp2.us, label %for.body, label %exit
463
464exit:
465  ret void
466}
467
468define void @sext_mul_nuw(ptr %A, i32 %multiple, i32 %M) {
469; CHECK-LABEL: @sext_mul_nuw(
470; CHECK-NEXT:  entry:
471; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[MULTIPLE:%.*]] to i64
472; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
473; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
474; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
475; CHECK:       for.body:
476; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
477; CHECK-NEXT:    [[TMP1:%.*]] = mul nuw nsw i64 [[INDVARS_IV]], [[TMP0]]
478; CHECK-NEXT:    [[TMP2:%.*]] = trunc nuw i64 [[TMP1]] to i32
479; CHECK-NEXT:    [[IDXPROM_US:%.*]] = sext i32 [[TMP2]] to i64
480; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
481; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
482; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
483; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
484; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
485; CHECK:       exit:
486; CHECK-NEXT:    ret void
487;
488entry:
489  br label %for.body
490
491for.body:
492  %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
493  %mul.us = mul nuw i32 %j.016.us, %multiple
494  %idxprom.us = sext i32 %mul.us to i64
495  %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
496  tail call void @use_ptr(ptr %arrayidx.us)
497  %inc.us = add nuw nsw i32 %j.016.us, 1
498  %cmp2.us = icmp slt i32 %inc.us, %M
499  br i1 %cmp2.us, label %for.body, label %exit
500
501exit:
502  ret void
503}
504
505define void @sext_mul_noflags(ptr %A, i32 %multiple, i32 %M) {
506; CHECK-LABEL: @sext_mul_noflags(
507; CHECK-NEXT:  entry:
508; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
509; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
510; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
511; CHECK:       for.body:
512; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
513; CHECK-NEXT:    [[TMP0:%.*]] = trunc nuw nsw i64 [[INDVARS_IV]] to i32
514; CHECK-NEXT:    [[MUL_US:%.*]] = mul i32 [[TMP0]], [[MULTIPLE:%.*]]
515; CHECK-NEXT:    [[IDXPROM_US:%.*]] = sext i32 [[MUL_US]] to i64
516; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
517; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
518; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
519; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
520; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
521; CHECK:       exit:
522; CHECK-NEXT:    ret void
523;
524entry:
525  br label %for.body
526
527for.body:
528  %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
529  %mul.us = mul i32 %j.016.us, %multiple
530  %idxprom.us = sext i32 %mul.us to i64
531  %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
532  tail call void @use_ptr(ptr %arrayidx.us)
533  %inc.us = add nuw nsw i32 %j.016.us, 1
534  %cmp2.us = icmp slt i32 %inc.us, %M
535  br i1 %cmp2.us, label %for.body, label %exit
536
537exit:
538  ret void
539}
540
541define void @zext_mul_nsw(ptr %A, i32 %multiple, i32 %M) {
542; CHECK-LABEL: @zext_mul_nsw(
543; CHECK-NEXT:  entry:
544; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[MULTIPLE:%.*]] to i64
545; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
546; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
547; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
548; CHECK:       for.body:
549; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
550; CHECK-NEXT:    [[TMP1:%.*]] = mul nsw i64 [[INDVARS_IV]], [[TMP0]]
551; CHECK-NEXT:    [[TMP2:%.*]] = trunc nsw i64 [[TMP1]] to i32
552; CHECK-NEXT:    [[IDXPROM_US:%.*]] = zext i32 [[TMP2]] to i64
553; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
554; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
555; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
556; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
557; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
558; CHECK:       exit:
559; CHECK-NEXT:    ret void
560;
561entry:
562  br label %for.body
563
564for.body:
565  %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
566  %mul.us = mul nsw i32 %j.016.us, %multiple
567  %idxprom.us = zext i32 %mul.us to i64
568  %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
569  tail call void @use_ptr(ptr %arrayidx.us)
570  %inc.us = add nuw nsw i32 %j.016.us, 1
571  %cmp2.us = icmp slt i32 %inc.us, %M
572  br i1 %cmp2.us, label %for.body, label %exit
573
574exit:
575  ret void
576}
577
578define void @zext_mul_nuw(ptr %A, i32 %multiple, i32 %M) {
579; CHECK-LABEL: @zext_mul_nuw(
580; CHECK-NEXT:  entry:
581; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[MULTIPLE:%.*]] to i64
582; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
583; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
584; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
585; CHECK:       for.body:
586; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
587; CHECK-NEXT:    [[TMP1:%.*]] = mul nuw nsw i64 [[INDVARS_IV]], [[TMP0]]
588; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]]
589; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
590; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
591; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
592; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
593; CHECK:       exit:
594; CHECK-NEXT:    ret void
595;
596entry:
597  br label %for.body
598
599for.body:
600  %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
601  %mul.us = mul nuw i32 %j.016.us, %multiple
602  %idxprom.us = zext i32 %mul.us to i64
603  %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
604  tail call void @use_ptr(ptr %arrayidx.us)
605  %inc.us = add nuw nsw i32 %j.016.us, 1
606  %cmp2.us = icmp slt i32 %inc.us, %M
607  br i1 %cmp2.us, label %for.body, label %exit
608
609exit:
610  ret void
611}
612
613define void @zext_mul_noflags(ptr %A, i32 %multiple, i32 %M) {
614; CHECK-LABEL: @zext_mul_noflags(
615; CHECK-NEXT:  entry:
616; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
617; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
618; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
619; CHECK:       for.body:
620; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
621; CHECK-NEXT:    [[TMP0:%.*]] = trunc nuw nsw i64 [[INDVARS_IV]] to i32
622; CHECK-NEXT:    [[MUL_US:%.*]] = mul i32 [[TMP0]], [[MULTIPLE:%.*]]
623; CHECK-NEXT:    [[IDXPROM_US:%.*]] = zext i32 [[MUL_US]] to i64
624; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
625; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
626; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
627; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
628; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
629; CHECK:       exit:
630; CHECK-NEXT:    ret void
631;
632entry:
633  br label %for.body
634
635for.body:
636  %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
637  %mul.us = mul i32 %j.016.us, %multiple
638  %idxprom.us = zext i32 %mul.us to i64
639  %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
640  tail call void @use_ptr(ptr %arrayidx.us)
641  %inc.us = add nuw nsw i32 %j.016.us, 1
642  %cmp2.us = icmp slt i32 %inc.us, %M
643  br i1 %cmp2.us, label %for.body, label %exit
644
645exit:
646  ret void
647}
648
649define void @zext_nneg_mul_nsw(ptr %A, i32 %multiple, i32 %M) {
650; CHECK-LABEL: @zext_nneg_mul_nsw(
651; CHECK-NEXT:  entry:
652; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[MULTIPLE:%.*]] to i64
653; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
654; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
655; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
656; CHECK:       for.body:
657; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
658; CHECK-NEXT:    [[TMP1:%.*]] = mul nsw i64 [[INDVARS_IV]], [[TMP0]]
659; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]]
660; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
661; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
662; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
663; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
664; CHECK:       exit:
665; CHECK-NEXT:    ret void
666;
667entry:
668  br label %for.body
669
670for.body:
671  %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
672  %mul.us = mul nsw i32 %j.016.us, %multiple
673  %idxprom.us = zext nneg i32 %mul.us to i64
674  %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
675  tail call void @use_ptr(ptr %arrayidx.us)
676  %inc.us = add nuw nsw i32 %j.016.us, 1
677  %cmp2.us = icmp slt i32 %inc.us, %M
678  br i1 %cmp2.us, label %for.body, label %exit
679
680exit:
681  ret void
682}
683
684define void @zext_nneg_mul_nuw(ptr %A, i32 %multiple, i32 %M) {
685; CHECK-LABEL: @zext_nneg_mul_nuw(
686; CHECK-NEXT:  entry:
687; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[MULTIPLE:%.*]] to i64
688; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
689; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
690; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
691; CHECK:       for.body:
692; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
693; CHECK-NEXT:    [[TMP1:%.*]] = mul nuw nsw i64 [[INDVARS_IV]], [[TMP0]]
694; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]]
695; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
696; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
697; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
698; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
699; CHECK:       exit:
700; CHECK-NEXT:    ret void
701;
702entry:
703  br label %for.body
704
705for.body:
706  %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
707  %mul.us = mul nuw i32 %j.016.us, %multiple
708  %idxprom.us = zext nneg i32 %mul.us to i64
709  %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
710  tail call void @use_ptr(ptr %arrayidx.us)
711  %inc.us = add nuw nsw i32 %j.016.us, 1
712  %cmp2.us = icmp slt i32 %inc.us, %M
713  br i1 %cmp2.us, label %for.body, label %exit
714
715exit:
716  ret void
717}
718
719define void @zext_nneg_mul_noflags(ptr %A, i32 %multiple, i32 %M) {
720; CHECK-LABEL: @zext_nneg_mul_noflags(
721; CHECK-NEXT:  entry:
722; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[M:%.*]], i32 1)
723; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
724; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
725; CHECK:       for.body:
726; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
727; CHECK-NEXT:    [[TMP0:%.*]] = trunc nuw nsw i64 [[INDVARS_IV]] to i32
728; CHECK-NEXT:    [[MUL_US:%.*]] = mul i32 [[TMP0]], [[MULTIPLE:%.*]]
729; CHECK-NEXT:    [[IDXPROM_US:%.*]] = zext nneg i32 [[MUL_US]] to i64
730; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]]
731; CHECK-NEXT:    tail call void @use_ptr(ptr [[ARRAYIDX_US]])
732; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
733; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
734; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[EXIT:%.*]]
735; CHECK:       exit:
736; CHECK-NEXT:    ret void
737;
738entry:
739  br label %for.body
740
741for.body:
742  %j.016.us = phi i32 [ 0, %entry ], [ %inc.us, %for.body ]
743  %mul.us = mul i32 %j.016.us, %multiple
744  %idxprom.us = zext nneg i32 %mul.us to i64
745  %arrayidx.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us
746  tail call void @use_ptr(ptr %arrayidx.us)
747  %inc.us = add nuw nsw i32 %j.016.us, 1
748  %cmp2.us = icmp slt i32 %inc.us, %M
749  br i1 %cmp2.us, label %for.body, label %exit
750
751exit:
752  ret void
753}
754
755declare dso_local void @use_ptr(ptr %0)
756