indvars: fixed IV cloning in -disable-iv-rewrite mode with associated
[oota-llvm.git] / test / Transforms / IndVarSimplify / elim-extend.ll
1 ; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s
2
3 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
4
5 ; Tests sign extend elimination in the inner and outer loop.
6 ; %outercount is straightforward to widen, besides being in an outer loop.
7 ; %innercount is currently blocked by lcssa, so is not widened.
8 ; %inneriv can be widened only after proving it has no signed-overflow
9 ;   based on the loop test.
10 define void @nestedIV(i8* %address, i32 %limit) nounwind {
11 entry:
12   %limitdec = add i32 %limit, -1
13   br label %outerloop
14
15 ; CHECK: outerloop:
16 ;
17 ; Eliminate %ofs1 after widening outercount.
18 ; CHECK-NOT: sext
19 ; CHECK: getelementptr
20 ;
21 ; IV rewriting hoists a gep into this block. We don't like that.
22 ; CHECK-NOT: getelementptr
23 outerloop:
24   %outercount   = phi i32 [ %outerpostcount, %outermerge ], [ 0, %entry ]
25   %innercount = phi i32 [ %innercount.merge, %outermerge ], [ 0, %entry ]
26
27   %outercountdec = add i32 %outercount, -1
28   %ofs1 = sext i32 %outercountdec to i64
29   %adr1 = getelementptr i8* %address, i64 %ofs1
30   store i8 0, i8* %adr1
31
32   br label %innerpreheader
33
34 innerpreheader:
35   %innerprecmp = icmp sgt i32 %limitdec, %innercount
36   br i1 %innerprecmp, label %innerloop, label %outermerge
37
38 ; CHECK: innerloop:
39 ;
40 ; Eliminate %ofs2 after widening inneriv.
41 ; CHECK-NOT: sext
42 ; CHECK: getelementptr
43 ;
44 ; FIXME: We should not increase the number of IVs in this loop.
45 ; sext elimination plus LFTR results in 3 final IVs.
46 ;
47 ; FIXME: eliminate %ofs3 based the loop pre/post conditions
48 ; even though innerpostiv is not NSW, thus sign extending innerpostiv
49 ; does not yield the same expression as incrementing the widened inneriv.
50 innerloop:
51   %inneriv = phi i32 [ %innerpostiv, %innerloop ], [ %innercount, %innerpreheader ]
52   %innerpostiv = add i32 %inneriv, 1
53
54   %ofs2 = sext i32 %inneriv to i64
55   %adr2 = getelementptr i8* %address, i64 %ofs2
56   store i8 0, i8* %adr2
57
58   %ofs3 = sext i32 %innerpostiv to i64
59   %adr3 = getelementptr i8* %address, i64 %ofs3
60   store i8 0, i8* %adr3
61
62   %innercmp = icmp sgt i32 %limitdec, %innerpostiv
63   br i1 %innercmp, label %innerloop, label %innerexit
64
65 innerexit:
66   %innercount.lcssa = phi i32 [ %innerpostiv, %innerloop ]
67   br label %outermerge
68
69 ; CHECK: outermerge:
70 ;
71 ; Eliminate %ofs4 after widening outercount
72 ; CHECK-NOT: sext
73 ; CHECK: getelementptr
74 ;
75 ; TODO: Eliminate %ofs5 after removing lcssa
76 outermerge:
77   %innercount.merge = phi i32 [ %innercount.lcssa, %innerexit ], [ %innercount, %innerpreheader ]
78
79   %ofs4 = sext i32 %outercount to i64
80   %adr4 = getelementptr i8* %address, i64 %ofs4
81   store i8 0, i8* %adr3
82
83   %ofs5 = sext i32 %innercount.merge to i64
84   %adr5 = getelementptr i8* %address, i64 %ofs5
85   store i8 0, i8* %adr4
86
87   %outerpostcount = add i32 %outercount, 1
88   %tmp47 = icmp slt i32 %outerpostcount, %limit
89   br i1 %tmp47, label %outerloop, label %return
90
91 return:
92   ret void
93 }