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