xref: /llvm-project/llvm/test/Transforms/LoopPredication/reverse.ll (revision 99da317331e37d530610695b0cf44ba2686b735e)
1cee313d2SEric Christopher; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2e23e1594SRoman Lebedev; RUN: opt -S -passes=loop-predication -loop-predication-enable-count-down-loop=true < %s 2>&1 | FileCheck %s
355bdb140SAnna Thomas; RUN: opt -S -passes='require<scalar-evolution>,loop-mssa(loop-predication)' -loop-predication-enable-count-down-loop=true < %s 2>&1 | FileCheck %s
4cee313d2SEric Christopher
5cee313d2SEric Christopherdeclare void @llvm.experimental.guard(i1, ...)
6cee313d2SEric Christopher
7ba89c667SNikita Popovdefine i32 @signed_reverse_loop_n_to_lower_limit(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) {
8cee313d2SEric Christopher; CHECK-LABEL: @signed_reverse_loop_n_to_lower_limit(
9cee313d2SEric Christopher; CHECK-NEXT:  entry:
10cee313d2SEric Christopher; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
11cee313d2SEric Christopher; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
12cee313d2SEric Christopher; CHECK:       loop.preheader:
13cee313d2SEric Christopher; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N]], -1
14cee313d2SEric Christopher; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
15cee313d2SEric Christopher; CHECK-NEXT:    [[TMP2:%.*]] = icmp sge i32 [[LOWERLIMIT:%.*]], 1
16cee313d2SEric Christopher; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]]
17*99da3173SSerguei Katkov; CHECK-NEXT:    [[TMP4:%.*]] = freeze i1 [[TMP3]]
18cee313d2SEric Christopher; CHECK-NEXT:    br label [[LOOP:%.*]]
19cee313d2SEric Christopher; CHECK:       loop:
20cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
21cee313d2SEric Christopher; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
22cee313d2SEric Christopher; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], -1
238307f6c8SDmitry Makogon; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]]
24*99da3173SSerguei Katkov; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ]
258307f6c8SDmitry Makogon; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
26cee313d2SEric Christopher; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
27ba89c667SNikita Popov; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
28ba89c667SNikita Popov; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
29cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
30cee313d2SEric Christopher; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp sgt i32 [[I]], [[LOWERLIMIT]]
31cee313d2SEric Christopher; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
32cee313d2SEric Christopher; CHECK:       exit.loopexit:
33cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
34cee313d2SEric Christopher; CHECK-NEXT:    br label [[EXIT]]
35cee313d2SEric Christopher; CHECK:       exit:
36cee313d2SEric Christopher; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
37cee313d2SEric Christopher; CHECK-NEXT:    ret i32 [[RESULT]]
38cee313d2SEric Christopher;
39cee313d2SEric Christopherentry:
40cee313d2SEric Christopher  %tmp5 = icmp eq i32 %n, 0
41cee313d2SEric Christopher  br i1 %tmp5, label %exit, label %loop.preheader
42cee313d2SEric Christopher
43cee313d2SEric Christopherloop.preheader:
44cee313d2SEric Christopher  br label %loop
45cee313d2SEric Christopher
46cee313d2SEric Christopherloop:
47cee313d2SEric Christopher  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
48cee313d2SEric Christopher  %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
49cee313d2SEric Christopher  %i.next = add nsw i32 %i, -1
50cee313d2SEric Christopher  %within.bounds = icmp ult i32 %i.next, %length
51cee313d2SEric Christopher  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
52cee313d2SEric Christopher  %i.i64 = zext i32 %i.next to i64
53ba89c667SNikita Popov  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
54ba89c667SNikita Popov  %array.i = load i32, ptr %array.i.ptr, align 4
55cee313d2SEric Christopher  %loop.acc.next = add i32 %loop.acc, %array.i
56cee313d2SEric Christopher  %continue = icmp sgt i32 %i, %lowerlimit
57cee313d2SEric Christopher  br i1 %continue, label %loop, label %exit
58cee313d2SEric Christopher
59cee313d2SEric Christopherexit:
60cee313d2SEric Christopher  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
61cee313d2SEric Christopher  ret i32 %result
62cee313d2SEric Christopher}
63cee313d2SEric Christopher
64ba89c667SNikita Popovdefine i32 @unsigned_reverse_loop_n_to_lower_limit(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) {
65cee313d2SEric Christopher; CHECK-LABEL: @unsigned_reverse_loop_n_to_lower_limit(
66cee313d2SEric Christopher; CHECK-NEXT:  entry:
67cee313d2SEric Christopher; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
68cee313d2SEric Christopher; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
69cee313d2SEric Christopher; CHECK:       loop.preheader:
70cee313d2SEric Christopher; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N]], -1
71cee313d2SEric Christopher; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
72cee313d2SEric Christopher; CHECK-NEXT:    [[TMP2:%.*]] = icmp uge i32 [[LOWERLIMIT:%.*]], 1
73cee313d2SEric Christopher; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]]
74*99da3173SSerguei Katkov; CHECK-NEXT:    [[TMP4:%.*]] = freeze i1 [[TMP3]]
75cee313d2SEric Christopher; CHECK-NEXT:    br label [[LOOP:%.*]]
76cee313d2SEric Christopher; CHECK:       loop:
77cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
78cee313d2SEric Christopher; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
79cee313d2SEric Christopher; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], -1
808307f6c8SDmitry Makogon; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]]
81*99da3173SSerguei Katkov; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ]
828307f6c8SDmitry Makogon; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
83cee313d2SEric Christopher; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
84ba89c667SNikita Popov; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
85ba89c667SNikita Popov; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
86cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
87cee313d2SEric Christopher; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ugt i32 [[I]], [[LOWERLIMIT]]
88cee313d2SEric Christopher; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
89cee313d2SEric Christopher; CHECK:       exit.loopexit:
90cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
91cee313d2SEric Christopher; CHECK-NEXT:    br label [[EXIT]]
92cee313d2SEric Christopher; CHECK:       exit:
93cee313d2SEric Christopher; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
94cee313d2SEric Christopher; CHECK-NEXT:    ret i32 [[RESULT]]
95cee313d2SEric Christopher;
96cee313d2SEric Christopherentry:
97cee313d2SEric Christopher  %tmp5 = icmp eq i32 %n, 0
98cee313d2SEric Christopher  br i1 %tmp5, label %exit, label %loop.preheader
99cee313d2SEric Christopher
100cee313d2SEric Christopherloop.preheader:
101cee313d2SEric Christopher  br label %loop
102cee313d2SEric Christopher
103cee313d2SEric Christopherloop:
104cee313d2SEric Christopher  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
105cee313d2SEric Christopher  %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
106cee313d2SEric Christopher  %i.next = add nsw i32 %i, -1
107cee313d2SEric Christopher  %within.bounds = icmp ult i32 %i.next, %length
108cee313d2SEric Christopher  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
109cee313d2SEric Christopher  %i.i64 = zext i32 %i.next to i64
110ba89c667SNikita Popov  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
111ba89c667SNikita Popov  %array.i = load i32, ptr %array.i.ptr, align 4
112cee313d2SEric Christopher  %loop.acc.next = add i32 %loop.acc, %array.i
113cee313d2SEric Christopher  %continue = icmp ugt i32 %i, %lowerlimit
114cee313d2SEric Christopher  br i1 %continue, label %loop, label %exit
115cee313d2SEric Christopher
116cee313d2SEric Christopherexit:
117cee313d2SEric Christopher  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
118cee313d2SEric Christopher  ret i32 %result
119cee313d2SEric Christopher}
120cee313d2SEric Christopher
121cee313d2SEric Christopher
122cee313d2SEric Christopher; if we predicated the loop, the guard will definitely fail and we will
123cee313d2SEric Christopher; deoptimize early on.
124ba89c667SNikita Popovdefine i32 @unsigned_reverse_loop_n_to_0(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) {
125cee313d2SEric Christopher; CHECK-LABEL: @unsigned_reverse_loop_n_to_0(
126cee313d2SEric Christopher; CHECK-NEXT:  entry:
127cee313d2SEric Christopher; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
128cee313d2SEric Christopher; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
129cee313d2SEric Christopher; CHECK:       loop.preheader:
130cee313d2SEric Christopher; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N]], -1
131cee313d2SEric Christopher; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
132b2915971SRoman Lebedev; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], false
133*99da3173SSerguei Katkov; CHECK-NEXT:    [[TMP3:%.*]] = freeze i1 [[TMP2]]
134cee313d2SEric Christopher; CHECK-NEXT:    br label [[LOOP:%.*]]
135cee313d2SEric Christopher; CHECK:       loop:
136cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
137cee313d2SEric Christopher; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
138cee313d2SEric Christopher; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], -1
1398307f6c8SDmitry Makogon; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]]
140*99da3173SSerguei Katkov; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
1418307f6c8SDmitry Makogon; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
142cee313d2SEric Christopher; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
143ba89c667SNikita Popov; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
144ba89c667SNikita Popov; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
145cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
146cee313d2SEric Christopher; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ugt i32 [[I]], 0
147cee313d2SEric Christopher; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
148cee313d2SEric Christopher; CHECK:       exit.loopexit:
149cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
150cee313d2SEric Christopher; CHECK-NEXT:    br label [[EXIT]]
151cee313d2SEric Christopher; CHECK:       exit:
152cee313d2SEric Christopher; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
153cee313d2SEric Christopher; CHECK-NEXT:    ret i32 [[RESULT]]
154cee313d2SEric Christopher;
155cee313d2SEric Christopherentry:
156cee313d2SEric Christopher  %tmp5 = icmp eq i32 %n, 0
157cee313d2SEric Christopher  br i1 %tmp5, label %exit, label %loop.preheader
158cee313d2SEric Christopher
159cee313d2SEric Christopherloop.preheader:
160cee313d2SEric Christopher  br label %loop
161cee313d2SEric Christopher
162cee313d2SEric Christopherloop:
163cee313d2SEric Christopher  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
164cee313d2SEric Christopher  %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
165cee313d2SEric Christopher  %i.next = add nsw i32 %i, -1
166cee313d2SEric Christopher  %within.bounds = icmp ult i32 %i.next, %length
167cee313d2SEric Christopher  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
168cee313d2SEric Christopher  %i.i64 = zext i32 %i.next to i64
169ba89c667SNikita Popov  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
170ba89c667SNikita Popov  %array.i = load i32, ptr %array.i.ptr, align 4
171cee313d2SEric Christopher  %loop.acc.next = add i32 %loop.acc, %array.i
172cee313d2SEric Christopher  %continue = icmp ugt i32 %i, 0
173cee313d2SEric Christopher  br i1 %continue, label %loop, label %exit
174cee313d2SEric Christopher
175cee313d2SEric Christopherexit:
176cee313d2SEric Christopher  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
177cee313d2SEric Christopher  ret i32 %result
178cee313d2SEric Christopher}
179cee313d2SEric Christopher
180cee313d2SEric Christopher; do not loop predicate when the range has step -1 and latch has step 1.
181ba89c667SNikita Popovdefine i32 @reverse_loop_range_step_increment(i32 %n, ptr %array, i32 %length) {
182cee313d2SEric Christopher; CHECK-LABEL: @reverse_loop_range_step_increment(
183cee313d2SEric Christopher; CHECK-NEXT:  entry:
184cee313d2SEric Christopher; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
185cee313d2SEric Christopher; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
186cee313d2SEric Christopher; CHECK:       loop.preheader:
187cee313d2SEric Christopher; CHECK-NEXT:    br label [[LOOP:%.*]]
188cee313d2SEric Christopher; CHECK:       loop:
189cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
190cee313d2SEric Christopher; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
191cee313d2SEric Christopher; CHECK-NEXT:    [[IRC:%.*]] = phi i32 [ [[I_INC:%.*]], [[LOOP]] ], [ 1, [[LOOP_PREHEADER]] ]
192cee313d2SEric Christopher; CHECK-NEXT:    [[I_INC]] = add nuw nsw i32 [[IRC]], 1
193cee313d2SEric Christopher; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[IRC]], [[LENGTH:%.*]]
194cee313d2SEric Christopher; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
195cee313d2SEric Christopher; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[IRC]] to i64
196ba89c667SNikita Popov; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
197ba89c667SNikita Popov; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
198cee313d2SEric Christopher; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], -1
199cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
200cee313d2SEric Christopher; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ugt i32 [[I]], 65534
201cee313d2SEric Christopher; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
202cee313d2SEric Christopher; CHECK:       exit.loopexit:
203cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
204cee313d2SEric Christopher; CHECK-NEXT:    br label [[EXIT]]
205cee313d2SEric Christopher; CHECK:       exit:
206cee313d2SEric Christopher; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
207cee313d2SEric Christopher; CHECK-NEXT:    ret i32 [[RESULT]]
208cee313d2SEric Christopher;
209cee313d2SEric Christopherentry:
210cee313d2SEric Christopher  %tmp5 = icmp eq i32 %n, 0
211cee313d2SEric Christopher  br i1 %tmp5, label %exit, label %loop.preheader
212cee313d2SEric Christopher
213cee313d2SEric Christopherloop.preheader:
214cee313d2SEric Christopher  br label %loop
215cee313d2SEric Christopher
216cee313d2SEric Christopherloop:
217cee313d2SEric Christopher  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
218cee313d2SEric Christopher  %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
219cee313d2SEric Christopher  %irc = phi i32 [ %i.inc, %loop ], [ 1, %loop.preheader ]
220cee313d2SEric Christopher  %i.inc = add nuw nsw i32 %irc, 1
221cee313d2SEric Christopher  %within.bounds = icmp ult i32 %irc, %length
222cee313d2SEric Christopher  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
223cee313d2SEric Christopher  %i.i64 = zext i32 %irc to i64
224ba89c667SNikita Popov  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
225ba89c667SNikita Popov  %array.i = load i32, ptr %array.i.ptr, align 4
226cee313d2SEric Christopher  %i.next = add nsw i32 %i, -1
227cee313d2SEric Christopher  %loop.acc.next = add i32 %loop.acc, %array.i
228cee313d2SEric Christopher  %continue = icmp ugt i32 %i, 65534
229cee313d2SEric Christopher  br i1 %continue, label %loop, label %exit
230cee313d2SEric Christopher
231cee313d2SEric Christopherexit:
232cee313d2SEric Christopher  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
233cee313d2SEric Christopher  ret i32 %result
234cee313d2SEric Christopher}
235cee313d2SEric Christopher
236ba89c667SNikita Popovdefine i32 @signed_reverse_loop_n_to_lower_limit_equal(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) {
237cee313d2SEric Christopher; CHECK-LABEL: @signed_reverse_loop_n_to_lower_limit_equal(
238cee313d2SEric Christopher; CHECK-NEXT:  entry:
239cee313d2SEric Christopher; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
240cee313d2SEric Christopher; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
241cee313d2SEric Christopher; CHECK:       loop.preheader:
242cee313d2SEric Christopher; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N]], -1
243cee313d2SEric Christopher; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
244cee313d2SEric Christopher; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[LOWERLIMIT:%.*]], 1
245cee313d2SEric Christopher; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]]
246*99da3173SSerguei Katkov; CHECK-NEXT:    [[TMP4:%.*]] = freeze i1 [[TMP3]]
247cee313d2SEric Christopher; CHECK-NEXT:    br label [[LOOP:%.*]]
248cee313d2SEric Christopher; CHECK:       loop:
249cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
250cee313d2SEric Christopher; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
251cee313d2SEric Christopher; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], -1
2528307f6c8SDmitry Makogon; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]]
253*99da3173SSerguei Katkov; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ]
2548307f6c8SDmitry Makogon; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
255cee313d2SEric Christopher; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
256ba89c667SNikita Popov; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
257ba89c667SNikita Popov; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
258cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
259cee313d2SEric Christopher; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp sge i32 [[I]], [[LOWERLIMIT]]
260cee313d2SEric Christopher; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
261cee313d2SEric Christopher; CHECK:       exit.loopexit:
262cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
263cee313d2SEric Christopher; CHECK-NEXT:    br label [[EXIT]]
264cee313d2SEric Christopher; CHECK:       exit:
265cee313d2SEric Christopher; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
266cee313d2SEric Christopher; CHECK-NEXT:    ret i32 [[RESULT]]
267cee313d2SEric Christopher;
268cee313d2SEric Christopherentry:
269cee313d2SEric Christopher  %tmp5 = icmp eq i32 %n, 0
270cee313d2SEric Christopher  br i1 %tmp5, label %exit, label %loop.preheader
271cee313d2SEric Christopher
272cee313d2SEric Christopherloop.preheader:
273cee313d2SEric Christopher  br label %loop
274cee313d2SEric Christopher
275cee313d2SEric Christopherloop:
276cee313d2SEric Christopher  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
277cee313d2SEric Christopher  %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
278cee313d2SEric Christopher  %i.next = add nsw i32 %i, -1
279cee313d2SEric Christopher  %within.bounds = icmp ult i32 %i.next, %length
280cee313d2SEric Christopher  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
281cee313d2SEric Christopher  %i.i64 = zext i32 %i.next to i64
282ba89c667SNikita Popov  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
283ba89c667SNikita Popov  %array.i = load i32, ptr %array.i.ptr, align 4
284cee313d2SEric Christopher  %loop.acc.next = add i32 %loop.acc, %array.i
285cee313d2SEric Christopher  %continue = icmp sge i32 %i, %lowerlimit
286cee313d2SEric Christopher  br i1 %continue, label %loop, label %exit
287cee313d2SEric Christopher
288cee313d2SEric Christopherexit:
289cee313d2SEric Christopher  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
290cee313d2SEric Christopher  ret i32 %result
291cee313d2SEric Christopher}
292cee313d2SEric Christopher
293ba89c667SNikita Popovdefine i32 @unsigned_reverse_loop_n_to_lower_limit_equal(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) {
294cee313d2SEric Christopher; CHECK-LABEL: @unsigned_reverse_loop_n_to_lower_limit_equal(
295cee313d2SEric Christopher; CHECK-NEXT:  entry:
296cee313d2SEric Christopher; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
297cee313d2SEric Christopher; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
298cee313d2SEric Christopher; CHECK:       loop.preheader:
299cee313d2SEric Christopher; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N]], -1
300cee313d2SEric Christopher; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
301cee313d2SEric Christopher; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[LOWERLIMIT:%.*]], 1
302cee313d2SEric Christopher; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]]
303*99da3173SSerguei Katkov; CHECK-NEXT:    [[TMP4:%.*]] = freeze i1 [[TMP3]]
304cee313d2SEric Christopher; CHECK-NEXT:    br label [[LOOP:%.*]]
305cee313d2SEric Christopher; CHECK:       loop:
306cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
307cee313d2SEric Christopher; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
308cee313d2SEric Christopher; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], -1
3098307f6c8SDmitry Makogon; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]]
310*99da3173SSerguei Katkov; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ]
3118307f6c8SDmitry Makogon; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
312cee313d2SEric Christopher; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
313ba89c667SNikita Popov; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
314ba89c667SNikita Popov; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
315cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
316cee313d2SEric Christopher; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp uge i32 [[I]], [[LOWERLIMIT]]
317cee313d2SEric Christopher; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
318cee313d2SEric Christopher; CHECK:       exit.loopexit:
319cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
320cee313d2SEric Christopher; CHECK-NEXT:    br label [[EXIT]]
321cee313d2SEric Christopher; CHECK:       exit:
322cee313d2SEric Christopher; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
323cee313d2SEric Christopher; CHECK-NEXT:    ret i32 [[RESULT]]
324cee313d2SEric Christopher;
325cee313d2SEric Christopherentry:
326cee313d2SEric Christopher  %tmp5 = icmp eq i32 %n, 0
327cee313d2SEric Christopher  br i1 %tmp5, label %exit, label %loop.preheader
328cee313d2SEric Christopher
329cee313d2SEric Christopherloop.preheader:
330cee313d2SEric Christopher  br label %loop
331cee313d2SEric Christopher
332cee313d2SEric Christopherloop:
333cee313d2SEric Christopher  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
334cee313d2SEric Christopher  %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
335cee313d2SEric Christopher  %i.next = add nsw i32 %i, -1
336cee313d2SEric Christopher  %within.bounds = icmp ult i32 %i.next, %length
337cee313d2SEric Christopher  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
338cee313d2SEric Christopher  %i.i64 = zext i32 %i.next to i64
339ba89c667SNikita Popov  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
340ba89c667SNikita Popov  %array.i = load i32, ptr %array.i.ptr, align 4
341cee313d2SEric Christopher  %loop.acc.next = add i32 %loop.acc, %array.i
342cee313d2SEric Christopher  %continue = icmp uge i32 %i, %lowerlimit
343cee313d2SEric Christopher  br i1 %continue, label %loop, label %exit
344cee313d2SEric Christopher
345cee313d2SEric Christopherexit:
346cee313d2SEric Christopher  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
347cee313d2SEric Christopher  ret i32 %result
348cee313d2SEric Christopher}
349cee313d2SEric Christopher
350cee313d2SEric Christopher
351cee313d2SEric Christopher; if we predicated the loop, the guard will definitely fail and we will
352cee313d2SEric Christopher; deoptimize early on.
353ba89c667SNikita Popovdefine i32 @unsigned_reverse_loop_n_to_1(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) {
354cee313d2SEric Christopher; CHECK-LABEL: @unsigned_reverse_loop_n_to_1(
355cee313d2SEric Christopher; CHECK-NEXT:  entry:
356cee313d2SEric Christopher; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
357cee313d2SEric Christopher; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
358cee313d2SEric Christopher; CHECK:       loop.preheader:
359cee313d2SEric Christopher; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N]], -1
360cee313d2SEric Christopher; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
361b2915971SRoman Lebedev; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], false
362*99da3173SSerguei Katkov; CHECK-NEXT:    [[TMP3:%.*]] = freeze i1 [[TMP2]]
363cee313d2SEric Christopher; CHECK-NEXT:    br label [[LOOP:%.*]]
364cee313d2SEric Christopher; CHECK:       loop:
365cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
366cee313d2SEric Christopher; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
367cee313d2SEric Christopher; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], -1
3688307f6c8SDmitry Makogon; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]]
369*99da3173SSerguei Katkov; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
3708307f6c8SDmitry Makogon; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
371cee313d2SEric Christopher; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
372ba89c667SNikita Popov; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
373ba89c667SNikita Popov; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
374cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
375cee313d2SEric Christopher; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp uge i32 [[I]], 1
376cee313d2SEric Christopher; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
377cee313d2SEric Christopher; CHECK:       exit.loopexit:
378cee313d2SEric Christopher; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
379cee313d2SEric Christopher; CHECK-NEXT:    br label [[EXIT]]
380cee313d2SEric Christopher; CHECK:       exit:
381cee313d2SEric Christopher; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
382cee313d2SEric Christopher; CHECK-NEXT:    ret i32 [[RESULT]]
383cee313d2SEric Christopher;
384cee313d2SEric Christopherentry:
385cee313d2SEric Christopher  %tmp5 = icmp eq i32 %n, 0
386cee313d2SEric Christopher  br i1 %tmp5, label %exit, label %loop.preheader
387cee313d2SEric Christopher
388cee313d2SEric Christopherloop.preheader:
389cee313d2SEric Christopher  br label %loop
390cee313d2SEric Christopher
391cee313d2SEric Christopherloop:
392cee313d2SEric Christopher  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
393cee313d2SEric Christopher  %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
394cee313d2SEric Christopher  %i.next = add nsw i32 %i, -1
395cee313d2SEric Christopher  %within.bounds = icmp ult i32 %i.next, %length
396cee313d2SEric Christopher  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
397cee313d2SEric Christopher  %i.i64 = zext i32 %i.next to i64
398ba89c667SNikita Popov  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
399ba89c667SNikita Popov  %array.i = load i32, ptr %array.i.ptr, align 4
400cee313d2SEric Christopher  %loop.acc.next = add i32 %loop.acc, %array.i
401cee313d2SEric Christopher  %continue = icmp uge i32 %i, 1
402cee313d2SEric Christopher  br i1 %continue, label %loop, label %exit
403cee313d2SEric Christopher
404cee313d2SEric Christopherexit:
405cee313d2SEric Christopher  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
406cee313d2SEric Christopher  ret i32 %result
407cee313d2SEric Christopher}
408cee313d2SEric Christopher
409