blob: 4b336f03795fbb16a98155e99bdac5ae875575f2 [file] [log] [blame]
Andrew Trick03d3d3b2011-05-25 04:42:22 +00001; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s
2
3target 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
Andrew Trickb1ce4c02011-05-31 21:17:47 +00005; IV with constant start, preinc and postinc sign extends, with and without NSW.
6; IV rewrite only removes one sext. WidenIVs removes all three.
Andrew Trickfcdc9a42011-05-26 00:46:11 +00007define void @postincConstIV(i8* %base, i32 %limit) nounwind {
8entry:
9 br label %loop
10; CHECK: loop:
11; CHECK-NOT: sext
12; CHECK: exit:
13loop:
14 %iv = phi i32 [ %postiv, %loop ], [ 0, %entry ]
15 %ivnsw = phi i32 [ %postivnsw, %loop ], [ 0, %entry ]
16 %preofs = sext i32 %iv to i64
17 %preadr = getelementptr i8* %base, i64 %preofs
18 store i8 0, i8* %preadr
19 %postiv = add i32 %iv, 1
20 %postofs = sext i32 %postiv to i64
21 %postadr = getelementptr i8* %base, i64 %postofs
22 store i8 0, i8* %postadr
23 %postivnsw = add nsw i32 %ivnsw, 1
24 %postofsnsw = sext i32 %postivnsw to i64
25 %postadrnsw = getelementptr i8* %base, i64 %postofsnsw
26 store i8 0, i8* %postadrnsw
27 %cond = icmp sgt i32 %limit, %iv
28 br i1 %cond, label %loop, label %exit
29exit:
30 br label %return
31return:
32 ret void
33}
34
Andrew Trickb1ce4c02011-05-31 21:17:47 +000035; IV with nonconstant start, preinc and postinc sign extends,
Andrew Trickfcdc9a42011-05-26 00:46:11 +000036; with and without NSW.
Andrew Trickb1ce4c02011-05-31 21:17:47 +000037; As with postincConstIV, WidenIVs removes all three sexts.
Andrew Trickfcdc9a42011-05-26 00:46:11 +000038define void @postincVarIV(i8* %base, i32 %init, i32 %limit) nounwind {
39entry:
Andrew Trickb1ce4c02011-05-31 21:17:47 +000040 %precond = icmp sgt i32 %limit, %init
41 br i1 %precond, label %loop, label %return
Andrew Trickfcdc9a42011-05-26 00:46:11 +000042; CHECK: loop:
Andrew Trickfcdc9a42011-05-26 00:46:11 +000043; CHECK-NOT: sext
44; CHECK: exit:
45loop:
46 %iv = phi i32 [ %postiv, %loop ], [ %init, %entry ]
Andrew Trickb1ce4c02011-05-31 21:17:47 +000047 %ivnsw = phi i32 [ %postivnsw, %loop ], [ %init, %entry ]
Andrew Trickfcdc9a42011-05-26 00:46:11 +000048 %preofs = sext i32 %iv to i64
49 %preadr = getelementptr i8* %base, i64 %preofs
50 store i8 0, i8* %preadr
51 %postiv = add i32 %iv, 1
52 %postofs = sext i32 %postiv to i64
53 %postadr = getelementptr i8* %base, i64 %postofs
54 store i8 0, i8* %postadr
55 %postivnsw = add nsw i32 %ivnsw, 1
56 %postofsnsw = sext i32 %postivnsw to i64
57 %postadrnsw = getelementptr i8* %base, i64 %postofsnsw
58 store i8 0, i8* %postadrnsw
Andrew Trickb1ce4c02011-05-31 21:17:47 +000059 %cond = icmp sgt i32 %limit, %postiv
Andrew Trickfcdc9a42011-05-26 00:46:11 +000060 br i1 %cond, label %loop, label %exit
61exit:
62 br label %return
63return:
64 ret void
65}
66
67; Test sign extend elimination in the inner and outer loop.
Andrew Trick03d3d3b2011-05-25 04:42:22 +000068; %outercount is straightforward to widen, besides being in an outer loop.
69; %innercount is currently blocked by lcssa, so is not widened.
70; %inneriv can be widened only after proving it has no signed-overflow
71; based on the loop test.
72define void @nestedIV(i8* %address, i32 %limit) nounwind {
73entry:
74 %limitdec = add i32 %limit, -1
75 br label %outerloop
76
77; CHECK: outerloop:
78;
79; Eliminate %ofs1 after widening outercount.
80; CHECK-NOT: sext
81; CHECK: getelementptr
82;
83; IV rewriting hoists a gep into this block. We don't like that.
84; CHECK-NOT: getelementptr
85outerloop:
86 %outercount = phi i32 [ %outerpostcount, %outermerge ], [ 0, %entry ]
87 %innercount = phi i32 [ %innercount.merge, %outermerge ], [ 0, %entry ]
88
89 %outercountdec = add i32 %outercount, -1
90 %ofs1 = sext i32 %outercountdec to i64
91 %adr1 = getelementptr i8* %address, i64 %ofs1
92 store i8 0, i8* %adr1
93
94 br label %innerpreheader
95
96innerpreheader:
97 %innerprecmp = icmp sgt i32 %limitdec, %innercount
98 br i1 %innerprecmp, label %innerloop, label %outermerge
99
100; CHECK: innerloop:
101;
102; Eliminate %ofs2 after widening inneriv.
Andrew Trickb1ce4c02011-05-31 21:17:47 +0000103; Eliminate %ofs3 after normalizing sext(innerpostiv)
Andrew Trick03d3d3b2011-05-25 04:42:22 +0000104; CHECK-NOT: sext
105; CHECK: getelementptr
106;
Andrew Trickb1ce4c02011-05-31 21:17:47 +0000107; FIXME: We should check that indvars does not increase the number of
108; IVs in this loop. sext elimination plus LFTR currently results in 2 final
109; IVs. Waiting to remove LFTR.
Andrew Trick03d3d3b2011-05-25 04:42:22 +0000110innerloop:
111 %inneriv = phi i32 [ %innerpostiv, %innerloop ], [ %innercount, %innerpreheader ]
112 %innerpostiv = add i32 %inneriv, 1
113
114 %ofs2 = sext i32 %inneriv to i64
115 %adr2 = getelementptr i8* %address, i64 %ofs2
116 store i8 0, i8* %adr2
117
118 %ofs3 = sext i32 %innerpostiv to i64
119 %adr3 = getelementptr i8* %address, i64 %ofs3
120 store i8 0, i8* %adr3
121
122 %innercmp = icmp sgt i32 %limitdec, %innerpostiv
123 br i1 %innercmp, label %innerloop, label %innerexit
124
125innerexit:
126 %innercount.lcssa = phi i32 [ %innerpostiv, %innerloop ]
127 br label %outermerge
128
129; CHECK: outermerge:
130;
131; Eliminate %ofs4 after widening outercount
132; CHECK-NOT: sext
133; CHECK: getelementptr
134;
135; TODO: Eliminate %ofs5 after removing lcssa
136outermerge:
137 %innercount.merge = phi i32 [ %innercount.lcssa, %innerexit ], [ %innercount, %innerpreheader ]
138
139 %ofs4 = sext i32 %outercount to i64
140 %adr4 = getelementptr i8* %address, i64 %ofs4
141 store i8 0, i8* %adr3
142
143 %ofs5 = sext i32 %innercount.merge to i64
144 %adr5 = getelementptr i8* %address, i64 %ofs5
145 store i8 0, i8* %adr4
146
147 %outerpostcount = add i32 %outercount, 1
148 %tmp47 = icmp slt i32 %outerpostcount, %limit
149 br i1 %tmp47, label %outerloop, label %return
150
151return:
152 ret void
153}