1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -indvars -S | FileCheck %s
3
4define void @test1() nounwind {
5; CHECK-LABEL: @test1(
6; CHECK-NEXT:  entry:
7; CHECK-NEXT:    br label [[BB:%.*]]
8; CHECK:       bb:
9; CHECK-NEXT:    [[IV_INT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[DOTINT:%.*]], [[BB]] ]
10; CHECK-NEXT:    [[INDVAR_CONV:%.*]] = sitofp i32 [[IV_INT]] to double
11; CHECK-NEXT:    [[TMP0:%.*]] = tail call i32 @foo(double [[INDVAR_CONV]]) #[[ATTR0:[0-9]+]]
12; CHECK-NEXT:    [[DOTINT]] = add nuw nsw i32 [[IV_INT]], 1
13; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[DOTINT]], 10000
14; CHECK-NEXT:    br i1 [[TMP1]], label [[BB]], label [[RETURN:%.*]]
15; CHECK:       return:
16; CHECK-NEXT:    ret void
17;
18entry:
19  br label %bb
20
21bb:		; preds = %bb, %entry
22  %iv = phi double [ 0.000000e+00, %entry ], [ %1, %bb ]
23  %0 = tail call i32 @foo(double %iv) nounwind
24  %1 = fadd double %iv, 1.000000e+00
25  %2 = fcmp olt double %1, 1.000000e+04
26  br i1 %2, label %bb, label %return
27
28return:		; preds = %bb
29  ret void
30}
31
32declare i32 @foo(double)
33
34define void @test2() nounwind {
35; CHECK-LABEL: @test2(
36; CHECK-NEXT:  entry:
37; CHECK-NEXT:    br label [[BB:%.*]]
38; CHECK:       bb:
39; CHECK-NEXT:    [[IV_INT:%.*]] = phi i32 [ -10, [[ENTRY:%.*]] ], [ [[DOTINT:%.*]], [[BB]] ]
40; CHECK-NEXT:    [[INDVAR_CONV:%.*]] = sitofp i32 [[IV_INT]] to double
41; CHECK-NEXT:    [[TMP0:%.*]] = tail call i32 @foo(double [[INDVAR_CONV]]) #[[ATTR0]]
42; CHECK-NEXT:    [[DOTINT]] = add nsw i32 [[IV_INT]], 2
43; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[DOTINT]], -1
44; CHECK-NEXT:    br i1 [[TMP1]], label [[BB]], label [[RETURN:%.*]]
45; CHECK:       return:
46; CHECK-NEXT:    ret void
47;
48entry:
49  br label %bb
50
51bb:		; preds = %bb, %entry
52  %iv = phi double [ -10.000000e+00, %entry ], [ %1, %bb ]
53  %0 = tail call i32 @foo(double %iv) nounwind
54  %1 = fadd double %iv, 2.000000e+00
55  %2 = fcmp olt double %1, -1.000000e+00
56  br i1 %2, label %bb, label %return
57
58return:		; preds = %bb
59  ret void
60}
61
62
63define void @test3() nounwind {
64; CHECK-LABEL: @test3(
65; CHECK-NEXT:  entry:
66; CHECK-NEXT:    br label [[BB:%.*]]
67; CHECK:       bb:
68; CHECK-NEXT:    [[TMP0:%.*]] = tail call i32 @foo(double 0.000000e+00) #[[ATTR0]]
69; CHECK-NEXT:    br i1 false, label [[BB]], label [[RETURN:%.*]]
70; CHECK:       return:
71; CHECK-NEXT:    ret void
72;
73entry:
74  br label %bb
75
76bb:		; preds = %bb, %entry
77  %iv = phi double [ 0.000000e+00, %entry ], [ %1, %bb ]
78  %0 = tail call i32 @foo(double %iv) nounwind
79  %1 = fadd double %iv, 1.000000e+00
80  %2 = fcmp olt double %1, -1.000000e+00
81  br i1 %2, label %bb, label %return
82
83return:
84  ret void
85}
86
87define void @test4() nounwind {
88; CHECK-LABEL: @test4(
89; CHECK-NEXT:  entry:
90; CHECK-NEXT:    br label [[BB:%.*]]
91; CHECK:       bb:
92; CHECK-NEXT:    [[IV_INT:%.*]] = phi i32 [ 40, [[ENTRY:%.*]] ], [ [[DOTINT:%.*]], [[BB]] ]
93; CHECK-NEXT:    [[INDVAR_CONV:%.*]] = sitofp i32 [[IV_INT]] to double
94; CHECK-NEXT:    [[TMP0:%.*]] = tail call i32 @foo(double [[INDVAR_CONV]]) #[[ATTR0]]
95; CHECK-NEXT:    [[DOTINT]] = add nsw i32 [[IV_INT]], -1
96; CHECK-NEXT:    br i1 false, label [[BB]], label [[RETURN:%.*]]
97; CHECK:       return:
98; CHECK-NEXT:    ret void
99;
100entry:
101  br label %bb
102
103bb:		; preds = %bb, %entry
104  %iv = phi double [ 40.000000e+00, %entry ], [ %1, %bb ]
105  %0 = tail call i32 @foo(double %iv) nounwind
106  %1 = fadd double %iv, -1.000000e+00
107  %2 = fcmp olt double %1, 1.000000e+00
108  br i1 %2, label %bb, label %return
109
110return:
111  ret void
112}
113
114; PR6761
115define void @test5() nounwind {
116; <label>:0
117; CHECK-LABEL: @test5(
118; CHECK-NEXT:    br label [[TMP1:%.*]]
119; CHECK:       1:
120; CHECK-NEXT:    [[DOTINT:%.*]] = phi i32 [ 9, [[TMP0:%.*]] ], [ [[DOTINT1:%.*]], [[TMP1]] ]
121; CHECK-NEXT:    [[TMP2:%.*]] = tail call i32 @foo(double 0.000000e+00)
122; CHECK-NEXT:    [[DOTINT1]] = add nsw i32 [[DOTINT]], -1
123; CHECK-NEXT:    [[TMP3:%.*]] = icmp slt i32 [[DOTINT1]], 0
124; CHECK-NEXT:    br i1 [[TMP3]], label [[EXIT:%.*]], label [[TMP1]]
125; CHECK:       exit:
126; CHECK-NEXT:    ret void
127;
128  br label %1
129
130; <label>:1
131  %2 = phi double [ 9.000000e+00, %0 ], [ %4, %1 ]
132  %3 = tail call i32 @foo(double 0.0)
133  %4 = fadd double %2, -1.000000e+00
134  %5 = fcmp ult double %4, 0.000000e+00
135  br i1 %5, label %exit, label %1
136
137exit:
138  ret void
139}
140
141define double @test_max_be() {
142; CHECK-LABEL: @test_max_be(
143; CHECK-NEXT:  bb4:
144; CHECK-NEXT:    br label [[BB8:%.*]]
145; CHECK:       bb8:
146; CHECK-NEXT:    [[TMP10:%.*]] = phi double [ 0.000000e+00, [[BB4:%.*]] ], [ [[TMP12:%.*]], [[BB22:%.*]] ]
147; CHECK-NEXT:    [[TMP11_INT:%.*]] = phi i32 [ 0, [[BB4]] ], [ [[TMP13_INT:%.*]], [[BB22]] ]
148; CHECK-NEXT:    [[INDVAR_CONV:%.*]] = sitofp i32 [[TMP11_INT]] to double
149; CHECK-NEXT:    [[TMP12]] = fadd double [[TMP10]], [[INDVAR_CONV]]
150; CHECK-NEXT:    [[TMP13_INT]] = add nuw nsw i32 [[TMP11_INT]], 1
151; CHECK-NEXT:    [[TMP14:%.*]] = icmp ult i32 [[TMP13_INT]], 99999
152; CHECK-NEXT:    br i1 [[TMP14]], label [[BB22]], label [[BB6:%.*]]
153; CHECK:       bb22:
154; CHECK-NEXT:    br i1 true, label [[BB8]], label [[BB6]]
155; CHECK:       bb6:
156; CHECK-NEXT:    [[TMP12_LCSSA:%.*]] = phi double [ [[TMP12]], [[BB22]] ], [ [[TMP12]], [[BB8]] ]
157; CHECK-NEXT:    ret double [[TMP12_LCSSA]]
158;
159bb4:
160  br label %bb8
161
162bb8:
163  %tmp9 = phi i64 [ 1, %bb4 ], [ %tmp23, %bb22 ]
164  %tmp10 = phi double [ 0.000000e+00, %bb4 ], [ %tmp12, %bb22 ]
165  %tmp11 = phi double [ 0.000000e+00, %bb4 ], [ %tmp13, %bb22 ]
166  %tmp12 = fadd double %tmp10, %tmp11
167  %tmp13 = fadd double %tmp11, 1.000000e+00
168  %tmp14 = fcmp olt double %tmp13, 9.999900e+04
169  br i1 %tmp14, label %bb22, label %bb6
170
171bb22:
172  %tmp23 = add nuw nsw i64 %tmp9, 1
173  %tmp24 = icmp ult i64 %tmp9, 1048576
174  br i1 %tmp24, label %bb8, label %bb6
175
176bb6:
177  ret double %tmp12
178}
179
180define float @test_max_be2() {
181; CHECK-LABEL: @test_max_be2(
182; CHECK-NEXT:  bb4:
183; CHECK-NEXT:    br label [[BB8:%.*]]
184; CHECK:       bb8:
185; CHECK-NEXT:    [[TMP10:%.*]] = phi float [ 0.000000e+00, [[BB4:%.*]] ], [ [[TMP12:%.*]], [[BB22:%.*]] ]
186; CHECK-NEXT:    [[TMP11_INT:%.*]] = phi i32 [ 0, [[BB4]] ], [ [[TMP13_INT:%.*]], [[BB22]] ]
187; CHECK-NEXT:    [[INDVAR_CONV:%.*]] = sitofp i32 [[TMP11_INT]] to float
188; CHECK-NEXT:    [[TMP12]] = fadd float [[TMP10]], [[INDVAR_CONV]]
189; CHECK-NEXT:    [[TMP13_INT]] = add nuw nsw i32 [[TMP11_INT]], 1
190; CHECK-NEXT:    [[TMP14:%.*]] = icmp ult i32 [[TMP13_INT]], 99999
191; CHECK-NEXT:    br i1 [[TMP14]], label [[BB22]], label [[BB6:%.*]]
192; CHECK:       bb22:
193; CHECK-NEXT:    br i1 true, label [[BB8]], label [[BB6]]
194; CHECK:       bb6:
195; CHECK-NEXT:    [[TMP12_LCSSA:%.*]] = phi float [ [[TMP12]], [[BB22]] ], [ [[TMP12]], [[BB8]] ]
196; CHECK-NEXT:    ret float [[TMP12_LCSSA]]
197;
198bb4:
199  br label %bb8
200
201bb8:
202  %tmp9 = phi i64 [ 1, %bb4 ], [ %tmp23, %bb22 ]
203  %tmp10 = phi float [ 0.000000e+00, %bb4 ], [ %tmp12, %bb22 ]
204  %tmp11 = phi float [ 0.000000e+00, %bb4 ], [ %tmp13, %bb22 ]
205  %tmp12 = fadd float %tmp10, %tmp11
206  %tmp13 = fadd float %tmp11, 1.000000e+00
207  %tmp14 = fcmp olt float %tmp13, 9.999900e+04
208  br i1 %tmp14, label %bb22, label %bb6
209
210bb22:
211  %tmp23 = add nuw nsw i64 %tmp9, 1
212  %tmp24 = icmp ult i64 %tmp9, 1048576
213  br i1 %tmp24, label %bb8, label %bb6
214
215bb6:
216  ret float %tmp12
217}
218
219; Bounds check
220define float @test_max_be3() {
221; CHECK-LABEL: @test_max_be3(
222; CHECK-NEXT:  bb4:
223; CHECK-NEXT:    br label [[BB8:%.*]]
224; CHECK:       bb8:
225; CHECK-NEXT:    [[TMP10:%.*]] = phi float [ 0.000000e+00, [[BB4:%.*]] ], [ [[TMP12:%.*]], [[BB22:%.*]] ]
226; CHECK-NEXT:    [[TMP11_INT:%.*]] = phi i32 [ 0, [[BB4]] ], [ [[TMP13_INT:%.*]], [[BB22]] ]
227; CHECK-NEXT:    [[INDVAR_CONV:%.*]] = sitofp i32 [[TMP11_INT]] to float
228; CHECK-NEXT:    [[TMP12]] = fadd float [[TMP10]], [[INDVAR_CONV]]
229; CHECK-NEXT:    [[TMP13_INT]] = add nuw nsw i32 [[TMP11_INT]], 1
230; CHECK-NEXT:    [[TMP14:%.*]] = icmp ult i32 [[TMP13_INT]], 99999
231; CHECK-NEXT:    br i1 [[TMP14]], label [[BB22]], label [[BB6:%.*]]
232; CHECK:       bb22:
233; CHECK-NEXT:    br i1 true, label [[BB8]], label [[BB6]]
234; CHECK:       bb6:
235; CHECK-NEXT:    [[TMP12_LCSSA:%.*]] = phi float [ [[TMP12]], [[BB22]] ], [ [[TMP12]], [[BB8]] ]
236; CHECK-NEXT:    ret float [[TMP12_LCSSA]]
237;
238bb4:
239  br label %bb8
240
241bb8:
242  %tmp9 = phi i64 [ 1, %bb4 ], [ %tmp23, %bb22 ]
243  %tmp10 = phi float [ 0.000000e+00, %bb4 ], [ %tmp12, %bb22 ]
244  %tmp11 = phi float [ 0.000000e+00, %bb4 ], [ %tmp13, %bb22 ]
245  %tmp12 = fadd float %tmp10, %tmp11
246  %tmp13 = fadd float %tmp11, 1.000000e+00
247  %tmp14 = fcmp olt float %tmp13, 9.999900e+04
248  br i1 %tmp14, label %bb22, label %bb6
249
250bb22:
251  %tmp23 = add nuw nsw i64 %tmp9, 1
252  ;; 2^23 = 16777215
253  %tmp24 = icmp ult i64 %tmp9, 16777215
254  br i1 %tmp24, label %bb8, label %bb6
255
256bb6:
257  ret float %tmp12
258}
259
260
261; Show that given a computeable exit count, we can remove an
262; fcmp of a casted integer IV. (TODO)
263define void @fcmp1() nounwind {
264; CHECK-LABEL: @fcmp1(
265; CHECK-NEXT:  entry:
266; CHECK-NEXT:    br label [[BB:%.*]]
267; CHECK:       bb:
268; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
269; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i64 [[IV]], 20000
270; CHECK-NEXT:    br i1 [[CMP1]], label [[BACKEDGE]], label [[RETURN:%.*]]
271; CHECK:       backedge:
272; CHECK-NEXT:    [[IV_FP:%.*]] = sitofp i64 [[IV]] to double
273; CHECK-NEXT:    [[TMP0:%.*]] = tail call i32 @foo(double [[IV_FP]]) #[[ATTR0]]
274; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
275; CHECK-NEXT:    [[CMP2:%.*]] = fcmp olt double [[IV_FP]], 1.000000e+04
276; CHECK-NEXT:    br i1 [[CMP2]], label [[BB]], label [[RETURN]]
277; CHECK:       return:
278; CHECK-NEXT:    ret void
279;
280entry:
281  br label %bb
282
283bb:		; preds = %bb, %entry
284  %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
285  %cmp1 = icmp slt i64 %iv, 20000
286  br i1 %cmp1, label %backedge, label %return
287
288backedge:
289  %iv.fp = sitofp i64 %iv to double
290  tail call i32 @foo(double %iv.fp) nounwind
291  %iv.next = add nsw nuw i64 %iv, 1
292  %cmp2 = fcmp olt double %iv.fp, 1.000000e+04
293  br i1 %cmp2, label %bb, label %return
294
295return:		; preds = %bb
296  ret void
297}
298
299define void @fcmp2() nounwind {
300; CHECK-LABEL: @fcmp2(
301; CHECK-NEXT:  entry:
302; CHECK-NEXT:    br label [[BB:%.*]]
303; CHECK:       bb:
304; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
305; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i64 [[IV]], 2000
306; CHECK-NEXT:    br i1 [[CMP1]], label [[BACKEDGE]], label [[RETURN:%.*]]
307; CHECK:       backedge:
308; CHECK-NEXT:    [[IV_FP:%.*]] = sitofp i64 [[IV]] to double
309; CHECK-NEXT:    [[TMP0:%.*]] = tail call i32 @foo(double [[IV_FP]]) #[[ATTR0]]
310; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
311; CHECK-NEXT:    [[CMP2:%.*]] = fcmp olt double [[IV_FP]], 1.000000e+04
312; CHECK-NEXT:    br i1 [[CMP2]], label [[BB]], label [[RETURN]]
313; CHECK:       return:
314; CHECK-NEXT:    ret void
315;
316entry:
317  br label %bb
318
319bb:		; preds = %bb, %entry
320  %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
321  %cmp1 = icmp slt i64 %iv, 2000
322  br i1 %cmp1, label %backedge, label %return
323
324backedge:
325  %iv.fp = sitofp i64 %iv to double
326  tail call i32 @foo(double %iv.fp) nounwind
327  %iv.next = add nsw nuw i64 %iv, 1
328  %cmp2 = fcmp olt double %iv.fp, 1.000000e+04
329  br i1 %cmp2, label %bb, label %return
330
331return:		; preds = %bb
332  ret void
333}
334
335define void @fcmp_neg1() nounwind {
336; CHECK-LABEL: @fcmp_neg1(
337; CHECK-NEXT:  entry:
338; CHECK-NEXT:    br label [[BB:%.*]]
339; CHECK:       bb:
340; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
341; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i64 [[IV]], -20
342; CHECK-NEXT:    br i1 [[CMP1]], label [[BACKEDGE]], label [[RETURN:%.*]]
343; CHECK:       backedge:
344; CHECK-NEXT:    [[IV_FP:%.*]] = sitofp i64 [[IV]] to double
345; CHECK-NEXT:    [[TMP0:%.*]] = tail call i32 @foo(double [[IV_FP]]) #[[ATTR0]]
346; CHECK-NEXT:    [[IV_NEXT]] = add nuw i64 [[IV]], 1
347; CHECK-NEXT:    [[CMP2:%.*]] = fcmp olt double [[IV_FP]], 1.000000e+04
348; CHECK-NEXT:    br i1 [[CMP2]], label [[BB]], label [[RETURN]]
349; CHECK:       return:
350; CHECK-NEXT:    ret void
351;
352entry:
353  br label %bb
354
355bb:		; preds = %bb, %entry
356  %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
357  ;; Range fact outside precise integer region
358  %cmp1 = icmp ult i64 %iv, -20
359  br i1 %cmp1, label %backedge, label %return
360
361backedge:
362  %iv.fp = sitofp i64 %iv to double
363  tail call i32 @foo(double %iv.fp) nounwind
364  %iv.next = add nuw i64 %iv, 1
365  %cmp2 = fcmp olt double %iv.fp, 1.000000e+04
366  br i1 %cmp2, label %bb, label %return
367
368return:		; preds = %bb
369  ret void
370}
371
372declare void @use.i16(i16)
373declare void @use.i32(i32)
374declare void @use.i64(i64)
375declare void @use.float(float)
376
377define void @pr55505_remove_redundant_fptosi_for_float_iv(i32 %index, ptr %dst) {
378; CHECK-LABEL: @pr55505_remove_redundant_fptosi_for_float_iv(
379; CHECK-NEXT:  entry:
380; CHECK-NEXT:    br label [[LOOP:%.*]]
381; CHECK:       loop:
382; CHECK-NEXT:    [[FLOAT_IV_INT:%.*]] = phi i32 [ 1000, [[ENTRY:%.*]] ], [ [[FLOAT_IV_NEXT_INT:%.*]], [[LOOP]] ]
383; CHECK-NEXT:    [[INDVAR_CONV:%.*]] = sitofp i32 [[FLOAT_IV_INT]] to float
384; CHECK-NEXT:    call void @use.float(float [[INDVAR_CONV]])
385; CHECK-NEXT:    call void @use.i32(i32 [[FLOAT_IV_INT]])
386; CHECK-NEXT:    [[CONV_I16:%.*]] = fptosi float [[INDVAR_CONV]] to i16
387; CHECK-NEXT:    [[CONV_I64:%.*]] = fptosi float [[INDVAR_CONV]] to i64
388; CHECK-NEXT:    call void @use.i16(i16 [[CONV_I16]])
389; CHECK-NEXT:    call void @use.i64(i64 [[CONV_I64]])
390; CHECK-NEXT:    [[UCONV_I16:%.*]] = fptoui float [[INDVAR_CONV]] to i16
391; CHECK-NEXT:    [[UCONV_I64:%.*]] = fptoui float [[INDVAR_CONV]] to i64
392; CHECK-NEXT:    call void @use.i16(i16 [[UCONV_I16]])
393; CHECK-NEXT:    call void @use.i64(i64 [[UCONV_I64]])
394; CHECK-NEXT:    [[FLOAT_IV_NEXT_INT]] = add nsw i32 [[FLOAT_IV_INT]], -1
395; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[FLOAT_IV_NEXT_INT]], 0
396; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
397; CHECK:       exit:
398; CHECK-NEXT:    ret void
399;
400entry:
401  br label %loop
402
403loop:
404  %float.iv = phi float [ 1.000000e+03, %entry ], [ %float.iv.next, %loop ]
405  call void @use.float(float %float.iv)
406  %conv.i32 = fptosi float %float.iv to i32
407  call void @use.i32(i32 %conv.i32)
408  %conv.i16 = fptosi float %float.iv to i16
409  %conv.i64 = fptosi float %float.iv to i64
410  call void @use.i16(i16 %conv.i16)
411  call void @use.i64(i64 %conv.i64)
412  %uconv.i16 = fptoui float %float.iv to i16
413  %uconv.i64 = fptoui float %float.iv to i64
414  call void @use.i16(i16 %uconv.i16)
415  call void @use.i64(i64 %uconv.i64)
416  %float.iv.next = fadd float %float.iv, -1.000000e+00
417  %cmp = fcmp ogt float %float.iv.next, 0.000000e+00
418  br i1 %cmp, label %loop, label %exit
419
420exit:
421  ret void
422}
423