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