xref: /llvm-project/llvm/test/Transforms/IRCE/decrementing-loop.ll (revision 0ec421d024fe47fb43afdaa625309b0f799e9a59)
1*0ec421d0SRoman Lebedev; RUN: opt -verify-loop-info -passes=irce -S < %s | FileCheck %s
267904db2SAlina Sbirlea; RUN: opt -verify-loop-info -passes='require<branch-prob>,irce' -S < %s | FileCheck %s
3cee313d2SEric Christopher
4631432a3SMatt Arsenaultdefine void @decrementing_loop(ptr %arr, ptr %a_len_ptr, i32 %n) {
5cee313d2SEric Christopher entry:
6631432a3SMatt Arsenault  %len = load i32, ptr %a_len_ptr, !range !0
7cee313d2SEric Christopher  %first.itr.check = icmp sgt i32 %n, 0
8cee313d2SEric Christopher  %start = sub i32 %n, 1
9cee313d2SEric Christopher  br i1 %first.itr.check, label %loop, label %exit
10cee313d2SEric Christopher
11cee313d2SEric Christopher loop:
12cee313d2SEric Christopher  %idx = phi i32 [ %start, %entry ] , [ %idx.dec, %in.bounds ]
13cee313d2SEric Christopher  %idx.dec = sub i32 %idx, 1
14cee313d2SEric Christopher  %abc.high = icmp slt i32 %idx, %len
15cee313d2SEric Christopher  %abc.low = icmp sge i32 %idx, 0
16cee313d2SEric Christopher  %abc = and i1 %abc.low, %abc.high
17cee313d2SEric Christopher  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
18cee313d2SEric Christopher
19cee313d2SEric Christopher in.bounds:
20631432a3SMatt Arsenault  %addr = getelementptr i32, ptr %arr, i32 %idx
21631432a3SMatt Arsenault  store i32 0, ptr %addr
22cee313d2SEric Christopher  %next = icmp sgt i32 %idx.dec, -1
23cee313d2SEric Christopher  br i1 %next, label %loop, label %exit
24cee313d2SEric Christopher
25cee313d2SEric Christopher out.of.bounds:
26cee313d2SEric Christopher  ret void
27cee313d2SEric Christopher
28cee313d2SEric Christopher exit:
29cee313d2SEric Christopher  ret void
30cee313d2SEric Christopher
31cee313d2SEric Christopher; CHECK: loop.preheader:
32b46c085dSRoman Lebedev; CHECK:   [[len_hiclamp:[^ ]+]] = call i32 @llvm.smin.i32(i32 %len, i32 %n)
33b46c085dSRoman Lebedev; CHECK:   [[not_exit_preloop_at:[^ ]+]] = call i32 @llvm.smax.i32(i32 [[len_hiclamp]], i32 0)
340cf9639aSSam Parker; CHECK:   %exit.preloop.at = add nsw i32 [[not_exit_preloop_at]], -1
35cee313d2SEric Christopher}
36cee313d2SEric Christopher
37cee313d2SEric Christopher; Make sure that we can eliminate the range check when the loop looks like:
38cee313d2SEric Christopher; for (i = len.a - 1; i >= 0; --i)
39cee313d2SEric Christopher;   b[i] = a[i];
40631432a3SMatt Arsenaultdefine void @test_01(ptr %a, ptr %b, ptr %a_len_ptr, ptr %b_len_ptr) {
41cee313d2SEric Christopher
42cee313d2SEric Christopher; CHECK-LABEL: test_01
43cee313d2SEric Christopher; CHECK:       mainloop:
44cee313d2SEric Christopher; CHECK-NEXT:    br label %loop
45cee313d2SEric Christopher; CHECK:       loop:
46cee313d2SEric Christopher; CHECK:         %rc = and i1 true, true
47cee313d2SEric Christopher; CHECK:       loop.preloop:
48cee313d2SEric Christopher
49cee313d2SEric Christopher entry:
50631432a3SMatt Arsenault  %len.a = load i32, ptr %a_len_ptr, !range !0
51631432a3SMatt Arsenault  %len.b = load i32, ptr %b_len_ptr, !range !0
52cee313d2SEric Christopher  %first.itr.check = icmp ne i32 %len.a, 0
53cee313d2SEric Christopher  br i1 %first.itr.check, label %loop, label %exit
54cee313d2SEric Christopher
55cee313d2SEric Christopher loop:
56cee313d2SEric Christopher  %idx = phi i32 [ %len.a, %entry ] , [ %idx.next, %in.bounds ]
57cee313d2SEric Christopher  %idx.next = sub i32 %idx, 1
58cee313d2SEric Christopher  %rca = icmp ult i32 %idx.next, %len.a
59cee313d2SEric Christopher  %rcb = icmp ult i32 %idx.next, %len.b
60cee313d2SEric Christopher  %rc = and i1 %rca, %rcb
61cee313d2SEric Christopher  br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1
62cee313d2SEric Christopher
63cee313d2SEric Christopher in.bounds:
64631432a3SMatt Arsenault  %el.a = getelementptr i32, ptr %a, i32 %idx.next
65631432a3SMatt Arsenault  %el.b = getelementptr i32, ptr %b, i32 %idx.next
66631432a3SMatt Arsenault  %v = load i32, ptr %el.a
67631432a3SMatt Arsenault  store i32 %v, ptr %el.b
68cee313d2SEric Christopher  %loop.cond = icmp slt i32 %idx, 2
69cee313d2SEric Christopher  br i1 %loop.cond, label %exit, label %loop
70cee313d2SEric Christopher
71cee313d2SEric Christopher out.of.bounds:
72cee313d2SEric Christopher  ret void
73cee313d2SEric Christopher
74cee313d2SEric Christopher exit:
75cee313d2SEric Christopher  ret void
76cee313d2SEric Christopher}
77cee313d2SEric Christopher
78cee313d2SEric Christopher; Same as test_01, but the latch condition is unsigned
79631432a3SMatt Arsenaultdefine void @test_02(ptr %a, ptr %b, ptr %a_len_ptr, ptr %b_len_ptr) {
80cee313d2SEric Christopher
81cee313d2SEric Christopher; CHECK-LABEL: test_02
82cee313d2SEric Christopher; CHECK:       mainloop:
83cee313d2SEric Christopher; CHECK-NEXT:    br label %loop
84cee313d2SEric Christopher; CHECK:       loop:
85cee313d2SEric Christopher; CHECK:         %rc = and i1 true, true
86cee313d2SEric Christopher; CHECK:       loop.preloop:
87cee313d2SEric Christopher
88cee313d2SEric Christopher entry:
89631432a3SMatt Arsenault  %len.a = load i32, ptr %a_len_ptr, !range !0
90631432a3SMatt Arsenault  %len.b = load i32, ptr %b_len_ptr, !range !0
91cee313d2SEric Christopher  %first.itr.check = icmp ne i32 %len.a, 0
92cee313d2SEric Christopher  br i1 %first.itr.check, label %loop, label %exit
93cee313d2SEric Christopher
94cee313d2SEric Christopher loop:
95cee313d2SEric Christopher  %idx = phi i32 [ %len.a, %entry ] , [ %idx.next, %in.bounds ]
96cee313d2SEric Christopher  %idx.next = sub i32 %idx, 1
97cee313d2SEric Christopher  %rca = icmp ult i32 %idx.next, %len.a
98cee313d2SEric Christopher  %rcb = icmp ult i32 %idx.next, %len.b
99cee313d2SEric Christopher  %rc = and i1 %rca, %rcb
100cee313d2SEric Christopher  br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1
101cee313d2SEric Christopher
102cee313d2SEric Christopher in.bounds:
103631432a3SMatt Arsenault  %el.a = getelementptr i32, ptr %a, i32 %idx.next
104631432a3SMatt Arsenault  %el.b = getelementptr i32, ptr %b, i32 %idx.next
105631432a3SMatt Arsenault  %v = load i32, ptr %el.a
106631432a3SMatt Arsenault  store i32 %v, ptr %el.b
107cee313d2SEric Christopher  %loop.cond = icmp ult i32 %idx, 2
108cee313d2SEric Christopher  br i1 %loop.cond, label %exit, label %loop
109cee313d2SEric Christopher
110cee313d2SEric Christopher out.of.bounds:
111cee313d2SEric Christopher  ret void
112cee313d2SEric Christopher
113cee313d2SEric Christopher exit:
114cee313d2SEric Christopher  ret void
115cee313d2SEric Christopher}
116cee313d2SEric Christopher
117cee313d2SEric Christopher; Check that we can figure out that IV is non-negative via implication through
118cee313d2SEric Christopher; Phi node.
119631432a3SMatt Arsenaultdefine void @test_03(ptr %a, ptr %a_len_ptr, i1 %cond) {
120cee313d2SEric Christopher
121cee313d2SEric Christopher; CHECK-LABEL: test_03
122cee313d2SEric Christopher; CHECK:       mainloop:
123cee313d2SEric Christopher; CHECK-NEXT:    br label %loop
124cee313d2SEric Christopher; CHECK:       loop:
125cee313d2SEric Christopher; CHECK:         br i1 true, label %in.bounds, label %out.of.bounds
126cee313d2SEric Christopher; CHECK:       loop.preloop:
127cee313d2SEric Christopher
128cee313d2SEric Christopher entry:
129631432a3SMatt Arsenault  %len.a = load i32, ptr %a_len_ptr, !range !0
130cee313d2SEric Christopher  %len.minus.one = sub nsw i32 %len.a, 1
131cee313d2SEric Christopher  %len.minus.two = sub nsw i32 %len.a, 2
132cee313d2SEric Christopher  br i1 %cond, label %if.true, label %if.false
133cee313d2SEric Christopher
134cee313d2SEric Christopherif.true:
135cee313d2SEric Christopher  br label %merge
136cee313d2SEric Christopher
137cee313d2SEric Christopherif.false:
138cee313d2SEric Christopher  br label %merge
139cee313d2SEric Christopher
140cee313d2SEric Christophermerge:
141cee313d2SEric Christopher  %starting.value = phi i32 [ %len.minus.two, %if.true ], [ %len.minus.one, %if.false ]
142cee313d2SEric Christopher  %first.itr.check = icmp sgt i32 %len.a, 3
143cee313d2SEric Christopher  br i1 %first.itr.check, label %loop, label %exit
144cee313d2SEric Christopher
145cee313d2SEric Christopherloop:
146cee313d2SEric Christopher  %idx = phi i32 [ %starting.value, %merge ] , [ %idx.next, %in.bounds ]
147cee313d2SEric Christopher  %idx.next = sub i32 %idx, 1
148cee313d2SEric Christopher  %rc = icmp ult i32 %idx.next, %len.a
149cee313d2SEric Christopher  br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1
150cee313d2SEric Christopher
151cee313d2SEric Christopherin.bounds:
152631432a3SMatt Arsenault  %el.a = getelementptr i32, ptr %a, i32 %idx.next
153631432a3SMatt Arsenault  %v = load i32, ptr %el.a
154cee313d2SEric Christopher  %loop.cond = icmp slt i32 %idx, 2
155cee313d2SEric Christopher  br i1 %loop.cond, label %exit, label %loop
156cee313d2SEric Christopher
157cee313d2SEric Christopherout.of.bounds:
158cee313d2SEric Christopher  ret void
159cee313d2SEric Christopher
160cee313d2SEric Christopherexit:
161cee313d2SEric Christopher  ret void
162cee313d2SEric Christopher}
163cee313d2SEric Christopher
164cee313d2SEric Christopher; Check that we can figure out that IV is non-negative via implication through
165cee313d2SEric Christopher; two Phi nodes.
166631432a3SMatt Arsenaultdefine void @test_04(ptr %a, ptr %a_len_ptr, i1 %cond) {
167cee313d2SEric Christopher
168cee313d2SEric Christopher; CHECK-LABEL: test_04
169cee313d2SEric Christopher; CHECK:       mainloop:
170cee313d2SEric Christopher; CHECK-NEXT:    br label %loop
171cee313d2SEric Christopher; CHECK:       loop:
172cee313d2SEric Christopher; CHECK:         br i1 true, label %in.bounds, label %out.of.bounds
173cee313d2SEric Christopher; CHECK:       loop.preloop:
174cee313d2SEric Christopher
175cee313d2SEric Christopher entry:
176631432a3SMatt Arsenault  %len.a = load i32, ptr %a_len_ptr, !range !0
177cee313d2SEric Christopher  %len.minus.one = sub nsw i32 %len.a, 1
178cee313d2SEric Christopher  %len.plus.one = add nsw i32 %len.a, 1
179cee313d2SEric Christopher  %len.minus.two = sub nsw i32 %len.a, 2
180cee313d2SEric Christopher  br i1 %cond, label %if.true, label %if.false
181cee313d2SEric Christopher
182cee313d2SEric Christopherif.true:
183cee313d2SEric Christopher  br label %merge
184cee313d2SEric Christopher
185cee313d2SEric Christopherif.false:
186cee313d2SEric Christopher  br label %merge
187cee313d2SEric Christopher
188cee313d2SEric Christophermerge:
189cee313d2SEric Christopher  %starting.value = phi i32 [ %len.minus.two, %if.true ], [ %len.minus.one, %if.false ]
190cee313d2SEric Christopher  %len.phi = phi i32 [ %len.a, %if.true ], [ %len.plus.one, %if.false ]
191cee313d2SEric Christopher  %first.itr.check = icmp sgt i32 %len.a, 3
192cee313d2SEric Christopher  br i1 %first.itr.check, label %loop, label %exit
193cee313d2SEric Christopher
194cee313d2SEric Christopherloop:
195cee313d2SEric Christopher  %idx = phi i32 [ %starting.value, %merge ] , [ %idx.next, %in.bounds ]
196cee313d2SEric Christopher  %idx.next = sub i32 %idx, 1
197cee313d2SEric Christopher  %rc = icmp ult i32 %idx.next, %len.phi
198cee313d2SEric Christopher  br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1
199cee313d2SEric Christopher
200cee313d2SEric Christopherin.bounds:
201631432a3SMatt Arsenault  %el.a = getelementptr i32, ptr %a, i32 %idx.next
202631432a3SMatt Arsenault  %v = load i32, ptr %el.a
203cee313d2SEric Christopher  %loop.cond = icmp slt i32 %idx, 2
204cee313d2SEric Christopher  br i1 %loop.cond, label %exit, label %loop
205cee313d2SEric Christopher
206cee313d2SEric Christopherout.of.bounds:
207cee313d2SEric Christopher  ret void
208cee313d2SEric Christopher
209cee313d2SEric Christopherexit:
210cee313d2SEric Christopher  ret void
211cee313d2SEric Christopher}
212cee313d2SEric Christopher
213cee313d2SEric Christopher; Check that we can figure out that IV is non-negative via implication through
214cee313d2SEric Christopher; two Phi nodes, one being AddRec.
215631432a3SMatt Arsenaultdefine void @test_05(ptr %a, ptr %a_len_ptr, i1 %cond) {
216cee313d2SEric Christopher
217cee313d2SEric Christopher; CHECK-LABEL: test_05
218e4d1d0ccSNikita Popov; CHECK:       mainloop:
219e4d1d0ccSNikita Popov; CHECK-NEXT:    br label %loop
220e4d1d0ccSNikita Popov; CHECK:       loop:
221e4d1d0ccSNikita Popov; CHECK:         br i1 true, label %in.bounds, label %out.of.bounds
222e4d1d0ccSNikita Popov; CHECK:       loop.preloop:
223cee313d2SEric Christopher
224cee313d2SEric Christopher entry:
225631432a3SMatt Arsenault  %len.a = load i32, ptr %a_len_ptr, !range !0
226cee313d2SEric Christopher  %len.minus.one = sub nsw i32 %len.a, 1
227cee313d2SEric Christopher  %len.plus.one = add nsw i32 %len.a, 1
228cee313d2SEric Christopher  %len.minus.two = sub nsw i32 %len.a, 2
229cee313d2SEric Christopher  br label %merge
230cee313d2SEric Christopher
231cee313d2SEric Christophermerge:
232cee313d2SEric Christopher  %starting.value = phi i32 [ %len.minus.two, %entry ], [ %len.minus.one, %merge ]
233cee313d2SEric Christopher  %len.phi = phi i32 [ %len.a, %entry ], [ %len.phi.next, %merge ]
234cee313d2SEric Christopher  %len.phi.next = add nsw i32 %len.phi, 1
235cee313d2SEric Christopher  br i1 true, label %first.iter.check, label %merge
236cee313d2SEric Christopher
237cee313d2SEric Christopherfirst.iter.check:
238cee313d2SEric Christopher  %first.itr.check = icmp sgt i32 %len.a, 3
239cee313d2SEric Christopher  br i1 %first.itr.check, label %loop, label %exit
240cee313d2SEric Christopher
241cee313d2SEric Christopherloop:
242cee313d2SEric Christopher  %idx = phi i32 [ %starting.value, %first.iter.check ] , [ %idx.next, %in.bounds ]
243cee313d2SEric Christopher  %idx.next = sub i32 %idx, 1
244cee313d2SEric Christopher  %rc = icmp ult i32 %idx.next, %len.phi
245cee313d2SEric Christopher  br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1
246cee313d2SEric Christopher
247cee313d2SEric Christopherin.bounds:
248631432a3SMatt Arsenault  %el.a = getelementptr i32, ptr %a, i32 %idx.next
249631432a3SMatt Arsenault  %v = load i32, ptr %el.a
250cee313d2SEric Christopher  %loop.cond = icmp slt i32 %idx, 2
251cee313d2SEric Christopher  br i1 %loop.cond, label %exit, label %loop
252cee313d2SEric Christopher
253cee313d2SEric Christopherout.of.bounds:
254cee313d2SEric Christopher  ret void
255cee313d2SEric Christopher
256cee313d2SEric Christopherexit:
257cee313d2SEric Christopher  ret void
258cee313d2SEric Christopher}
259cee313d2SEric Christopher
260cee313d2SEric Christopher!0 = !{i32 0, i32 2147483647}
261cee313d2SEric Christopher!1 = !{!"branch_weights", i32 64, i32 4}
262