[AMDGPU] Mark AGPR tuple implicit in the first instr of AGPR spills. (#115285)
[llvm-project.git] / llvm / test / Transforms / LoopFlatten / loop-flatten-version.ll
blob85072bf3a43f4840029450c39ecffc3c711d1097
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2 ; RUN: opt %s -S -passes='loop(loop-flatten),verify' -verify-loop-info -verify-dom-info -verify-scev -o - | FileCheck %s
4 target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
6 ; We need to version the loop as the GEPs are not inbounds
7 define void @noinbounds_gep(i32 %N, ptr %A) {
8 ; CHECK-LABEL: define void @noinbounds_gep(
9 ; CHECK-SAME: i32 [[N:%.*]], ptr [[A:%.*]]) {
10 ; CHECK-NEXT:  entry:
11 ; CHECK-NEXT:    [[CMP3:%.*]] = icmp ult i32 0, [[N]]
12 ; CHECK-NEXT:    br i1 [[CMP3]], label [[FOR_INNER_PREHEADER_LVER_CHECK:%.*]], label [[FOR_END:%.*]]
13 ; CHECK:       for.inner.preheader.lver.check:
14 ; CHECK-NEXT:    [[FLATTEN_MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[N]], i32 [[N]])
15 ; CHECK-NEXT:    [[FLATTEN_TRIPCOUNT:%.*]] = extractvalue { i32, i1 } [[FLATTEN_MUL]], 0
16 ; CHECK-NEXT:    [[FLATTEN_OVERFLOW:%.*]] = extractvalue { i32, i1 } [[FLATTEN_MUL]], 1
17 ; CHECK-NEXT:    br i1 [[FLATTEN_OVERFLOW]], label [[FOR_INNER_PREHEADER_PH_LVER_ORIG:%.*]], label [[FOR_INNER_PREHEADER_PH:%.*]]
18 ; CHECK:       for.inner.preheader.ph.lver.orig:
19 ; CHECK-NEXT:    br label [[FOR_INNER_PREHEADER_LVER_ORIG:%.*]]
20 ; CHECK:       for.inner.preheader.lver.orig:
21 ; CHECK-NEXT:    [[I_LVER_ORIG:%.*]] = phi i32 [ 0, [[FOR_INNER_PREHEADER_PH_LVER_ORIG]] ], [ [[INC2_LVER_ORIG:%.*]], [[FOR_OUTER_LVER_ORIG:%.*]] ]
22 ; CHECK-NEXT:    br label [[FOR_INNER_LVER_ORIG:%.*]]
23 ; CHECK:       for.inner.lver.orig:
24 ; CHECK-NEXT:    [[J_LVER_ORIG:%.*]] = phi i32 [ 0, [[FOR_INNER_PREHEADER_LVER_ORIG]] ], [ [[INC1_LVER_ORIG:%.*]], [[FOR_INNER_LVER_ORIG]] ]
25 ; CHECK-NEXT:    [[MUL_LVER_ORIG:%.*]] = mul i32 [[I_LVER_ORIG]], [[N]]
26 ; CHECK-NEXT:    [[GEP_LVER_ORIG:%.*]] = getelementptr i32, ptr [[A]], i32 [[MUL_LVER_ORIG]]
27 ; CHECK-NEXT:    [[ARRAYIDX_LVER_ORIG:%.*]] = getelementptr i32, ptr [[GEP_LVER_ORIG]], i32 [[J_LVER_ORIG]]
28 ; CHECK-NEXT:    store i32 0, ptr [[ARRAYIDX_LVER_ORIG]], align 4
29 ; CHECK-NEXT:    [[INC1_LVER_ORIG]] = add nuw i32 [[J_LVER_ORIG]], 1
30 ; CHECK-NEXT:    [[CMP2_LVER_ORIG:%.*]] = icmp ult i32 [[INC1_LVER_ORIG]], [[N]]
31 ; CHECK-NEXT:    br i1 [[CMP2_LVER_ORIG]], label [[FOR_INNER_LVER_ORIG]], label [[FOR_OUTER_LVER_ORIG]]
32 ; CHECK:       for.outer.lver.orig:
33 ; CHECK-NEXT:    [[INC2_LVER_ORIG]] = add i32 [[I_LVER_ORIG]], 1
34 ; CHECK-NEXT:    [[CMP1_LVER_ORIG:%.*]] = icmp ult i32 [[INC2_LVER_ORIG]], [[N]]
35 ; CHECK-NEXT:    br i1 [[CMP1_LVER_ORIG]], label [[FOR_INNER_PREHEADER_LVER_ORIG]], label [[FOR_END_LOOPEXIT_LOOPEXIT:%.*]]
36 ; CHECK:       for.inner.preheader.ph:
37 ; CHECK-NEXT:    br label [[FOR_INNER_PREHEADER:%.*]]
38 ; CHECK:       for.inner.preheader:
39 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[FOR_INNER_PREHEADER_PH]] ], [ [[INC2:%.*]], [[FOR_OUTER:%.*]] ]
40 ; CHECK-NEXT:    [[FLATTEN_ARRAYIDX:%.*]] = getelementptr i32, ptr [[A]], i32 [[I]]
41 ; CHECK-NEXT:    br label [[FOR_INNER:%.*]]
42 ; CHECK:       for.inner:
43 ; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[FOR_INNER_PREHEADER]] ]
44 ; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[I]], [[N]]
45 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[A]], i32 [[MUL]]
46 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[GEP]], i32 [[J]]
47 ; CHECK-NEXT:    store i32 0, ptr [[FLATTEN_ARRAYIDX]], align 4
48 ; CHECK-NEXT:    [[INC1:%.*]] = add nuw i32 [[J]], 1
49 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[INC1]], [[N]]
50 ; CHECK-NEXT:    br label [[FOR_OUTER]]
51 ; CHECK:       for.outer:
52 ; CHECK-NEXT:    [[INC2]] = add i32 [[I]], 1
53 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[INC2]], [[FLATTEN_TRIPCOUNT]]
54 ; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_INNER_PREHEADER]], label [[FOR_END_LOOPEXIT_LOOPEXIT1:%.*]]
55 ; CHECK:       for.end.loopexit.loopexit:
56 ; CHECK-NEXT:    br label [[FOR_END_LOOPEXIT:%.*]]
57 ; CHECK:       for.end.loopexit.loopexit1:
58 ; CHECK-NEXT:    br label [[FOR_END_LOOPEXIT]]
59 ; CHECK:       for.end.loopexit:
60 ; CHECK-NEXT:    br label [[FOR_END]]
61 ; CHECK:       for.end:
62 ; CHECK-NEXT:    ret void
64 entry:
65   %cmp3 = icmp ult i32 0, %N
66   br i1 %cmp3, label %for.outer.preheader, label %for.end
68 for.outer.preheader:
69   br label %for.inner.preheader
71 for.inner.preheader:
72   %i = phi i32 [ 0, %for.outer.preheader ], [ %inc2, %for.outer ]
73   br label %for.inner
75 for.inner:
76   %j = phi i32 [ 0, %for.inner.preheader ], [ %inc1, %for.inner ]
77   %mul = mul i32 %i, %N
78   %gep = getelementptr i32, ptr %A, i32 %mul
79   %arrayidx = getelementptr i32, ptr %gep, i32 %j
80   store i32 0, ptr %arrayidx, align 4
81   %inc1 = add nuw i32 %j, 1
82   %cmp2 = icmp ult i32 %inc1, %N
83   br i1 %cmp2, label %for.inner, label %for.outer
85 for.outer:
86   %inc2 = add i32 %i, 1
87   %cmp1 = icmp ult i32 %inc2, %N
88   br i1 %cmp1, label %for.inner.preheader, label %for.end.loopexit
90 for.end.loopexit:
91   br label %for.end
93 for.end:
94   ret void
97 ; We shouldn't version the loop here as the multiply would use an illegal type.
98 define void @noinbounds_gep_too_large_mul(i64 %N, ptr %A) {
99 ; CHECK-LABEL: define void @noinbounds_gep_too_large_mul(
100 ; CHECK-SAME: i64 [[N:%.*]], ptr [[A:%.*]]) {
101 ; CHECK-NEXT:  entry:
102 ; CHECK-NEXT:    [[CMP3:%.*]] = icmp ult i64 0, [[N]]
103 ; CHECK-NEXT:    br i1 [[CMP3]], label [[FOR_OUTER_PREHEADER:%.*]], label [[FOR_END:%.*]]
104 ; CHECK:       for.outer.preheader:
105 ; CHECK-NEXT:    br label [[FOR_INNER_PREHEADER:%.*]]
106 ; CHECK:       for.inner.preheader:
107 ; CHECK-NEXT:    [[I:%.*]] = phi i64 [ 0, [[FOR_OUTER_PREHEADER]] ], [ [[INC2:%.*]], [[FOR_OUTER:%.*]] ]
108 ; CHECK-NEXT:    br label [[FOR_INNER:%.*]]
109 ; CHECK:       for.inner:
110 ; CHECK-NEXT:    [[J:%.*]] = phi i64 [ 0, [[FOR_INNER_PREHEADER]] ], [ [[INC1:%.*]], [[FOR_INNER]] ]
111 ; CHECK-NEXT:    [[MUL:%.*]] = mul i64 [[I]], [[N]]
112 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[A]], i64 [[MUL]]
113 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr i32, ptr [[GEP]], i64 [[J]]
114 ; CHECK-NEXT:    store i32 0, ptr [[ARRAYIDX]], align 4
115 ; CHECK-NEXT:    [[INC1]] = add nuw i64 [[J]], 1
116 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i64 [[INC1]], [[N]]
117 ; CHECK-NEXT:    br i1 [[CMP2]], label [[FOR_INNER]], label [[FOR_OUTER]]
118 ; CHECK:       for.outer:
119 ; CHECK-NEXT:    [[INC2]] = add i64 [[I]], 1
120 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i64 [[INC2]], [[N]]
121 ; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_INNER_PREHEADER]], label [[FOR_END_LOOPEXIT:%.*]]
122 ; CHECK:       for.end.loopexit:
123 ; CHECK-NEXT:    br label [[FOR_END]]
124 ; CHECK:       for.end:
125 ; CHECK-NEXT:    ret void
127 entry:
128   %cmp3 = icmp ult i64 0, %N
129   br i1 %cmp3, label %for.outer.preheader, label %for.end
131 for.outer.preheader:
132   br label %for.inner.preheader
134 for.inner.preheader:
135   %i = phi i64 [ 0, %for.outer.preheader ], [ %inc2, %for.outer ]
136   br label %for.inner
138 for.inner:
139   %j = phi i64 [ 0, %for.inner.preheader ], [ %inc1, %for.inner ]
140   %mul = mul i64 %i, %N
141   %gep = getelementptr i32, ptr %A, i64 %mul
142   %arrayidx = getelementptr i32, ptr %gep, i64 %j
143   store i32 0, ptr %arrayidx, align 4
144   %inc1 = add nuw i64 %j, 1
145   %cmp2 = icmp ult i64 %inc1, %N
146   br i1 %cmp2, label %for.inner, label %for.outer
148 for.outer:
149   %inc2 = add i64 %i, 1
150   %cmp1 = icmp ult i64 %inc2, %N
151   br i1 %cmp1, label %for.inner.preheader, label %for.end.loopexit
153 for.end.loopexit:
154   br label %for.end
156 for.end:
157   ret void
160 ; A 3d loop corresponding to:
162 ;   for (int k = 0; k < N; ++k)
163 ;    for (int i = 0; i < N; ++i)
164 ;      for (int j = 0; j < M; ++j)
165 ;        f(&A[i*M+j]);
167 define void @d3_2(ptr %A, i32 %N, i32 %M) {
168 ; CHECK-LABEL: define void @d3_2(
169 ; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]], i32 [[M:%.*]]) {
170 ; CHECK-NEXT:  entry:
171 ; CHECK-NEXT:    [[CMP30:%.*]] = icmp sgt i32 [[N]], 0
172 ; CHECK-NEXT:    br i1 [[CMP30]], label [[FOR_COND1_PREHEADER_LR_PH:%.*]], label [[FOR_COND_CLEANUP:%.*]]
173 ; CHECK:       for.cond1.preheader.lr.ph:
174 ; CHECK-NEXT:    [[CMP625:%.*]] = icmp sgt i32 [[M]], 0
175 ; CHECK-NEXT:    br label [[FOR_COND1_PREHEADER_US:%.*]]
176 ; CHECK:       for.cond1.preheader.us:
177 ; CHECK-NEXT:    [[K_031_US:%.*]] = phi i32 [ 0, [[FOR_COND1_PREHEADER_LR_PH]] ], [ [[INC13_US:%.*]], [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US:%.*]] ]
178 ; CHECK-NEXT:    br i1 [[CMP625]], label [[FOR_COND5_PREHEADER_US_US_LVER_CHECK:%.*]], label [[FOR_COND5_PREHEADER_US43_PREHEADER:%.*]]
179 ; CHECK:       for.cond5.preheader.us43.preheader:
180 ; CHECK-NEXT:    br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US_LOOPEXIT50:%.*]]
181 ; CHECK:       for.cond5.preheader.us.us.lver.check:
182 ; CHECK-NEXT:    [[FLATTEN_MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[N]], i32 [[M]])
183 ; CHECK-NEXT:    [[FLATTEN_TRIPCOUNT:%.*]] = extractvalue { i32, i1 } [[FLATTEN_MUL]], 0
184 ; CHECK-NEXT:    [[FLATTEN_OVERFLOW:%.*]] = extractvalue { i32, i1 } [[FLATTEN_MUL]], 1
185 ; CHECK-NEXT:    br i1 [[FLATTEN_OVERFLOW]], label [[FOR_COND5_PREHEADER_US_US_PH_LVER_ORIG:%.*]], label [[FOR_COND5_PREHEADER_US_US_PH:%.*]]
186 ; CHECK:       for.cond5.preheader.us.us.ph.lver.orig:
187 ; CHECK-NEXT:    br label [[FOR_COND5_PREHEADER_US_US_LVER_ORIG:%.*]]
188 ; CHECK:       for.cond5.preheader.us.us.lver.orig:
189 ; CHECK-NEXT:    [[I_028_US_US_LVER_ORIG:%.*]] = phi i32 [ [[INC10_US_US_LVER_ORIG:%.*]], [[FOR_COND5_FOR_COND_CLEANUP7_CRIT_EDGE_US_US_LVER_ORIG:%.*]] ], [ 0, [[FOR_COND5_PREHEADER_US_US_PH_LVER_ORIG]] ]
190 ; CHECK-NEXT:    [[MUL_US_US_LVER_ORIG:%.*]] = mul nsw i32 [[I_028_US_US_LVER_ORIG]], [[M]]
191 ; CHECK-NEXT:    br label [[FOR_BODY8_US_US_LVER_ORIG:%.*]]
192 ; CHECK:       for.body8.us.us.lver.orig:
193 ; CHECK-NEXT:    [[J_026_US_US_LVER_ORIG:%.*]] = phi i32 [ 0, [[FOR_COND5_PREHEADER_US_US_LVER_ORIG]] ], [ [[INC_US_US_LVER_ORIG:%.*]], [[FOR_BODY8_US_US_LVER_ORIG]] ]
194 ; CHECK-NEXT:    [[ADD_US_US_LVER_ORIG:%.*]] = add nsw i32 [[J_026_US_US_LVER_ORIG]], [[MUL_US_US_LVER_ORIG]]
195 ; CHECK-NEXT:    [[IDXPROM_US_US_LVER_ORIG:%.*]] = sext i32 [[ADD_US_US_LVER_ORIG]] to i64
196 ; CHECK-NEXT:    [[ARRAYIDX_US_US_LVER_ORIG:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IDXPROM_US_US_LVER_ORIG]]
197 ; CHECK-NEXT:    tail call void @f(ptr [[ARRAYIDX_US_US_LVER_ORIG]])
198 ; CHECK-NEXT:    [[INC_US_US_LVER_ORIG]] = add nuw nsw i32 [[J_026_US_US_LVER_ORIG]], 1
199 ; CHECK-NEXT:    [[EXITCOND_LVER_ORIG:%.*]] = icmp ne i32 [[INC_US_US_LVER_ORIG]], [[M]]
200 ; CHECK-NEXT:    br i1 [[EXITCOND_LVER_ORIG]], label [[FOR_BODY8_US_US_LVER_ORIG]], label [[FOR_COND5_FOR_COND_CLEANUP7_CRIT_EDGE_US_US_LVER_ORIG]]
201 ; CHECK:       for.cond5.for.cond.cleanup7_crit_edge.us.us.lver.orig:
202 ; CHECK-NEXT:    [[INC10_US_US_LVER_ORIG]] = add nuw nsw i32 [[I_028_US_US_LVER_ORIG]], 1
203 ; CHECK-NEXT:    [[EXITCOND51_LVER_ORIG:%.*]] = icmp ne i32 [[INC10_US_US_LVER_ORIG]], [[N]]
204 ; CHECK-NEXT:    br i1 [[EXITCOND51_LVER_ORIG]], label [[FOR_COND5_PREHEADER_US_US_LVER_ORIG]], label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US_LOOPEXIT_LOOPEXIT:%.*]]
205 ; CHECK:       for.cond5.preheader.us.us.ph:
206 ; CHECK-NEXT:    br label [[FOR_COND5_PREHEADER_US_US:%.*]]
207 ; CHECK:       for.cond1.for.cond.cleanup3_crit_edge.us.loopexit.loopexit:
208 ; CHECK-NEXT:    br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US_LOOPEXIT:%.*]]
209 ; CHECK:       for.cond1.for.cond.cleanup3_crit_edge.us.loopexit.loopexit1:
210 ; CHECK-NEXT:    br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US_LOOPEXIT]]
211 ; CHECK:       for.cond1.for.cond.cleanup3_crit_edge.us.loopexit:
212 ; CHECK-NEXT:    br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US]]
213 ; CHECK:       for.cond1.for.cond.cleanup3_crit_edge.us.loopexit50:
214 ; CHECK-NEXT:    br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US]]
215 ; CHECK:       for.cond1.for.cond.cleanup3_crit_edge.us:
216 ; CHECK-NEXT:    [[INC13_US]] = add nuw nsw i32 [[K_031_US]], 1
217 ; CHECK-NEXT:    [[EXITCOND52:%.*]] = icmp ne i32 [[INC13_US]], [[N]]
218 ; CHECK-NEXT:    br i1 [[EXITCOND52]], label [[FOR_COND1_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
219 ; CHECK:       for.cond5.preheader.us.us:
220 ; CHECK-NEXT:    [[I_028_US_US:%.*]] = phi i32 [ [[INC10_US_US:%.*]], [[FOR_COND5_FOR_COND_CLEANUP7_CRIT_EDGE_US_US:%.*]] ], [ 0, [[FOR_COND5_PREHEADER_US_US_PH]] ]
221 ; CHECK-NEXT:    [[MUL_US_US:%.*]] = mul nsw i32 [[I_028_US_US]], [[M]]
222 ; CHECK-NEXT:    br label [[FOR_BODY8_US_US:%.*]]
223 ; CHECK:       for.cond5.for.cond.cleanup7_crit_edge.us.us:
224 ; CHECK-NEXT:    [[INC10_US_US]] = add nuw nsw i32 [[I_028_US_US]], 1
225 ; CHECK-NEXT:    [[EXITCOND51:%.*]] = icmp ne i32 [[INC10_US_US]], [[FLATTEN_TRIPCOUNT]]
226 ; CHECK-NEXT:    br i1 [[EXITCOND51]], label [[FOR_COND5_PREHEADER_US_US]], label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US_LOOPEXIT_LOOPEXIT1:%.*]]
227 ; CHECK:       for.body8.us.us:
228 ; CHECK-NEXT:    [[J_026_US_US:%.*]] = phi i32 [ 0, [[FOR_COND5_PREHEADER_US_US]] ]
229 ; CHECK-NEXT:    [[ADD_US_US:%.*]] = add nsw i32 [[J_026_US_US]], [[MUL_US_US]]
230 ; CHECK-NEXT:    [[IDXPROM_US_US:%.*]] = sext i32 [[I_028_US_US]] to i64
231 ; CHECK-NEXT:    [[ARRAYIDX_US_US:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IDXPROM_US_US]]
232 ; CHECK-NEXT:    tail call void @f(ptr [[ARRAYIDX_US_US]])
233 ; CHECK-NEXT:    [[INC_US_US:%.*]] = add nuw nsw i32 [[J_026_US_US]], 1
234 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[INC_US_US]], [[M]]
235 ; CHECK-NEXT:    br label [[FOR_COND5_FOR_COND_CLEANUP7_CRIT_EDGE_US_US]]
236 ; CHECK:       for.cond.cleanup.loopexit:
237 ; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
238 ; CHECK:       for.cond.cleanup:
239 ; CHECK-NEXT:    ret void
241 entry:
242   %cmp30 = icmp sgt i32 %N, 0
243   br i1 %cmp30, label %for.cond1.preheader.lr.ph, label %for.cond.cleanup
245 for.cond1.preheader.lr.ph:
246   %cmp625 = icmp sgt i32 %M, 0
247   br label %for.cond1.preheader.us
249 for.cond1.preheader.us:
250   %k.031.us = phi i32 [ 0, %for.cond1.preheader.lr.ph ], [ %inc13.us, %for.cond1.for.cond.cleanup3_crit_edge.us ]
251   br i1 %cmp625, label %for.cond5.preheader.us.us.preheader, label %for.cond5.preheader.us43.preheader
253 for.cond5.preheader.us43.preheader:
254   br label %for.cond1.for.cond.cleanup3_crit_edge.us.loopexit50
256 for.cond5.preheader.us.us.preheader:
257   br label %for.cond5.preheader.us.us
259 for.cond1.for.cond.cleanup3_crit_edge.us.loopexit:
260   br label %for.cond1.for.cond.cleanup3_crit_edge.us
262 for.cond1.for.cond.cleanup3_crit_edge.us.loopexit50:
263   br label %for.cond1.for.cond.cleanup3_crit_edge.us
265 for.cond1.for.cond.cleanup3_crit_edge.us:
266   %inc13.us = add nuw nsw i32 %k.031.us, 1
267   %exitcond52 = icmp ne i32 %inc13.us, %N
268   br i1 %exitcond52, label %for.cond1.preheader.us, label %for.cond.cleanup.loopexit
270 for.cond5.preheader.us.us:
271   %i.028.us.us = phi i32 [ %inc10.us.us, %for.cond5.for.cond.cleanup7_crit_edge.us.us ], [ 0, %for.cond5.preheader.us.us.preheader ]
272   %mul.us.us = mul nsw i32 %i.028.us.us, %M
273   br label %for.body8.us.us
275 for.cond5.for.cond.cleanup7_crit_edge.us.us:
276   %inc10.us.us = add nuw nsw i32 %i.028.us.us, 1
277   %exitcond51 = icmp ne i32 %inc10.us.us, %N
278   br i1 %exitcond51, label %for.cond5.preheader.us.us, label %for.cond1.for.cond.cleanup3_crit_edge.us.loopexit
280 for.body8.us.us:
281   %j.026.us.us = phi i32 [ 0, %for.cond5.preheader.us.us ], [ %inc.us.us, %for.body8.us.us ]
282   %add.us.us = add nsw i32 %j.026.us.us, %mul.us.us
283   %idxprom.us.us = sext i32 %add.us.us to i64
284   %arrayidx.us.us = getelementptr inbounds i32, ptr %A, i64 %idxprom.us.us
285   tail call void @f(ptr %arrayidx.us.us) #2
286   %inc.us.us = add nuw nsw i32 %j.026.us.us, 1
287   %exitcond = icmp ne i32 %inc.us.us, %M
288   br i1 %exitcond, label %for.body8.us.us, label %for.cond5.for.cond.cleanup7_crit_edge.us.us
290 for.cond.cleanup.loopexit:
291   br label %for.cond.cleanup
293 for.cond.cleanup:
294   ret void
297 ; GEP doesn't dominate the loop latch so we need to check if N*M will overflow.
298 @first = global i32 1, align 4
299 @a = external global [0 x i8], align 1
300 define void @overflow(i32 %lim, ptr %a) {
301 ; CHECK-LABEL: define void @overflow(
302 ; CHECK-SAME: i32 [[LIM:%.*]], ptr [[A:%.*]]) {
303 ; CHECK-NEXT:  entry:
304 ; CHECK-NEXT:    [[CMP17_NOT:%.*]] = icmp eq i32 [[LIM]], 0
305 ; CHECK-NEXT:    br i1 [[CMP17_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_COND1_PREHEADER_LVER_CHECK:%.*]]
306 ; CHECK:       for.cond1.preheader.lver.check:
307 ; CHECK-NEXT:    [[FLATTEN_MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[LIM]], i32 100000)
308 ; CHECK-NEXT:    [[FLATTEN_TRIPCOUNT:%.*]] = extractvalue { i32, i1 } [[FLATTEN_MUL]], 0
309 ; CHECK-NEXT:    [[FLATTEN_OVERFLOW:%.*]] = extractvalue { i32, i1 } [[FLATTEN_MUL]], 1
310 ; CHECK-NEXT:    br i1 [[FLATTEN_OVERFLOW]], label [[FOR_COND1_PREHEADER_PH_LVER_ORIG:%.*]], label [[FOR_COND1_PREHEADER_PH:%.*]]
311 ; CHECK:       for.cond1.preheader.ph.lver.orig:
312 ; CHECK-NEXT:    br label [[FOR_COND1_PREHEADER_LVER_ORIG:%.*]]
313 ; CHECK:       for.cond1.preheader.lver.orig:
314 ; CHECK-NEXT:    [[I_018_LVER_ORIG:%.*]] = phi i32 [ [[INC6_LVER_ORIG:%.*]], [[FOR_COND_CLEANUP3_LVER_ORIG:%.*]] ], [ 0, [[FOR_COND1_PREHEADER_PH_LVER_ORIG]] ]
315 ; CHECK-NEXT:    [[MUL_LVER_ORIG:%.*]] = mul i32 [[I_018_LVER_ORIG]], 100000
316 ; CHECK-NEXT:    br label [[FOR_BODY4_LVER_ORIG:%.*]]
317 ; CHECK:       for.body4.lver.orig:
318 ; CHECK-NEXT:    [[J_016_LVER_ORIG:%.*]] = phi i32 [ 0, [[FOR_COND1_PREHEADER_LVER_ORIG]] ], [ [[INC_LVER_ORIG:%.*]], [[IF_END_LVER_ORIG:%.*]] ]
319 ; CHECK-NEXT:    [[ADD_LVER_ORIG:%.*]] = add i32 [[J_016_LVER_ORIG]], [[MUL_LVER_ORIG]]
320 ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr @first, align 4
321 ; CHECK-NEXT:    [[TOBOOL_NOT_LVER_ORIG:%.*]] = icmp eq i32 [[TMP0]], 0
322 ; CHECK-NEXT:    br i1 [[TOBOOL_NOT_LVER_ORIG]], label [[IF_END_LVER_ORIG]], label [[IF_THEN_LVER_ORIG:%.*]]
323 ; CHECK:       if.then.lver.orig:
324 ; CHECK-NEXT:    [[ARRAYIDX_LVER_ORIG:%.*]] = getelementptr inbounds [0 x i8], ptr @a, i32 0, i32 [[ADD_LVER_ORIG]]
325 ; CHECK-NEXT:    [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX_LVER_ORIG]], align 1
326 ; CHECK-NEXT:    tail call void asm sideeffect "", "r"(i8 [[TMP1]])
327 ; CHECK-NEXT:    store i32 0, ptr @first, align 4
328 ; CHECK-NEXT:    br label [[IF_END_LVER_ORIG]]
329 ; CHECK:       if.end.lver.orig:
330 ; CHECK-NEXT:    tail call void asm sideeffect "", "r"(i32 [[ADD_LVER_ORIG]])
331 ; CHECK-NEXT:    [[INC_LVER_ORIG]] = add nuw nsw i32 [[J_016_LVER_ORIG]], 1
332 ; CHECK-NEXT:    [[CMP2_LVER_ORIG:%.*]] = icmp ult i32 [[J_016_LVER_ORIG]], 99999
333 ; CHECK-NEXT:    br i1 [[CMP2_LVER_ORIG]], label [[FOR_BODY4_LVER_ORIG]], label [[FOR_COND_CLEANUP3_LVER_ORIG]]
334 ; CHECK:       for.cond.cleanup3.lver.orig:
335 ; CHECK-NEXT:    [[INC6_LVER_ORIG]] = add i32 [[I_018_LVER_ORIG]], 1
336 ; CHECK-NEXT:    [[CMP_LVER_ORIG:%.*]] = icmp ult i32 [[INC6_LVER_ORIG]], [[LIM]]
337 ; CHECK-NEXT:    br i1 [[CMP_LVER_ORIG]], label [[FOR_COND1_PREHEADER_LVER_ORIG]], label [[FOR_COND_CLEANUP_LOOPEXIT_LOOPEXIT:%.*]]
338 ; CHECK:       for.cond1.preheader.ph:
339 ; CHECK-NEXT:    br label [[FOR_COND1_PREHEADER:%.*]]
340 ; CHECK:       for.cond1.preheader:
341 ; CHECK-NEXT:    [[I_018:%.*]] = phi i32 [ [[INC6:%.*]], [[FOR_COND_CLEANUP3:%.*]] ], [ 0, [[FOR_COND1_PREHEADER_PH]] ]
342 ; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[I_018]], 100000
343 ; CHECK-NEXT:    br label [[FOR_BODY4:%.*]]
344 ; CHECK:       for.cond.cleanup.loopexit.loopexit:
345 ; CHECK-NEXT:    br label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
346 ; CHECK:       for.cond.cleanup.loopexit.loopexit1:
347 ; CHECK-NEXT:    br label [[FOR_COND_CLEANUP_LOOPEXIT]]
348 ; CHECK:       for.cond.cleanup.loopexit:
349 ; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
350 ; CHECK:       for.cond.cleanup:
351 ; CHECK-NEXT:    ret void
352 ; CHECK:       for.cond.cleanup3:
353 ; CHECK-NEXT:    [[INC6]] = add i32 [[I_018]], 1
354 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[INC6]], [[FLATTEN_TRIPCOUNT]]
355 ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_COND1_PREHEADER]], label [[FOR_COND_CLEANUP_LOOPEXIT_LOOPEXIT1:%.*]]
356 ; CHECK:       for.body4:
357 ; CHECK-NEXT:    [[J_016:%.*]] = phi i32 [ 0, [[FOR_COND1_PREHEADER]] ]
358 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[J_016]], [[MUL]]
359 ; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr @first, align 4
360 ; CHECK-NEXT:    [[TOBOOL_NOT:%.*]] = icmp eq i32 [[TMP2]], 0
361 ; CHECK-NEXT:    br i1 [[TOBOOL_NOT]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
362 ; CHECK:       if.then:
363 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr @a, i32 0, i32 [[I_018]]
364 ; CHECK-NEXT:    [[TMP3:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
365 ; CHECK-NEXT:    tail call void asm sideeffect "", "r"(i8 [[TMP3]])
366 ; CHECK-NEXT:    store i32 0, ptr @first, align 4
367 ; CHECK-NEXT:    br label [[IF_END]]
368 ; CHECK:       if.end:
369 ; CHECK-NEXT:    tail call void asm sideeffect "", "r"(i32 [[I_018]])
370 ; CHECK-NEXT:    [[INC:%.*]] = add nuw nsw i32 [[J_016]], 1
371 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[J_016]], 99999
372 ; CHECK-NEXT:    br label [[FOR_COND_CLEANUP3]]
374 entry:
375   %cmp17.not = icmp eq i32 %lim, 0
376   br i1 %cmp17.not, label %for.cond.cleanup, label %for.cond1.preheader.preheader
378 for.cond1.preheader.preheader:
379   br label %for.cond1.preheader
381 for.cond1.preheader:
382   %i.018 = phi i32 [ %inc6, %for.cond.cleanup3 ], [ 0, %for.cond1.preheader.preheader ]
383   %mul = mul i32 %i.018, 100000
384   br label %for.body4
386 for.cond.cleanup.loopexit:
387   br label %for.cond.cleanup
389 for.cond.cleanup:
390   ret void
392 for.cond.cleanup3:
393   %inc6 = add i32 %i.018, 1
394   %cmp = icmp ult i32 %inc6, %lim
395   br i1 %cmp, label %for.cond1.preheader, label %for.cond.cleanup.loopexit
397 for.body4:
398   %j.016 = phi i32 [ 0, %for.cond1.preheader ], [ %inc, %if.end ]
399   %add = add i32 %j.016, %mul
400   %0 = load i32, ptr @first, align 4
401   %tobool.not = icmp eq i32 %0, 0
402   br i1 %tobool.not, label %if.end, label %if.then
404 if.then:
405   %arrayidx = getelementptr inbounds [0 x i8], ptr @a, i32 0, i32 %add
406   %1 = load i8, ptr %arrayidx, align 1
407   tail call void asm sideeffect "", "r"(i8 %1)
408   store i32 0, ptr @first, align 4
409   br label %if.end
411 if.end:
412   tail call void asm sideeffect "", "r"(i32 %add)
413   %inc = add nuw nsw i32 %j.016, 1
414   %cmp2 = icmp ult i32 %j.016, 99999
415   br i1 %cmp2, label %for.body4, label %for.cond.cleanup3
418 declare dso_local void @f(ptr)