[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / LoopFlatten / widen-iv.ll
blobabd70138e4c1c12a0dfbba10108b89a9c074a56b
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
5 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
7 ; DONTWIDEN-NOT:   %flatten.tripcount
8 ; DONTWIDEN-NOT:   %flatten.trunciv
10 ; Function Attrs: nounwind
11 define 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
49 entry:
50   %cmp17 = icmp sgt i32 %N, 0
51   br i1 %cmp17, label %for.cond1.preheader.lr.ph, label %for.cond.cleanup
53 for.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
57 for.cond1.preheader.us.preheader:
58   br label %for.cond1.preheader.us
60 for.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
65 for.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
75 for.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
80 for.cond.cleanup:
81   ret void
84 define 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
121 entry:
122   %cmp20.not = icmp eq i32 %N, 0
123   br i1 %cmp20.not, label %for.end9, label %for.cond1.preheader.us.preheader
125 for.cond1.preheader.us.preheader:
126   br label %for.cond1.preheader.us
128 for.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
133 for.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
145 for.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
150 for.end9.loopexit:
151   br label %for.end9
153 for.end9:
154   ret void
157 ; This IR corresponds to this input:
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 ; }
167 define 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
213 entry:
214   %cmp25.not = icmp eq i8 %n, 0
215   br i1 %cmp25.not, label %for.cond.cleanup, label %for.cond3.preheader.lr.ph
217 for.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
221 for.cond3.preheader.preheader:
222   br label %for.cond3.preheader
224 for.cond3.preheader.us.preheader:
225   br label %for.cond3.preheader.us
227 for.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
232 for.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
241 for.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
246 for.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
252 for.cond.cleanup:
253   ret void
256 ; This IR corresponds to this input:
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 ; }
270 define 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
322 entry:
323   %cmp37.not = icmp eq i8 %n, 0
324   br i1 %cmp37.not, label %for.cond.cleanup, label %for.cond3.preheader.lr.ph
326 for.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
330 for.cond3.preheader.preheader:
331   br label %for.cond3.preheader
333 for.cond3.preheader.us.preheader:
334   br label %for.cond3.preheader.us
336 for.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
341 for.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
356 for.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
361 for.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
367 for.cond.cleanup:
368   ret void
371 ; This IR corresponds to this input:
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 ; }
385 define 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
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
480 entry:
481   %cmp38 = icmp sgt i16 %n, 0
482   br i1 %cmp38, label %for.cond3.preheader.lr.ph, label %for.cond.cleanup
484 for.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
488 for.cond3.preheader.preheader:
489   br label %for.cond3.preheader
491 for.cond3.preheader.us.preheader:
492   br label %for.cond3.preheader.us
494 for.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
499 for.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
513 for.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
518 for.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
524 for.cond.cleanup:
525   ret void
528 ; Identify trip count when it is constant and the IV has been widened.
529 define i32 @constTripCount() {
530 ; CHECK-LABEL: @constTripCount(
531 ; CHECK-NEXT:  entry:
532 ; CHECK-NEXT:    [[FLATTEN_TRIPCOUNT:%.*]] = mul i64 20, 20
533 ; CHECK-NEXT:    br label [[I_LOOP:%.*]]
534 ; CHECK:       i.loop:
535 ; CHECK-NEXT:    [[INDVAR1:%.*]] = phi i64 [ [[INDVAR_NEXT2:%.*]], [[J_LOOPDONE:%.*]] ], [ 0, [[ENTRY:%.*]] ]
536 ; CHECK-NEXT:    br label [[J_LOOP:%.*]]
537 ; CHECK:       j.loop:
538 ; CHECK-NEXT:    [[INDVAR:%.*]] = phi i64 [ 0, [[I_LOOP]] ]
539 ; CHECK-NEXT:    call void @payload()
540 ; CHECK-NEXT:    [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1
541 ; CHECK-NEXT:    [[J_ATEND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], 20
542 ; CHECK-NEXT:    br label [[J_LOOPDONE]]
543 ; CHECK:       j.loopdone:
544 ; CHECK-NEXT:    [[INDVAR_NEXT2]] = add i64 [[INDVAR1]], 1
545 ; CHECK-NEXT:    [[I_ATEND:%.*]] = icmp eq i64 [[INDVAR_NEXT2]], [[FLATTEN_TRIPCOUNT]]
546 ; CHECK-NEXT:    br i1 [[I_ATEND]], label [[I_LOOPDONE:%.*]], label [[I_LOOP]]
547 ; CHECK:       i.loopdone:
548 ; CHECK-NEXT:    ret i32 0
550 entry:
551   br label %i.loop
553 i.loop:
554   %i = phi i8 [ 0, %entry ], [ %i.inc, %j.loopdone ]
555   br label %j.loop
557 j.loop:
558   %j = phi i8 [ 0, %i.loop ], [ %j.inc, %j.loop ]
559   call void @payload()
560   %j.inc = add i8 %j, 1
561   %j.atend = icmp eq i8 %j.inc, 20
562   br i1 %j.atend, label %j.loopdone, label %j.loop
564 j.loopdone:
565   %i.inc = add i8 %i, 1
566   %i.atend = icmp eq i8 %i.inc, 20
567   br i1 %i.atend, label %i.loopdone, label %i.loop
569 i.loopdone:
570   ret i32 0
573 declare void @payload()
574 declare dso_local i32 @use_32(i32)
575 declare dso_local i32 @use_16(i16)
576 declare dso_local i32 @use_64(i64)
578 declare dso_local void @f(i32* %0) local_unnamed_addr #1