1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -S -loop-simplify -loop-flatten -loop-flatten-widen-iv=true -verify-loop-info -verify-dom-info -verify-scev -verify | FileCheck %s --check-prefix=CHECK
3; RUN: opt < %s -S -loop-simplify -loop-flatten -loop-flatten-widen-iv=false -verify-loop-info -verify-dom-info -verify-scev -verify | FileCheck %s --check-prefix=DONTWIDEN
4
5target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
6
7; DONTWIDEN-NOT:   %flatten.tripcount
8; DONTWIDEN-NOT:   %flatten.trunciv
9
10; Function Attrs: nounwind
11define void @foo(i32* %A, i32 %N, i32 %M) {
12; CHECK-LABEL: @foo(
13; CHECK-NEXT:  entry:
14; CHECK-NEXT:    [[CMP17:%.*]] = icmp sgt i32 [[N:%.*]], 0
15; CHECK-NEXT:    br i1 [[CMP17]], label [[FOR_COND1_PREHEADER_LR_PH:%.*]], label [[FOR_COND_CLEANUP:%.*]]
16; CHECK:       for.cond1.preheader.lr.ph:
17; CHECK-NEXT:    [[CMP215:%.*]] = icmp sgt i32 [[M:%.*]], 0
18; CHECK-NEXT:    br i1 [[CMP215]], label [[FOR_COND1_PREHEADER_US_PREHEADER:%.*]], label [[FOR_COND_CLEANUP]]
19; CHECK:       for.cond1.preheader.us.preheader:
20; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[M]] to i64
21; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[N]] to i64
22; CHECK-NEXT:    [[FLATTEN_TRIPCOUNT:%.*]] = mul i64 [[TMP0]], [[TMP1]]
23; CHECK-NEXT:    br label [[FOR_COND1_PREHEADER_US:%.*]]
24; CHECK:       for.cond1.preheader.us:
25; CHECK-NEXT:    [[INDVAR1:%.*]] = phi i64 [ [[INDVAR_NEXT2:%.*]], [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US:%.*]] ], [ 0, [[FOR_COND1_PREHEADER_US_PREHEADER]] ]
26; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[INDVAR1]] to i32
27; CHECK-NEXT:    [[MUL_US:%.*]] = mul nsw i32 [[TMP2]], [[M]]
28; CHECK-NEXT:    [[FLATTEN_TRUNCIV:%.*]] = trunc i64 [[INDVAR1]] to i32
29; CHECK-NEXT:    br label [[FOR_BODY4_US:%.*]]
30; CHECK:       for.body4.us:
31; CHECK-NEXT:    [[INDVAR:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER_US]] ]
32; CHECK-NEXT:    [[TMP3:%.*]] = trunc i64 [[INDVAR]] to i32
33; CHECK-NEXT:    [[ADD_US:%.*]] = add nsw i32 [[TMP3]], [[MUL_US]]
34; CHECK-NEXT:    [[IDXPROM_US:%.*]] = sext i32 [[FLATTEN_TRUNCIV]] to i64
35; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[IDXPROM_US]]
36; CHECK-NEXT:    tail call void @f(i32* [[ARRAYIDX_US]])
37; CHECK-NEXT:    [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1
38; CHECK-NEXT:    [[CMP2_US:%.*]] = icmp slt i64 [[INDVAR_NEXT]], [[TMP0]]
39; CHECK-NEXT:    br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US]]
40; CHECK:       for.cond1.for.cond.cleanup3_crit_edge.us:
41; CHECK-NEXT:    [[INDVAR_NEXT2]] = add i64 [[INDVAR1]], 1
42; CHECK-NEXT:    [[CMP_US:%.*]] = icmp slt i64 [[INDVAR_NEXT2]], [[FLATTEN_TRIPCOUNT]]
43; CHECK-NEXT:    br i1 [[CMP_US]], label [[FOR_COND1_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
44; CHECK:       for.cond.cleanup.loopexit:
45; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
46; CHECK:       for.cond.cleanup:
47; CHECK-NEXT:    ret void
48;
49entry:
50  %cmp17 = icmp sgt i32 %N, 0
51  br i1 %cmp17, label %for.cond1.preheader.lr.ph, label %for.cond.cleanup
52
53for.cond1.preheader.lr.ph:
54  %cmp215 = icmp sgt i32 %M, 0
55  br i1 %cmp215, label %for.cond1.preheader.us.preheader, label %for.cond.cleanup
56
57for.cond1.preheader.us.preheader:
58  br label %for.cond1.preheader.us
59
60for.cond1.preheader.us:
61  %i.018.us = phi i32 [ %inc6.us, %for.cond1.for.cond.cleanup3_crit_edge.us ], [ 0, %for.cond1.preheader.us.preheader ]
62  %mul.us = mul nsw i32 %i.018.us, %M
63  br label %for.body4.us
64
65for.body4.us:
66  %j.016.us = phi i32 [ 0, %for.cond1.preheader.us ], [ %inc.us, %for.body4.us ]
67  %add.us = add nsw i32 %j.016.us, %mul.us
68  %idxprom.us = sext i32 %add.us to i64
69  %arrayidx.us = getelementptr inbounds i32, i32* %A, i64 %idxprom.us
70  tail call void @f(i32* %arrayidx.us) #2
71  %inc.us = add nuw nsw i32 %j.016.us, 1
72  %cmp2.us = icmp slt i32 %inc.us, %M
73  br i1 %cmp2.us, label %for.body4.us, label %for.cond1.for.cond.cleanup3_crit_edge.us
74
75for.cond1.for.cond.cleanup3_crit_edge.us:
76  %inc6.us = add nuw nsw i32 %i.018.us, 1
77  %cmp.us = icmp slt i32 %inc6.us, %N
78  br i1 %cmp.us, label %for.cond1.preheader.us, label %for.cond.cleanup
79
80for.cond.cleanup:
81  ret void
82}
83
84define void @zext(i32 %N, i16* nocapture %A, i16 %val) {
85; CHECK-LABEL: @zext(
86; CHECK-NEXT:  entry:
87; CHECK-NEXT:    [[CMP20_NOT:%.*]] = icmp eq i32 [[N:%.*]], 0
88; CHECK-NEXT:    br i1 [[CMP20_NOT]], label [[FOR_END9:%.*]], label [[FOR_COND1_PREHEADER_US_PREHEADER:%.*]]
89; CHECK:       for.cond1.preheader.us.preheader:
90; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[N]] to i64
91; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[N]] to i64
92; CHECK-NEXT:    [[FLATTEN_TRIPCOUNT:%.*]] = mul i64 [[TMP0]], [[TMP1]]
93; CHECK-NEXT:    br label [[FOR_COND1_PREHEADER_US:%.*]]
94; CHECK:       for.cond1.preheader.us:
95; CHECK-NEXT:    [[INDVAR1:%.*]] = phi i64 [ [[INDVAR_NEXT2:%.*]], [[FOR_COND1_FOR_INC7_CRIT_EDGE_US:%.*]] ], [ 0, [[FOR_COND1_PREHEADER_US_PREHEADER]] ]
96; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[INDVAR1]] to i32
97; CHECK-NEXT:    [[MUL_US:%.*]] = mul i32 [[TMP2]], [[N]]
98; CHECK-NEXT:    [[FLATTEN_TRUNCIV:%.*]] = trunc i64 [[INDVAR1]] to i32
99; CHECK-NEXT:    br label [[FOR_BODY3_US:%.*]]
100; CHECK:       for.body3.us:
101; CHECK-NEXT:    [[INDVAR:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER_US]] ]
102; CHECK-NEXT:    [[TMP3:%.*]] = trunc i64 [[INDVAR]] to i32
103; CHECK-NEXT:    [[ADD_US:%.*]] = add i32 [[TMP3]], [[MUL_US]]
104; CHECK-NEXT:    [[IDXPROM_US:%.*]] = zext i32 [[FLATTEN_TRUNCIV]] to i64
105; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i16, i16* [[A:%.*]], i64 [[IDXPROM_US]]
106; CHECK-NEXT:    [[TMP4:%.*]] = load i16, i16* [[ARRAYIDX_US]], align 2
107; CHECK-NEXT:    [[ADD5_US:%.*]] = add i16 [[TMP4]], [[VAL:%.*]]
108; CHECK-NEXT:    store i16 [[ADD5_US]], i16* [[ARRAYIDX_US]], align 2
109; CHECK-NEXT:    [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1
110; CHECK-NEXT:    [[CMP2_US:%.*]] = icmp ult i64 [[INDVAR_NEXT]], [[TMP0]]
111; CHECK-NEXT:    br label [[FOR_COND1_FOR_INC7_CRIT_EDGE_US]]
112; CHECK:       for.cond1.for.inc7_crit_edge.us:
113; CHECK-NEXT:    [[INDVAR_NEXT2]] = add i64 [[INDVAR1]], 1
114; CHECK-NEXT:    [[CMP_US:%.*]] = icmp ult i64 [[INDVAR_NEXT2]], [[FLATTEN_TRIPCOUNT]]
115; CHECK-NEXT:    br i1 [[CMP_US]], label [[FOR_COND1_PREHEADER_US]], label [[FOR_END9_LOOPEXIT:%.*]]
116; CHECK:       for.end9.loopexit:
117; CHECK-NEXT:    br label [[FOR_END9]]
118; CHECK:       for.end9:
119; CHECK-NEXT:    ret void
120;
121entry:
122  %cmp20.not = icmp eq i32 %N, 0
123  br i1 %cmp20.not, label %for.end9, label %for.cond1.preheader.us.preheader
124
125for.cond1.preheader.us.preheader:
126  br label %for.cond1.preheader.us
127
128for.cond1.preheader.us:
129  %i.021.us = phi i32 [ %inc8.us, %for.cond1.for.inc7_crit_edge.us ], [ 0, %for.cond1.preheader.us.preheader ]
130  %mul.us = mul i32 %i.021.us, %N
131  br label %for.body3.us
132
133for.body3.us:
134  %j.019.us = phi i32 [ 0, %for.cond1.preheader.us ], [ %inc.us, %for.body3.us ]
135  %add.us = add i32 %j.019.us, %mul.us
136  %idxprom.us = zext i32 %add.us to i64
137  %arrayidx.us = getelementptr inbounds i16, i16* %A, i64 %idxprom.us
138  %0 = load i16, i16* %arrayidx.us, align 2
139  %add5.us = add i16 %0, %val
140  store i16 %add5.us, i16* %arrayidx.us, align 2
141  %inc.us = add nuw i32 %j.019.us, 1
142  %cmp2.us = icmp ult i32 %inc.us, %N
143  br i1 %cmp2.us, label %for.body3.us, label %for.cond1.for.inc7_crit_edge.us
144
145for.cond1.for.inc7_crit_edge.us:
146  %inc8.us = add i32 %i.021.us, 1
147  %cmp.us = icmp ult i32 %inc8.us, %N
148  br i1 %cmp.us, label %for.cond1.preheader.us, label %for.end9.loopexit
149
150for.end9.loopexit:
151  br label %for.end9
152
153for.end9:
154  ret void
155}
156
157; This IR corresponds to this input:
158;
159; void test(char n, char m) {
160;   for(char i = 0; i < n; i++)
161;     for(char j = 0; j < m; j++) {
162;       char x = i*m+j;
163;       use_32(x);
164;     }
165; }
166;
167define void @test(i8 %n, i8 %m) {
168; CHECK-LABEL: @test(
169; CHECK-NEXT:  entry:
170; CHECK-NEXT:    [[CMP25_NOT:%.*]] = icmp eq i8 [[N:%.*]], 0
171; CHECK-NEXT:    br i1 [[CMP25_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_COND3_PREHEADER_LR_PH:%.*]]
172; CHECK:       for.cond3.preheader.lr.ph:
173; CHECK-NEXT:    [[CMP623_NOT:%.*]] = icmp eq i8 [[M:%.*]], 0
174; CHECK-NEXT:    br i1 [[CMP623_NOT]], label [[FOR_COND3_PREHEADER_PREHEADER:%.*]], label [[FOR_COND3_PREHEADER_US_PREHEADER:%.*]]
175; CHECK:       for.cond3.preheader.preheader:
176; CHECK-NEXT:    br label [[FOR_COND3_PREHEADER:%.*]]
177; CHECK:       for.cond3.preheader.us.preheader:
178; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[M]] to i64
179; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[N]] to i64
180; CHECK-NEXT:    [[FLATTEN_TRIPCOUNT:%.*]] = mul i64 [[TMP0]], [[TMP1]]
181; CHECK-NEXT:    br label [[FOR_COND3_PREHEADER_US:%.*]]
182; CHECK:       for.cond3.preheader.us:
183; CHECK-NEXT:    [[INDVAR2:%.*]] = phi i64 [ [[INDVAR_NEXT3:%.*]], [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US:%.*]] ], [ 0, [[FOR_COND3_PREHEADER_US_PREHEADER]] ]
184; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[INDVAR2]] to i8
185; CHECK-NEXT:    [[MUL_US:%.*]] = mul i8 [[TMP2]], [[M]]
186; CHECK-NEXT:    [[FLATTEN_TRUNCIV:%.*]] = trunc i64 [[INDVAR2]] to i8
187; CHECK-NEXT:    br label [[FOR_BODY9_US:%.*]]
188; CHECK:       for.body9.us:
189; CHECK-NEXT:    [[INDVAR:%.*]] = phi i64 [ 0, [[FOR_COND3_PREHEADER_US]] ]
190; CHECK-NEXT:    [[TMP3:%.*]] = trunc i64 [[INDVAR]] to i8
191; CHECK-NEXT:    [[ADD_US:%.*]] = add i8 [[TMP3]], [[MUL_US]]
192; CHECK-NEXT:    [[CONV14_US:%.*]] = zext i8 [[FLATTEN_TRUNCIV]] to i32
193; CHECK-NEXT:    [[CALL_US:%.*]] = tail call i32 @use_32(i32 [[CONV14_US]])
194; CHECK-NEXT:    [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1
195; CHECK-NEXT:    [[CMP6_US:%.*]] = icmp ult i64 [[INDVAR_NEXT]], [[TMP0]]
196; CHECK-NEXT:    br label [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US]]
197; CHECK:       for.cond3.for.cond.cleanup8_crit_edge.us:
198; CHECK-NEXT:    [[INDVAR_NEXT3]] = add i64 [[INDVAR2]], 1
199; CHECK-NEXT:    [[CMP_US:%.*]] = icmp ult i64 [[INDVAR_NEXT3]], [[FLATTEN_TRIPCOUNT]]
200; CHECK-NEXT:    br i1 [[CMP_US]], label [[FOR_COND3_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT1:%.*]]
201; CHECK:       for.cond3.preheader:
202; CHECK-NEXT:    [[I_026:%.*]] = phi i8 [ [[INC16:%.*]], [[FOR_COND3_PREHEADER]] ], [ 0, [[FOR_COND3_PREHEADER_PREHEADER]] ]
203; CHECK-NEXT:    [[INC16]] = add i8 [[I_026]], 1
204; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[INC16]], [[N]]
205; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_COND3_PREHEADER]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
206; CHECK:       for.cond.cleanup.loopexit:
207; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
208; CHECK:       for.cond.cleanup.loopexit1:
209; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
210; CHECK:       for.cond.cleanup:
211; CHECK-NEXT:    ret void
212;
213entry:
214  %cmp25.not = icmp eq i8 %n, 0
215  br i1 %cmp25.not, label %for.cond.cleanup, label %for.cond3.preheader.lr.ph
216
217for.cond3.preheader.lr.ph:
218  %cmp623.not = icmp eq i8 %m, 0
219  br i1 %cmp623.not, label %for.cond3.preheader.preheader, label %for.cond3.preheader.us.preheader
220
221for.cond3.preheader.preheader:
222  br label %for.cond3.preheader
223
224for.cond3.preheader.us.preheader:
225  br label %for.cond3.preheader.us
226
227for.cond3.preheader.us:
228  %i.026.us = phi i8 [ %inc16.us, %for.cond3.for.cond.cleanup8_crit_edge.us ], [ 0, %for.cond3.preheader.us.preheader ]
229  %mul.us = mul i8 %i.026.us, %m
230  br label %for.body9.us
231
232for.body9.us:
233  %j.024.us = phi i8 [ 0, %for.cond3.preheader.us ], [ %inc.us, %for.body9.us ]
234  %add.us = add i8 %j.024.us, %mul.us
235  %conv14.us = zext i8 %add.us to i32
236  %call.us = tail call i32 @use_32(i32 %conv14.us) #2
237  %inc.us = add nuw i8 %j.024.us, 1
238  %cmp6.us = icmp ult i8 %inc.us, %m
239  br i1 %cmp6.us, label %for.body9.us, label %for.cond3.for.cond.cleanup8_crit_edge.us
240
241for.cond3.for.cond.cleanup8_crit_edge.us:
242  %inc16.us = add i8 %i.026.us, 1
243  %cmp.us = icmp ult i8 %inc16.us, %n
244  br i1 %cmp.us, label %for.cond3.preheader.us, label %for.cond.cleanup
245
246for.cond3.preheader:
247  %i.026 = phi i8 [ %inc16, %for.cond3.preheader ], [ 0, %for.cond3.preheader.preheader ]
248  %inc16 = add i8 %i.026, 1
249  %cmp = icmp ult i8 %inc16, %n
250  br i1 %cmp, label %for.cond3.preheader, label %for.cond.cleanup
251
252for.cond.cleanup:
253  ret void
254}
255
256; This IR corresponds to this input:
257;
258; void test3(char n, char m) {
259;   for(char i = 0; i < n; i++)
260;     for(char j = 0; j < m; j++) {
261;       char x = i*m+j;
262;       use_32(x);
263;       use_16(x);
264;       use_32(x);
265;       use_16(x);
266;       use_64(x);
267;     }
268; }
269;
270define void @test3(i8 %n, i8 %m) {
271; CHECK-LABEL: @test3(
272; CHECK-NEXT:  entry:
273; CHECK-NEXT:    [[CMP37_NOT:%.*]] = icmp eq i8 [[N:%.*]], 0
274; CHECK-NEXT:    br i1 [[CMP37_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_COND3_PREHEADER_LR_PH:%.*]]
275; CHECK:       for.cond3.preheader.lr.ph:
276; CHECK-NEXT:    [[CMP635_NOT:%.*]] = icmp eq i8 [[M:%.*]], 0
277; CHECK-NEXT:    br i1 [[CMP635_NOT]], label [[FOR_COND3_PREHEADER_PREHEADER:%.*]], label [[FOR_COND3_PREHEADER_US_PREHEADER:%.*]]
278; CHECK:       for.cond3.preheader.preheader:
279; CHECK-NEXT:    br label [[FOR_COND3_PREHEADER:%.*]]
280; CHECK:       for.cond3.preheader.us.preheader:
281; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[M]] to i64
282; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[N]] to i64
283; CHECK-NEXT:    [[FLATTEN_TRIPCOUNT:%.*]] = mul i64 [[TMP0]], [[TMP1]]
284; CHECK-NEXT:    br label [[FOR_COND3_PREHEADER_US:%.*]]
285; CHECK:       for.cond3.preheader.us:
286; CHECK-NEXT:    [[INDVAR2:%.*]] = phi i64 [ [[INDVAR_NEXT3:%.*]], [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US:%.*]] ], [ 0, [[FOR_COND3_PREHEADER_US_PREHEADER]] ]
287; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[INDVAR2]] to i8
288; CHECK-NEXT:    [[MUL_US:%.*]] = mul i8 [[TMP2]], [[M]]
289; CHECK-NEXT:    [[FLATTEN_TRUNCIV:%.*]] = trunc i64 [[INDVAR2]] to i8
290; CHECK-NEXT:    br label [[FOR_BODY9_US:%.*]]
291; CHECK:       for.body9.us:
292; CHECK-NEXT:    [[INDVAR:%.*]] = phi i64 [ 0, [[FOR_COND3_PREHEADER_US]] ]
293; CHECK-NEXT:    [[TMP3:%.*]] = trunc i64 [[INDVAR]] to i8
294; CHECK-NEXT:    [[ADD_US:%.*]] = add i8 [[TMP3]], [[MUL_US]]
295; CHECK-NEXT:    [[CONV14_US:%.*]] = zext i8 [[FLATTEN_TRUNCIV]] to i32
296; CHECK-NEXT:    [[CALL_US:%.*]] = tail call i32 @use_32(i32 [[CONV14_US]])
297; CHECK-NEXT:    [[CONV15_US:%.*]] = zext i8 [[FLATTEN_TRUNCIV]] to i16
298; CHECK-NEXT:    [[CALL16_US:%.*]] = tail call i32 @use_16(i16 [[CONV15_US]])
299; CHECK-NEXT:    [[CALL18_US:%.*]] = tail call i32 @use_32(i32 [[CONV14_US]])
300; CHECK-NEXT:    [[CALL20_US:%.*]] = tail call i32 @use_16(i16 [[CONV15_US]])
301; CHECK-NEXT:    [[CONV21_US:%.*]] = zext i8 [[FLATTEN_TRUNCIV]] to i64
302; CHECK-NEXT:    [[CALL22_US:%.*]] = tail call i32 @use_64(i64 [[CONV21_US]])
303; CHECK-NEXT:    [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1
304; CHECK-NEXT:    [[CMP6_US:%.*]] = icmp ult i64 [[INDVAR_NEXT]], [[TMP0]]
305; CHECK-NEXT:    br label [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US]]
306; CHECK:       for.cond3.for.cond.cleanup8_crit_edge.us:
307; CHECK-NEXT:    [[INDVAR_NEXT3]] = add i64 [[INDVAR2]], 1
308; CHECK-NEXT:    [[CMP_US:%.*]] = icmp ult i64 [[INDVAR_NEXT3]], [[FLATTEN_TRIPCOUNT]]
309; CHECK-NEXT:    br i1 [[CMP_US]], label [[FOR_COND3_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT1:%.*]]
310; CHECK:       for.cond3.preheader:
311; CHECK-NEXT:    [[I_038:%.*]] = phi i8 [ [[INC24:%.*]], [[FOR_COND3_PREHEADER]] ], [ 0, [[FOR_COND3_PREHEADER_PREHEADER]] ]
312; CHECK-NEXT:    [[INC24]] = add i8 [[I_038]], 1
313; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[INC24]], [[N]]
314; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_COND3_PREHEADER]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
315; CHECK:       for.cond.cleanup.loopexit:
316; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
317; CHECK:       for.cond.cleanup.loopexit1:
318; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
319; CHECK:       for.cond.cleanup:
320; CHECK-NEXT:    ret void
321;
322entry:
323  %cmp37.not = icmp eq i8 %n, 0
324  br i1 %cmp37.not, label %for.cond.cleanup, label %for.cond3.preheader.lr.ph
325
326for.cond3.preheader.lr.ph:
327  %cmp635.not = icmp eq i8 %m, 0
328  br i1 %cmp635.not, label %for.cond3.preheader.preheader, label %for.cond3.preheader.us.preheader
329
330for.cond3.preheader.preheader:
331  br label %for.cond3.preheader
332
333for.cond3.preheader.us.preheader:
334  br label %for.cond3.preheader.us
335
336for.cond3.preheader.us:
337  %i.038.us = phi i8 [ %inc24.us, %for.cond3.for.cond.cleanup8_crit_edge.us ], [ 0, %for.cond3.preheader.us.preheader ]
338  %mul.us = mul i8 %i.038.us, %m
339  br label %for.body9.us
340
341for.body9.us:
342  %j.036.us = phi i8 [ 0, %for.cond3.preheader.us ], [ %inc.us, %for.body9.us ]
343  %add.us = add i8 %j.036.us, %mul.us
344  %conv14.us = zext i8 %add.us to i32
345  %call.us = tail call i32 @use_32(i32 %conv14.us)
346  %conv15.us = zext i8 %add.us to i16
347  %call16.us = tail call i32 @use_16(i16 %conv15.us)
348  %call18.us = tail call i32 @use_32(i32 %conv14.us)
349  %call20.us = tail call i32 @use_16(i16 %conv15.us)
350  %conv21.us = zext i8 %add.us to i64
351  %call22.us = tail call i32 @use_64(i64 %conv21.us)
352  %inc.us = add nuw i8 %j.036.us, 1
353  %cmp6.us = icmp ult i8 %inc.us, %m
354  br i1 %cmp6.us, label %for.body9.us, label %for.cond3.for.cond.cleanup8_crit_edge.us
355
356for.cond3.for.cond.cleanup8_crit_edge.us:
357  %inc24.us = add i8 %i.038.us, 1
358  %cmp.us = icmp ult i8 %inc24.us, %n
359  br i1 %cmp.us, label %for.cond3.preheader.us, label %for.cond.cleanup
360
361for.cond3.preheader:
362  %i.038 = phi i8 [ %inc24, %for.cond3.preheader ], [ 0, %for.cond3.preheader.preheader ]
363  %inc24 = add i8 %i.038, 1
364  %cmp = icmp ult i8 %inc24, %n
365  br i1 %cmp, label %for.cond3.preheader, label %for.cond.cleanup
366
367for.cond.cleanup:
368  ret void
369}
370
371; This IR corresponds to this input:
372;
373; void test4(short n, short m) {
374;   for(short i = 0; i < n; i++)
375;     for(short j = 0; j < m; j++) {
376;       short x = i*m+j;
377;       use_32(x);
378;       use_16(x);
379;       use_32(x);
380;       use_16(x);
381;       use_64(x);
382;     }
383; }
384;
385define void @test4(i16 %n, i16 %m) {
386; CHECK-LABEL: @test4(
387; CHECK-NEXT:  entry:
388; CHECK-NEXT:    [[CMP38:%.*]] = icmp sgt i16 [[N:%.*]], 0
389; CHECK-NEXT:    br i1 [[CMP38]], label [[FOR_COND3_PREHEADER_LR_PH:%.*]], label [[FOR_COND_CLEANUP:%.*]]
390; CHECK:       for.cond3.preheader.lr.ph:
391; CHECK-NEXT:    [[CMP636:%.*]] = icmp sgt i16 [[M:%.*]], 0
392; CHECK-NEXT:    br i1 [[CMP636]], label [[FOR_COND3_PREHEADER_US_PREHEADER:%.*]], label [[FOR_COND3_PREHEADER_PREHEADER:%.*]]
393; CHECK:       for.cond3.preheader.preheader:
394; CHECK-NEXT:    br label [[FOR_COND3_PREHEADER:%.*]]
395; CHECK:       for.cond3.preheader.us.preheader:
396; CHECK-NEXT:    [[TMP0:%.*]] = sext i16 [[M]] to i64
397; CHECK-NEXT:    [[TMP1:%.*]] = sext i16 [[N]] to i64
398; CHECK-NEXT:    [[FLATTEN_TRIPCOUNT:%.*]] = mul i64 [[TMP0]], [[TMP1]]
399; CHECK-NEXT:    br label [[FOR_COND3_PREHEADER_US:%.*]]
400; CHECK:       for.cond3.preheader.us:
401; CHECK-NEXT:    [[INDVAR2:%.*]] = phi i64 [ [[INDVAR_NEXT3:%.*]], [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US:%.*]] ], [ 0, [[FOR_COND3_PREHEADER_US_PREHEADER]] ]
402; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[INDVAR2]] to i16
403; CHECK-NEXT:    [[MUL_US:%.*]] = mul i16 [[TMP2]], [[M]]
404; CHECK-NEXT:    [[FLATTEN_TRUNCIV:%.*]] = trunc i64 [[INDVAR2]] to i16
405; CHECK-NEXT:    br label [[FOR_BODY9_US:%.*]]
406; CHECK:       for.body9.us:
407; CHECK-NEXT:    [[INDVAR:%.*]] = phi i64 [ 0, [[FOR_COND3_PREHEADER_US]] ]
408; CHECK-NEXT:    [[TMP3:%.*]] = trunc i64 [[INDVAR]] to i16
409; CHECK-NEXT:    [[ADD_US:%.*]] = add i16 [[TMP3]], [[MUL_US]]
410; CHECK-NEXT:    [[CONV14_US:%.*]] = sext i16 [[FLATTEN_TRUNCIV]] to i32
411; CHECK-NEXT:    [[CALL_US:%.*]] = tail call i32 @use_32(i32 [[CONV14_US]])
412; CHECK-NEXT:    [[CALL15_US:%.*]] = tail call i32 @use_16(i16 [[FLATTEN_TRUNCIV]])
413; CHECK-NEXT:    [[CALL17_US:%.*]] = tail call i32 @use_32(i32 [[CONV14_US]])
414; CHECK-NEXT:    [[CALL18_US:%.*]] = tail call i32 @use_16(i16 [[FLATTEN_TRUNCIV]])
415; CHECK-NEXT:    [[CONV19_US:%.*]] = sext i16 [[FLATTEN_TRUNCIV]] to i64
416; CHECK-NEXT:    [[CALL20_US:%.*]] = tail call i32 @use_64(i64 [[CONV19_US]])
417; CHECK-NEXT:    [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1
418; CHECK-NEXT:    [[CMP6_US:%.*]] = icmp slt i64 [[INDVAR_NEXT]], [[TMP0]]
419; CHECK-NEXT:    br label [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US]]
420; CHECK:       for.cond3.for.cond.cleanup8_crit_edge.us:
421; CHECK-NEXT:    [[INDVAR_NEXT3]] = add i64 [[INDVAR2]], 1
422; CHECK-NEXT:    [[CMP_US:%.*]] = icmp slt i64 [[INDVAR_NEXT3]], [[FLATTEN_TRIPCOUNT]]
423; CHECK-NEXT:    br i1 [[CMP_US]], label [[FOR_COND3_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
424; CHECK:       for.cond3.preheader:
425; CHECK-NEXT:    [[I_039:%.*]] = phi i16 [ [[INC22:%.*]], [[FOR_COND3_PREHEADER]] ], [ 0, [[FOR_COND3_PREHEADER_PREHEADER]] ]
426; CHECK-NEXT:    [[INC22]] = add i16 [[I_039]], 1
427; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[INC22]], [[N]]
428; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_COND3_PREHEADER]], label [[FOR_COND_CLEANUP_LOOPEXIT1:%.*]]
429; CHECK:       for.cond.cleanup.loopexit:
430; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
431; CHECK:       for.cond.cleanup.loopexit1:
432; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
433; CHECK:       for.cond.cleanup:
434; CHECK-NEXT:    ret void
435;
436; DONTWIDEN-LABEL: @test4(
437; DONTWIDEN-NEXT:  entry:
438; DONTWIDEN-NEXT:    [[CMP38:%.*]] = icmp sgt i16 [[N:%.*]], 0
439; DONTWIDEN-NEXT:    br i1 [[CMP38]], label [[FOR_COND3_PREHEADER_LR_PH:%.*]], label [[FOR_COND_CLEANUP:%.*]]
440; DONTWIDEN:       for.cond3.preheader.lr.ph:
441; DONTWIDEN-NEXT:    [[CMP636:%.*]] = icmp sgt i16 [[M:%.*]], 0
442; DONTWIDEN-NEXT:    br i1 [[CMP636]], label [[FOR_COND3_PREHEADER_US_PREHEADER:%.*]], label [[FOR_COND3_PREHEADER_PREHEADER:%.*]]
443; DONTWIDEN:       for.cond3.preheader.preheader:
444; DONTWIDEN-NEXT:    br label [[FOR_COND3_PREHEADER:%.*]]
445; DONTWIDEN:       for.cond3.preheader.us.preheader:
446; DONTWIDEN-NEXT:    br label [[FOR_COND3_PREHEADER_US:%.*]]
447; DONTWIDEN:       for.cond3.preheader.us:
448; DONTWIDEN-NEXT:    [[I_039_US:%.*]] = phi i16 [ [[INC22_US:%.*]], [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US:%.*]] ], [ 0, [[FOR_COND3_PREHEADER_US_PREHEADER]] ]
449; DONTWIDEN-NEXT:    [[MUL_US:%.*]] = mul i16 [[I_039_US]], [[M]]
450; DONTWIDEN-NEXT:    br label [[FOR_BODY9_US:%.*]]
451; DONTWIDEN:       for.body9.us:
452; DONTWIDEN-NEXT:    [[J_037_US:%.*]] = phi i16 [ 0, [[FOR_COND3_PREHEADER_US]] ], [ [[INC_US:%.*]], [[FOR_BODY9_US]] ]
453; DONTWIDEN-NEXT:    [[ADD_US:%.*]] = add i16 [[J_037_US]], [[MUL_US]]
454; DONTWIDEN-NEXT:    [[CONV14_US:%.*]] = sext i16 [[ADD_US]] to i32
455; DONTWIDEN-NEXT:    [[CALL_US:%.*]] = tail call i32 @use_32(i32 [[CONV14_US]])
456; DONTWIDEN-NEXT:    [[CALL15_US:%.*]] = tail call i32 @use_16(i16 [[ADD_US]])
457; DONTWIDEN-NEXT:    [[CALL17_US:%.*]] = tail call i32 @use_32(i32 [[CONV14_US]])
458; DONTWIDEN-NEXT:    [[CALL18_US:%.*]] = tail call i32 @use_16(i16 [[ADD_US]])
459; DONTWIDEN-NEXT:    [[CONV19_US:%.*]] = sext i16 [[ADD_US]] to i64
460; DONTWIDEN-NEXT:    [[CALL20_US:%.*]] = tail call i32 @use_64(i64 [[CONV19_US]])
461; DONTWIDEN-NEXT:    [[INC_US]] = add nuw nsw i16 [[J_037_US]], 1
462; DONTWIDEN-NEXT:    [[CMP6_US:%.*]] = icmp slt i16 [[INC_US]], [[M]]
463; DONTWIDEN-NEXT:    br i1 [[CMP6_US]], label [[FOR_BODY9_US]], label [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US]]
464; DONTWIDEN:       for.cond3.for.cond.cleanup8_crit_edge.us:
465; DONTWIDEN-NEXT:    [[INC22_US]] = add i16 [[I_039_US]], 1
466; DONTWIDEN-NEXT:    [[CMP_US:%.*]] = icmp slt i16 [[INC22_US]], [[N]]
467; DONTWIDEN-NEXT:    br i1 [[CMP_US]], label [[FOR_COND3_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
468; DONTWIDEN:       for.cond3.preheader:
469; DONTWIDEN-NEXT:    [[I_039:%.*]] = phi i16 [ [[INC22:%.*]], [[FOR_COND3_PREHEADER]] ], [ 0, [[FOR_COND3_PREHEADER_PREHEADER]] ]
470; DONTWIDEN-NEXT:    [[INC22]] = add i16 [[I_039]], 1
471; DONTWIDEN-NEXT:    [[CMP:%.*]] = icmp slt i16 [[INC22]], [[N]]
472; DONTWIDEN-NEXT:    br i1 [[CMP]], label [[FOR_COND3_PREHEADER]], label [[FOR_COND_CLEANUP_LOOPEXIT1:%.*]]
473; DONTWIDEN:       for.cond.cleanup.loopexit:
474; DONTWIDEN-NEXT:    br label [[FOR_COND_CLEANUP]]
475; DONTWIDEN:       for.cond.cleanup.loopexit1:
476; DONTWIDEN-NEXT:    br label [[FOR_COND_CLEANUP]]
477; DONTWIDEN:       for.cond.cleanup:
478; DONTWIDEN-NEXT:    ret void
479;
480entry:
481  %cmp38 = icmp sgt i16 %n, 0
482  br i1 %cmp38, label %for.cond3.preheader.lr.ph, label %for.cond.cleanup
483
484for.cond3.preheader.lr.ph:
485  %cmp636 = icmp sgt i16 %m, 0
486  br i1 %cmp636, label %for.cond3.preheader.us.preheader, label %for.cond3.preheader.preheader
487
488for.cond3.preheader.preheader:
489  br label %for.cond3.preheader
490
491for.cond3.preheader.us.preheader:
492  br label %for.cond3.preheader.us
493
494for.cond3.preheader.us:
495  %i.039.us = phi i16 [ %inc22.us, %for.cond3.for.cond.cleanup8_crit_edge.us ], [ 0, %for.cond3.preheader.us.preheader ]
496  %mul.us = mul i16 %i.039.us, %m
497  br label %for.body9.us
498
499for.body9.us:
500  %j.037.us = phi i16 [ 0, %for.cond3.preheader.us ], [ %inc.us, %for.body9.us ]
501  %add.us = add i16 %j.037.us, %mul.us
502  %conv14.us = sext i16 %add.us to i32
503  %call.us = tail call i32 @use_32(i32 %conv14.us) #2
504  %call15.us = tail call i32 @use_16(i16 %add.us) #2
505  %call17.us = tail call i32 @use_32(i32 %conv14.us) #2
506  %call18.us = tail call i32 @use_16(i16 %add.us) #2
507  %conv19.us = sext i16 %add.us to i64
508  %call20.us = tail call i32 @use_64(i64 %conv19.us) #2
509  %inc.us = add nuw nsw i16 %j.037.us, 1
510  %cmp6.us = icmp slt i16 %inc.us, %m
511  br i1 %cmp6.us, label %for.body9.us, label %for.cond3.for.cond.cleanup8_crit_edge.us
512
513for.cond3.for.cond.cleanup8_crit_edge.us:
514  %inc22.us = add i16 %i.039.us, 1
515  %cmp.us = icmp slt i16 %inc22.us, %n
516  br i1 %cmp.us, label %for.cond3.preheader.us, label %for.cond.cleanup
517
518for.cond3.preheader:
519  %i.039 = phi i16 [ %inc22, %for.cond3.preheader ], [ 0, %for.cond3.preheader.preheader ]
520  %inc22 = add i16 %i.039, 1
521  %cmp = icmp slt i16 %inc22, %n
522  br i1 %cmp, label %for.cond3.preheader, label %for.cond.cleanup
523
524for.cond.cleanup:
525  ret void
526}
527
528declare dso_local i32 @use_32(i32)
529declare dso_local i32 @use_16(i16)
530declare dso_local i32 @use_64(i64)
531
532declare dso_local void @f(i32* %0) local_unnamed_addr #1
533