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