• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt < %s -indvars -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
5; IV with constant start, preinc and postinc sign extends, with and without NSW.
6; IV rewrite only removes one sext. WidenIVs removes all three.
7define 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, 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, 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 inbounds i8, 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
35; IV with nonconstant start, preinc and postinc sign extends,
36; with and without NSW.
37; As with postincConstIV, WidenIVs removes all three sexts.
38define void @postincVarIV(i8* %base, i32 %init, i32 %limit) nounwind {
39entry:
40  %precond = icmp sgt i32 %limit, %init
41  br i1 %precond, label %loop, label %return
42; CHECK: loop:
43; CHECK-NOT: sext
44; CHECK: wide.trip.count = sext
45; CHECK-NOT: sext
46; CHECK: exit:
47loop:
48  %iv = phi i32 [ %postiv, %loop ], [ %init, %entry ]
49  %ivnsw = phi i32 [ %postivnsw, %loop ], [ %init, %entry ]
50  %preofs = sext i32 %iv to i64
51  %preadr = getelementptr i8, i8* %base, i64 %preofs
52  store i8 0, i8* %preadr
53  %postiv = add i32 %iv, 1
54  %postofs = sext i32 %postiv to i64
55  %postadr = getelementptr i8, i8* %base, i64 %postofs
56  store i8 0, i8* %postadr
57  %postivnsw = add nsw i32 %ivnsw, 1
58  %postofsnsw = sext i32 %postivnsw to i64
59  %postadrnsw = getelementptr i8, i8* %base, i64 %postofsnsw
60  store i8 0, i8* %postadrnsw
61  %cond = icmp sgt i32 %limit, %postiv
62  br i1 %cond, label %loop, label %exit
63exit:
64  br label %return
65return:
66  ret void
67}
68
69; Test sign extend elimination in the inner and outer loop.
70; %outercount is straightforward to widen, besides being in an outer loop.
71; %innercount is currently blocked by lcssa, so is not widened.
72; %inneriv can be widened only after proving it has no signed-overflow
73;   based on the loop test.
74define void @nestedIV(i8* %address, i32 %limit) nounwind {
75entry:
76  %limitdec = add i32 %limit, -1
77  br label %outerloop
78
79; CHECK: outerloop:
80;
81; Eliminate %ofs1 after widening outercount.
82; CHECK-NOT: sext
83; CHECK: getelementptr
84;
85; IV rewriting hoists a gep into this block. We don't like that.
86; CHECK-NOT: getelementptr
87outerloop:
88  %outercount   = phi i32 [ %outerpostcount, %outermerge ], [ 0, %entry ]
89  %innercount = phi i32 [ %innercount.merge, %outermerge ], [ 0, %entry ]
90
91  %outercountdec = add i32 %outercount, -1
92  %ofs1 = sext i32 %outercountdec to i64
93  %adr1 = getelementptr i8, i8* %address, i64 %ofs1
94  store i8 0, i8* %adr1
95
96  br label %innerpreheader
97
98innerpreheader:
99  %innerprecmp = icmp sgt i32 %limitdec, %innercount
100  br i1 %innerprecmp, label %innerloop, label %outermerge
101
102; CHECK: innerloop:
103;
104; Eliminate %ofs2 after widening inneriv.
105; Eliminate %ofs3 after normalizing sext(innerpostiv)
106; CHECK-NOT: sext
107; CHECK: getelementptr
108;
109; FIXME: We should check that indvars does not increase the number of
110; IVs in this loop. sext elimination plus LFTR currently results in 2 final
111; IVs. Waiting to remove LFTR.
112innerloop:
113  %inneriv = phi i32 [ %innerpostiv, %innerloop ], [ %innercount, %innerpreheader ]
114  %innerpostiv = add i32 %inneriv, 1
115
116  %ofs2 = sext i32 %inneriv to i64
117  %adr2 = getelementptr i8, i8* %address, i64 %ofs2
118  store i8 0, i8* %adr2
119
120  %ofs3 = sext i32 %innerpostiv to i64
121  %adr3 = getelementptr i8, i8* %address, i64 %ofs3
122  store i8 0, i8* %adr3
123
124  %innercmp = icmp sgt i32 %limitdec, %innerpostiv
125  br i1 %innercmp, label %innerloop, label %innerexit
126
127innerexit:
128  %innercount.lcssa = phi i32 [ %innerpostiv, %innerloop ]
129  br label %outermerge
130
131; CHECK: outermerge:
132;
133; Eliminate %ofs4 after widening outercount
134; CHECK-NOT: sext
135; CHECK: getelementptr
136;
137; TODO: Eliminate %ofs5 after removing lcssa
138outermerge:
139  %innercount.merge = phi i32 [ %innercount.lcssa, %innerexit ], [ %innercount, %innerpreheader ]
140
141  %ofs4 = sext i32 %outercount to i64
142  %adr4 = getelementptr i8, i8* %address, i64 %ofs4
143  store i8 0, i8* %adr4
144
145  %ofs5 = sext i32 %innercount.merge to i64
146  %adr5 = getelementptr i8, i8* %address, i64 %ofs5
147  store i8 0, i8* %adr5
148
149  %outerpostcount = add i32 %outercount, 1
150  %tmp47 = icmp slt i32 %outerpostcount, %limit
151  br i1 %tmp47, label %outerloop, label %return
152
153return:
154  ret void
155}
156