xref: /aosp_15_r20/external/llvm/test/Transforms/LoopUnroll/scevunroll.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker; RUN: opt < %s -S -indvars -loop-unroll -verify-loop-info | FileCheck %s
2*9880d681SAndroid Build Coastguard Worker;
3*9880d681SAndroid Build Coastguard Worker; Unit tests for loop unrolling using ScalarEvolution to compute trip counts.
4*9880d681SAndroid Build Coastguard Worker;
5*9880d681SAndroid Build Coastguard Worker; Indvars is run first to generate an "old" SCEV result. Some unit
6*9880d681SAndroid Build Coastguard Worker; tests may check that SCEV is properly invalidated between passes.
7*9880d681SAndroid Build Coastguard Worker
8*9880d681SAndroid Build Coastguard Worker; Completely unroll loops without a canonical IV.
9*9880d681SAndroid Build Coastguard Worker;
10*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @sansCanonical(
11*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: phi
12*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: icmp
13*9880d681SAndroid Build Coastguard Worker; CHECK: ret
14*9880d681SAndroid Build Coastguard Workerdefine i32 @sansCanonical(i32* %base) nounwind {
15*9880d681SAndroid Build Coastguard Workerentry:
16*9880d681SAndroid Build Coastguard Worker  br label %while.body
17*9880d681SAndroid Build Coastguard Worker
18*9880d681SAndroid Build Coastguard Workerwhile.body:
19*9880d681SAndroid Build Coastguard Worker  %iv = phi i64 [ 10, %entry ], [ %iv.next, %while.body ]
20*9880d681SAndroid Build Coastguard Worker  %sum = phi i32 [ 0, %entry ], [ %sum.next, %while.body ]
21*9880d681SAndroid Build Coastguard Worker  %iv.next = add i64 %iv, -1
22*9880d681SAndroid Build Coastguard Worker  %adr = getelementptr inbounds i32, i32* %base, i64 %iv.next
23*9880d681SAndroid Build Coastguard Worker  %tmp = load i32, i32* %adr, align 8
24*9880d681SAndroid Build Coastguard Worker  %sum.next = add i32 %sum, %tmp
25*9880d681SAndroid Build Coastguard Worker  %iv.narrow = trunc i64 %iv.next to i32
26*9880d681SAndroid Build Coastguard Worker  %cmp.i65 = icmp sgt i32 %iv.narrow, 0
27*9880d681SAndroid Build Coastguard Worker  br i1 %cmp.i65, label %while.body, label %exit
28*9880d681SAndroid Build Coastguard Worker
29*9880d681SAndroid Build Coastguard Workerexit:
30*9880d681SAndroid Build Coastguard Worker  ret i32 %sum
31*9880d681SAndroid Build Coastguard Worker}
32*9880d681SAndroid Build Coastguard Worker
33*9880d681SAndroid Build Coastguard Worker; SCEV unrolling properly handles loops with multiple exits. In this
34*9880d681SAndroid Build Coastguard Worker; case, the computed trip count based on a canonical IV is *not* for a
35*9880d681SAndroid Build Coastguard Worker; latch block. Canonical unrolling incorrectly unrolls it, but SCEV
36*9880d681SAndroid Build Coastguard Worker; unrolling does not.
37*9880d681SAndroid Build Coastguard Worker;
38*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @earlyLoopTest(
39*9880d681SAndroid Build Coastguard Worker; CHECK: tail:
40*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: br
41*9880d681SAndroid Build Coastguard Worker; CHECK: br i1 %cmp2, label %loop, label %exit2
42*9880d681SAndroid Build Coastguard Workerdefine i64 @earlyLoopTest(i64* %base) nounwind {
43*9880d681SAndroid Build Coastguard Workerentry:
44*9880d681SAndroid Build Coastguard Worker  br label %loop
45*9880d681SAndroid Build Coastguard Worker
46*9880d681SAndroid Build Coastguard Workerloop:
47*9880d681SAndroid Build Coastguard Worker  %iv = phi i64 [ 0, %entry ], [ %inc, %tail ]
48*9880d681SAndroid Build Coastguard Worker  %s = phi i64 [ 0, %entry ], [ %s.next, %tail ]
49*9880d681SAndroid Build Coastguard Worker  %adr = getelementptr i64, i64* %base, i64 %iv
50*9880d681SAndroid Build Coastguard Worker  %val = load i64, i64* %adr
51*9880d681SAndroid Build Coastguard Worker  %s.next = add i64 %s, %val
52*9880d681SAndroid Build Coastguard Worker  %inc = add i64 %iv, 1
53*9880d681SAndroid Build Coastguard Worker  %cmp = icmp ne i64 %inc, 4
54*9880d681SAndroid Build Coastguard Worker  br i1 %cmp, label %tail, label %exit1
55*9880d681SAndroid Build Coastguard Worker
56*9880d681SAndroid Build Coastguard Workertail:
57*9880d681SAndroid Build Coastguard Worker  %cmp2 = icmp ne i64 %val, 0
58*9880d681SAndroid Build Coastguard Worker  br i1 %cmp2, label %loop, label %exit2
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Workerexit1:
61*9880d681SAndroid Build Coastguard Worker  ret i64 %s
62*9880d681SAndroid Build Coastguard Worker
63*9880d681SAndroid Build Coastguard Workerexit2:
64*9880d681SAndroid Build Coastguard Worker  ret i64 %s.next
65*9880d681SAndroid Build Coastguard Worker}
66*9880d681SAndroid Build Coastguard Worker
67*9880d681SAndroid Build Coastguard Worker; SCEV properly unrolls multi-exit loops.
68*9880d681SAndroid Build Coastguard Worker;
69*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @multiExit(
70*9880d681SAndroid Build Coastguard Worker; CHECK: getelementptr i32, i32* %base, i32 10
71*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: load i32, i32*
72*9880d681SAndroid Build Coastguard Worker; CHECK: br i1 false, label %l2.10, label %exit1
73*9880d681SAndroid Build Coastguard Worker; CHECK: l2.10:
74*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: br
75*9880d681SAndroid Build Coastguard Worker; CHECK: ret i32
76*9880d681SAndroid Build Coastguard Workerdefine i32 @multiExit(i32* %base) nounwind {
77*9880d681SAndroid Build Coastguard Workerentry:
78*9880d681SAndroid Build Coastguard Worker  br label %l1
79*9880d681SAndroid Build Coastguard Workerl1:
80*9880d681SAndroid Build Coastguard Worker  %iv1 = phi i32 [ 0, %entry ], [ %inc1, %l2 ]
81*9880d681SAndroid Build Coastguard Worker  %iv2 = phi i32 [ 0, %entry ], [ %inc2, %l2 ]
82*9880d681SAndroid Build Coastguard Worker  %inc1 = add i32 %iv1, 1
83*9880d681SAndroid Build Coastguard Worker  %inc2 = add i32 %iv2, 1
84*9880d681SAndroid Build Coastguard Worker  %adr = getelementptr i32, i32* %base, i32 %iv1
85*9880d681SAndroid Build Coastguard Worker  %val = load i32, i32* %adr
86*9880d681SAndroid Build Coastguard Worker  %cmp1 = icmp slt i32 %iv1, 5
87*9880d681SAndroid Build Coastguard Worker  br i1 %cmp1, label %l2, label %exit1
88*9880d681SAndroid Build Coastguard Workerl2:
89*9880d681SAndroid Build Coastguard Worker  %cmp2 = icmp slt i32 %iv2, 10
90*9880d681SAndroid Build Coastguard Worker  br i1 %cmp2, label %l1, label %exit2
91*9880d681SAndroid Build Coastguard Workerexit1:
92*9880d681SAndroid Build Coastguard Worker  ret i32 1
93*9880d681SAndroid Build Coastguard Workerexit2:
94*9880d681SAndroid Build Coastguard Worker  ret i32 %val
95*9880d681SAndroid Build Coastguard Worker}
96*9880d681SAndroid Build Coastguard Worker
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Worker; SCEV should not unroll a multi-exit loops unless the latch block has
99*9880d681SAndroid Build Coastguard Worker; a known trip count, regardless of the early exit trip counts. The
100*9880d681SAndroid Build Coastguard Worker; LoopUnroll utility uses this assumption to optimize the latch
101*9880d681SAndroid Build Coastguard Worker; block's branch.
102*9880d681SAndroid Build Coastguard Worker;
103*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @multiExitIncomplete(
104*9880d681SAndroid Build Coastguard Worker; CHECK: l3:
105*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: br
106*9880d681SAndroid Build Coastguard Worker; CHECK:   br i1 %cmp3, label %l1, label %exit3
107*9880d681SAndroid Build Coastguard Workerdefine i32 @multiExitIncomplete(i32* %base) nounwind {
108*9880d681SAndroid Build Coastguard Workerentry:
109*9880d681SAndroid Build Coastguard Worker  br label %l1
110*9880d681SAndroid Build Coastguard Workerl1:
111*9880d681SAndroid Build Coastguard Worker  %iv1 = phi i32 [ 0, %entry ], [ %inc1, %l3 ]
112*9880d681SAndroid Build Coastguard Worker  %iv2 = phi i32 [ 0, %entry ], [ %inc2, %l3 ]
113*9880d681SAndroid Build Coastguard Worker  %inc1 = add i32 %iv1, 1
114*9880d681SAndroid Build Coastguard Worker  %inc2 = add i32 %iv2, 1
115*9880d681SAndroid Build Coastguard Worker  %adr = getelementptr i32, i32* %base, i32 %iv1
116*9880d681SAndroid Build Coastguard Worker  %val = load i32, i32* %adr
117*9880d681SAndroid Build Coastguard Worker  %cmp1 = icmp slt i32 %iv1, 5
118*9880d681SAndroid Build Coastguard Worker  br i1 %cmp1, label %l2, label %exit1
119*9880d681SAndroid Build Coastguard Workerl2:
120*9880d681SAndroid Build Coastguard Worker  %cmp2 = icmp slt i32 %iv2, 10
121*9880d681SAndroid Build Coastguard Worker  br i1 %cmp2, label %l3, label %exit2
122*9880d681SAndroid Build Coastguard Workerl3:
123*9880d681SAndroid Build Coastguard Worker  %cmp3 = icmp ne i32 %val, 0
124*9880d681SAndroid Build Coastguard Worker  br i1 %cmp3, label %l1, label %exit3
125*9880d681SAndroid Build Coastguard Worker
126*9880d681SAndroid Build Coastguard Workerexit1:
127*9880d681SAndroid Build Coastguard Worker  ret i32 1
128*9880d681SAndroid Build Coastguard Workerexit2:
129*9880d681SAndroid Build Coastguard Worker  ret i32 2
130*9880d681SAndroid Build Coastguard Workerexit3:
131*9880d681SAndroid Build Coastguard Worker  ret i32 3
132*9880d681SAndroid Build Coastguard Worker}
133*9880d681SAndroid Build Coastguard Worker
134*9880d681SAndroid Build Coastguard Worker; When loop unroll merges a loop exit with one of its parent loop's
135*9880d681SAndroid Build Coastguard Worker; exits, SCEV must forget its ExitNotTaken info.
136*9880d681SAndroid Build Coastguard Worker;
137*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @nestedUnroll(
138*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: br i1
139*9880d681SAndroid Build Coastguard Worker; CHECK: for.body87:
140*9880d681SAndroid Build Coastguard Workerdefine void @nestedUnroll() nounwind {
141*9880d681SAndroid Build Coastguard Workerentry:
142*9880d681SAndroid Build Coastguard Worker  br label %for.inc
143*9880d681SAndroid Build Coastguard Worker
144*9880d681SAndroid Build Coastguard Workerfor.inc:
145*9880d681SAndroid Build Coastguard Worker  br i1 false, label %for.inc, label %for.body38.preheader
146*9880d681SAndroid Build Coastguard Worker
147*9880d681SAndroid Build Coastguard Workerfor.body38.preheader:
148*9880d681SAndroid Build Coastguard Worker  br label %for.body38
149*9880d681SAndroid Build Coastguard Worker
150*9880d681SAndroid Build Coastguard Workerfor.body38:
151*9880d681SAndroid Build Coastguard Worker  %i.113 = phi i32 [ %inc76, %for.inc74 ], [ 0, %for.body38.preheader ]
152*9880d681SAndroid Build Coastguard Worker  %mul48 = mul nsw i32 %i.113, 6
153*9880d681SAndroid Build Coastguard Worker  br label %for.body43
154*9880d681SAndroid Build Coastguard Worker
155*9880d681SAndroid Build Coastguard Workerfor.body43:
156*9880d681SAndroid Build Coastguard Worker  %j.011 = phi i32 [ 0, %for.body38 ], [ %inc72, %for.body43 ]
157*9880d681SAndroid Build Coastguard Worker  %add49 = add nsw i32 %j.011, %mul48
158*9880d681SAndroid Build Coastguard Worker  %sh_prom50 = zext i32 %add49 to i64
159*9880d681SAndroid Build Coastguard Worker  %inc72 = add nsw i32 %j.011, 1
160*9880d681SAndroid Build Coastguard Worker  br i1 false, label %for.body43, label %for.inc74
161*9880d681SAndroid Build Coastguard Worker
162*9880d681SAndroid Build Coastguard Workerfor.inc74:
163*9880d681SAndroid Build Coastguard Worker  %inc76 = add nsw i32 %i.113, 1
164*9880d681SAndroid Build Coastguard Worker  br i1 false, label %for.body38, label %for.body87.preheader
165*9880d681SAndroid Build Coastguard Worker
166*9880d681SAndroid Build Coastguard Workerfor.body87.preheader:
167*9880d681SAndroid Build Coastguard Worker  br label %for.body87
168*9880d681SAndroid Build Coastguard Worker
169*9880d681SAndroid Build Coastguard Workerfor.body87:
170*9880d681SAndroid Build Coastguard Worker  br label %for.body87
171*9880d681SAndroid Build Coastguard Worker}
172*9880d681SAndroid Build Coastguard Worker
173*9880d681SAndroid Build Coastguard Worker; PR16130: clang produces incorrect code with loop/expression at -O2
174*9880d681SAndroid Build Coastguard Worker; rdar:14036816 loop-unroll makes assumptions about undefined behavior
175*9880d681SAndroid Build Coastguard Worker;
176*9880d681SAndroid Build Coastguard Worker; The loop latch is assumed to exit after the first iteration because
177*9880d681SAndroid Build Coastguard Worker; of the induction variable's NSW flag. However, the loop latch's
178*9880d681SAndroid Build Coastguard Worker; equality test is skipped and the loop exits after the second
179*9880d681SAndroid Build Coastguard Worker; iteration via the early exit. So loop unrolling cannot assume that
180*9880d681SAndroid Build Coastguard Worker; the loop latch's exit count of zero is an upper bound on the number
181*9880d681SAndroid Build Coastguard Worker; of iterations.
182*9880d681SAndroid Build Coastguard Worker;
183*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @nsw_latch(
184*9880d681SAndroid Build Coastguard Worker; CHECK: for.body:
185*9880d681SAndroid Build Coastguard Worker; CHECK: %b.03 = phi i32 [ 0, %entry ], [ %add, %for.cond ]
186*9880d681SAndroid Build Coastguard Worker; CHECK: return:
187*9880d681SAndroid Build Coastguard Worker; CHECK: %b.03.lcssa = phi i32 [ %b.03, %for.body ], [ %b.03, %for.cond ]
188*9880d681SAndroid Build Coastguard Workerdefine void @nsw_latch(i32* %a) nounwind {
189*9880d681SAndroid Build Coastguard Workerentry:
190*9880d681SAndroid Build Coastguard Worker  br label %for.body
191*9880d681SAndroid Build Coastguard Worker
192*9880d681SAndroid Build Coastguard Workerfor.body:                                         ; preds = %for.cond, %entry
193*9880d681SAndroid Build Coastguard Worker  %b.03 = phi i32 [ 0, %entry ], [ %add, %for.cond ]
194*9880d681SAndroid Build Coastguard Worker  %tobool = icmp eq i32 %b.03, 0
195*9880d681SAndroid Build Coastguard Worker  %add = add nsw i32 %b.03, 8
196*9880d681SAndroid Build Coastguard Worker  br i1 %tobool, label %for.cond, label %return
197*9880d681SAndroid Build Coastguard Worker
198*9880d681SAndroid Build Coastguard Workerfor.cond:                                         ; preds = %for.body
199*9880d681SAndroid Build Coastguard Worker  %cmp = icmp eq i32 %add, 13
200*9880d681SAndroid Build Coastguard Worker  br i1 %cmp, label %return, label %for.body
201*9880d681SAndroid Build Coastguard Worker
202*9880d681SAndroid Build Coastguard Workerreturn:                                           ; preds = %for.body, %for.cond
203*9880d681SAndroid Build Coastguard Worker  %b.03.lcssa = phi i32 [ %b.03, %for.body ], [ %b.03, %for.cond ]
204*9880d681SAndroid Build Coastguard Worker  %retval.0 = phi i32 [ 1, %for.body ], [ 0, %for.cond ]
205*9880d681SAndroid Build Coastguard Worker  store i32 %b.03.lcssa, i32* %a, align 4
206*9880d681SAndroid Build Coastguard Worker  ret void
207*9880d681SAndroid Build Coastguard Worker}
208