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