xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/monotonic-pointer-phis-early-exits.ll (revision e6a1657fa30c747f4412fc47f567660ebe861a9e)
1cbacab26SFlorian Hahn; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2cbacab26SFlorian Hahn; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
3cbacab26SFlorian Hahn
4cbacab26SFlorian Hahntarget datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
5cbacab26SFlorian Hahn
6cbacab26SFlorian Hahn
7cbacab26SFlorian Hahndeclare void @use(ptr)
8cbacab26SFlorian Hahndeclare void @use.i1(i1)
9cbacab26SFlorian Hahndeclare void @llvm.assume(i1)
10cbacab26SFlorian Hahndeclare i1 @cond()
11cbacab26SFlorian Hahn
12cbacab26SFlorian Hahndefine void @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit(ptr %start, i16 %len) {
13cbacab26SFlorian Hahn; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit(
14cbacab26SFlorian Hahn; CHECK-NEXT:  entry:
15cbacab26SFlorian Hahn; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
16cbacab26SFlorian Hahn; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
17cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
18cbacab26SFlorian Hahn; CHECK:       loop.ph:
19cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
20cbacab26SFlorian Hahn; CHECK:       loop.header:
21cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
22cbacab26SFlorian Hahn; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
23cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
24cbacab26SFlorian Hahn; CHECK:       for.body:
25cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
26cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
27cbacab26SFlorian Hahn; CHECK:       loop.next:
28*e6a1657fSFlorian Hahn; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
29cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
30cbacab26SFlorian Hahn; CHECK:       loop.latch:
31cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
32cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
33cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER]]
34cbacab26SFlorian Hahn; CHECK:       exit:
35cbacab26SFlorian Hahn; CHECK-NEXT:    ret void
36cbacab26SFlorian Hahn;
37cbacab26SFlorian Hahnentry:
38cbacab26SFlorian Hahn  %upper = getelementptr inbounds i32, ptr %start, i16 %len
39cbacab26SFlorian Hahn  %len.neg = icmp slt i16 %len, 0
40cbacab26SFlorian Hahn  br i1 %len.neg, label %exit, label %loop.ph
41cbacab26SFlorian Hahn
42cbacab26SFlorian Hahnloop.ph:
43cbacab26SFlorian Hahn  br label %loop.header
44cbacab26SFlorian Hahn
45cbacab26SFlorian Hahnloop.header:
46cbacab26SFlorian Hahn  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
47cbacab26SFlorian Hahn  %c = icmp eq ptr %ptr.iv, %upper
48cbacab26SFlorian Hahn  br i1 %c, label %exit, label %for.body
49cbacab26SFlorian Hahn
50cbacab26SFlorian Hahnfor.body:
51cbacab26SFlorian Hahn  %c.1 = call i1 @cond()
52cbacab26SFlorian Hahn  br i1 %c.1, label %loop.next, label %exit
53cbacab26SFlorian Hahn
54cbacab26SFlorian Hahnloop.next:
55cbacab26SFlorian Hahn  %t.1 = icmp uge ptr %ptr.iv, %start
56cbacab26SFlorian Hahn  %t.2 = icmp ult ptr %ptr.iv, %upper
57cbacab26SFlorian Hahn  %and = and i1 %t.1, %t.2
58cbacab26SFlorian Hahn  br i1 %and, label %loop.latch, label %exit
59cbacab26SFlorian Hahn
60cbacab26SFlorian Hahnloop.latch:
61cbacab26SFlorian Hahn  call void @use(ptr %ptr.iv)
62cbacab26SFlorian Hahn  %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
63cbacab26SFlorian Hahn  br label %loop.header
64cbacab26SFlorian Hahn
65cbacab26SFlorian Hahnexit:
66cbacab26SFlorian Hahn  ret void
67cbacab26SFlorian Hahn}
68cbacab26SFlorian Hahn
69cbacab26SFlorian Hahndefine void @test_monotonic_ptr_iv_inc_2_different_element_types_1_with_early_exit(ptr %start, i16 %len) {
70cbacab26SFlorian Hahn; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_different_element_types_1_with_early_exit(
71cbacab26SFlorian Hahn; CHECK-NEXT:  entry:
72cbacab26SFlorian Hahn; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i16 [[LEN:%.*]]
73cbacab26SFlorian Hahn; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
74cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
75cbacab26SFlorian Hahn; CHECK:       loop.ph:
76cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
77cbacab26SFlorian Hahn; CHECK:       loop.header:
78cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
79cbacab26SFlorian Hahn; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
80cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
81cbacab26SFlorian Hahn; CHECK:       for.body:
82cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
83cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
84cbacab26SFlorian Hahn; CHECK:       loop.next:
85cbacab26SFlorian Hahn; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
86*e6a1657fSFlorian Hahn; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
87cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
88cbacab26SFlorian Hahn; CHECK:       loop.latch:
89cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
90cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
91cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER]]
92cbacab26SFlorian Hahn; CHECK:       exit:
93cbacab26SFlorian Hahn; CHECK-NEXT:    ret void
94cbacab26SFlorian Hahn;
95cbacab26SFlorian Hahnentry:
96cbacab26SFlorian Hahn  %upper = getelementptr inbounds i8, ptr %start, i16 %len
97cbacab26SFlorian Hahn  %len.neg = icmp slt i16 %len, 0
98cbacab26SFlorian Hahn  br i1 %len.neg, label %exit, label %loop.ph
99cbacab26SFlorian Hahn
100cbacab26SFlorian Hahnloop.ph:
101cbacab26SFlorian Hahn  br label %loop.header
102cbacab26SFlorian Hahn
103cbacab26SFlorian Hahnloop.header:
104cbacab26SFlorian Hahn  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
105cbacab26SFlorian Hahn  %c = icmp eq ptr %ptr.iv, %upper
106cbacab26SFlorian Hahn  br i1 %c, label %exit, label %for.body
107cbacab26SFlorian Hahn
108cbacab26SFlorian Hahnfor.body:
109cbacab26SFlorian Hahn  %c.1 = call i1 @cond()
110cbacab26SFlorian Hahn  br i1 %c.1, label %loop.next, label %exit
111cbacab26SFlorian Hahn
112cbacab26SFlorian Hahnloop.next:
113cbacab26SFlorian Hahn  %t.1 = icmp uge ptr %ptr.iv, %start
114cbacab26SFlorian Hahn  %t.2 = icmp ult ptr %ptr.iv, %upper
115cbacab26SFlorian Hahn  %and = and i1 %t.1, %t.2
116cbacab26SFlorian Hahn  br i1 %and, label %loop.latch, label %exit
117cbacab26SFlorian Hahn
118cbacab26SFlorian Hahnloop.latch:
119cbacab26SFlorian Hahn  call void @use(ptr %ptr.iv)
120cbacab26SFlorian Hahn  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
121cbacab26SFlorian Hahn  br label %loop.header
122cbacab26SFlorian Hahn
123cbacab26SFlorian Hahnexit:
124cbacab26SFlorian Hahn  ret void
125cbacab26SFlorian Hahn}
126cbacab26SFlorian Hahn
127cbacab26SFlorian Hahndefine void @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr_with_early_exit(ptr %start, ptr %end) {
128cbacab26SFlorian Hahn; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr_with_early_exit(
129cbacab26SFlorian Hahn; CHECK-NEXT:  entry:
130cbacab26SFlorian Hahn; CHECK-NEXT:    [[START_ULT_END:%.*]] = icmp uge ptr [[START:%.*]], [[END:%.*]]
131cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[START_ULT_END]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
132cbacab26SFlorian Hahn; CHECK:       loop.ph:
133cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
134cbacab26SFlorian Hahn; CHECK:       loop.header:
135cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
136cbacab26SFlorian Hahn; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[END]]
137cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
138cbacab26SFlorian Hahn; CHECK:       for.body:
139cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
140cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
141cbacab26SFlorian Hahn; CHECK:       loop.next:
142*e6a1657fSFlorian Hahn; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
143cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
144cbacab26SFlorian Hahn; CHECK:       loop.latch:
145cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
146cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
147cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER]]
148cbacab26SFlorian Hahn; CHECK:       exit:
149cbacab26SFlorian Hahn; CHECK-NEXT:    ret void
150cbacab26SFlorian Hahn;
151cbacab26SFlorian Hahnentry:
152cbacab26SFlorian Hahn  %start.ult.end = icmp uge ptr %start, %end
153cbacab26SFlorian Hahn  br i1 %start.ult.end, label %exit, label %loop.ph
154cbacab26SFlorian Hahn
155cbacab26SFlorian Hahnloop.ph:
156cbacab26SFlorian Hahn  br label %loop.header
157cbacab26SFlorian Hahn
158cbacab26SFlorian Hahnloop.header:
159cbacab26SFlorian Hahn  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
160cbacab26SFlorian Hahn  %c = icmp eq ptr %ptr.iv, %end
161cbacab26SFlorian Hahn  br i1 %c, label %exit, label %for.body
162cbacab26SFlorian Hahn
163cbacab26SFlorian Hahnfor.body:
164cbacab26SFlorian Hahn  %c.1 = call i1 @cond()
165cbacab26SFlorian Hahn  br i1 %c.1, label %loop.next, label %exit
166cbacab26SFlorian Hahn
167cbacab26SFlorian Hahnloop.next:
168cbacab26SFlorian Hahn  %t.1 = icmp uge ptr %ptr.iv, %start
169cbacab26SFlorian Hahn  %t.2 = icmp ult ptr %ptr.iv, %end
170cbacab26SFlorian Hahn  %and = and i1 %t.1, %t.2
171cbacab26SFlorian Hahn  br i1 %and, label %loop.latch, label %exit
172cbacab26SFlorian Hahn
173cbacab26SFlorian Hahnloop.latch:
174cbacab26SFlorian Hahn  call void @use(ptr %ptr.iv)
175cbacab26SFlorian Hahn  %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
176cbacab26SFlorian Hahn  br label %loop.header
177cbacab26SFlorian Hahn
178cbacab26SFlorian Hahnexit:
179cbacab26SFlorian Hahn  ret void
180cbacab26SFlorian Hahn}
181cbacab26SFlorian Hahn
182cbacab26SFlorian Hahndefine void @test_monotonic_ptr_iv_inc_1_gep_step_size_i32_unknown_end_ptr_with_early_exit(ptr %start, ptr %end) {
183cbacab26SFlorian Hahn; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_gep_step_size_i32_unknown_end_ptr_with_early_exit(
184cbacab26SFlorian Hahn; CHECK-NEXT:  entry:
185cbacab26SFlorian Hahn; CHECK-NEXT:    [[START_ULT_END:%.*]] = icmp uge ptr [[START:%.*]], [[END:%.*]]
186cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[START_ULT_END]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
187cbacab26SFlorian Hahn; CHECK:       loop.ph:
188cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
189cbacab26SFlorian Hahn; CHECK:       loop.header:
190cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
191cbacab26SFlorian Hahn; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[END]]
192cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
193cbacab26SFlorian Hahn; CHECK:       for.body:
194cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
195cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
196cbacab26SFlorian Hahn; CHECK:       loop.next:
197cbacab26SFlorian Hahn; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[END]]
198*e6a1657fSFlorian Hahn; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
199cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
200cbacab26SFlorian Hahn; CHECK:       loop.latch:
201cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
202cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
203cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER]]
204cbacab26SFlorian Hahn; CHECK:       exit:
205cbacab26SFlorian Hahn; CHECK-NEXT:    ret void
206cbacab26SFlorian Hahn;
207cbacab26SFlorian Hahnentry:
208cbacab26SFlorian Hahn  %start.ult.end = icmp uge ptr %start, %end
209cbacab26SFlorian Hahn  br i1 %start.ult.end, label %exit, label %loop.ph
210cbacab26SFlorian Hahn
211cbacab26SFlorian Hahnloop.ph:
212cbacab26SFlorian Hahn  br label %loop.header
213cbacab26SFlorian Hahn
214cbacab26SFlorian Hahnloop.header:
215cbacab26SFlorian Hahn  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
216cbacab26SFlorian Hahn  %c = icmp eq ptr %ptr.iv, %end
217cbacab26SFlorian Hahn  br i1 %c, label %exit, label %for.body
218cbacab26SFlorian Hahn
219cbacab26SFlorian Hahnfor.body:
220cbacab26SFlorian Hahn  %c.1 = call i1 @cond()
221cbacab26SFlorian Hahn  br i1 %c.1, label %loop.next, label %exit
222cbacab26SFlorian Hahn
223cbacab26SFlorian Hahnloop.next:
224cbacab26SFlorian Hahn  %t.1 = icmp uge ptr %ptr.iv, %start
225cbacab26SFlorian Hahn  %t.2 = icmp ult ptr %ptr.iv, %end
226cbacab26SFlorian Hahn  %and = and i1 %t.1, %t.2
227cbacab26SFlorian Hahn  br i1 %and, label %loop.latch, label %exit
228cbacab26SFlorian Hahn
229cbacab26SFlorian Hahnloop.latch:
230cbacab26SFlorian Hahn  call void @use(ptr %ptr.iv)
231cbacab26SFlorian Hahn  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
232cbacab26SFlorian Hahn  br label %loop.header
233cbacab26SFlorian Hahn
234cbacab26SFlorian Hahnexit:
235cbacab26SFlorian Hahn  ret void
236cbacab26SFlorian Hahn}
237cbacab26SFlorian Hahn
238cbacab26SFlorian Hahndefine void @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit_and_different_upper(ptr %start, ptr %end, i16 %len) {
239cbacab26SFlorian Hahn; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit_and_different_upper(
240cbacab26SFlorian Hahn; CHECK-NEXT:  entry:
241cbacab26SFlorian Hahn; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[END:%.*]], i16 [[LEN:%.*]]
242cbacab26SFlorian Hahn; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
243cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
244cbacab26SFlorian Hahn; CHECK:       loop.ph:
245cbacab26SFlorian Hahn; CHECK-NEXT:    [[START_ULT_END:%.*]] = icmp ult ptr [[START:%.*]], [[UPPER]]
246cbacab26SFlorian Hahn; CHECK-NEXT:    call void @llvm.assume(i1 [[START_ULT_END]])
247cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
248cbacab26SFlorian Hahn; CHECK:       loop.header:
249cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
250cbacab26SFlorian Hahn; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
251cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
252cbacab26SFlorian Hahn; CHECK:       for.body:
253cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
254cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
255cbacab26SFlorian Hahn; CHECK:       loop.next:
256cbacab26SFlorian Hahn; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
257*e6a1657fSFlorian Hahn; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
258cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
259cbacab26SFlorian Hahn; CHECK:       loop.latch:
260cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
261cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
262cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER]]
263cbacab26SFlorian Hahn; CHECK:       exit:
264cbacab26SFlorian Hahn; CHECK-NEXT:    ret void
265cbacab26SFlorian Hahn;
266cbacab26SFlorian Hahnentry:
267cbacab26SFlorian Hahn  %upper = getelementptr inbounds i32, ptr %end, i16 %len
268cbacab26SFlorian Hahn  %len.neg = icmp slt i16 %len, 0
269cbacab26SFlorian Hahn  br i1 %len.neg, label %exit, label %loop.ph
270cbacab26SFlorian Hahn
271cbacab26SFlorian Hahnloop.ph:
272cbacab26SFlorian Hahn  %start.ult.end = icmp ult ptr %start, %upper
273cbacab26SFlorian Hahn  call void @llvm.assume(i1 %start.ult.end)
274cbacab26SFlorian Hahn  br label %loop.header
275cbacab26SFlorian Hahn
276cbacab26SFlorian Hahnloop.header:
277cbacab26SFlorian Hahn  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
278cbacab26SFlorian Hahn  %c = icmp eq ptr %ptr.iv, %upper
279cbacab26SFlorian Hahn  br i1 %c, label %exit, label %for.body
280cbacab26SFlorian Hahn
281cbacab26SFlorian Hahnfor.body:
282cbacab26SFlorian Hahn  %c.1 = call i1 @cond()
283cbacab26SFlorian Hahn  br i1 %c.1, label %loop.next, label %exit
284cbacab26SFlorian Hahn
285cbacab26SFlorian Hahnloop.next:
286cbacab26SFlorian Hahn  %t.1 = icmp uge ptr %ptr.iv, %start
287cbacab26SFlorian Hahn  %t.2 = icmp ult ptr %ptr.iv, %upper
288cbacab26SFlorian Hahn  %and = and i1 %t.1, %t.2
289cbacab26SFlorian Hahn  br i1 %and, label %loop.latch, label %exit
290cbacab26SFlorian Hahn
291cbacab26SFlorian Hahnloop.latch:
292cbacab26SFlorian Hahn  call void @use(ptr %ptr.iv)
293cbacab26SFlorian Hahn  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
294cbacab26SFlorian Hahn  br label %loop.header
295cbacab26SFlorian Hahn
296cbacab26SFlorian Hahnexit:
297cbacab26SFlorian Hahn  ret void
298cbacab26SFlorian Hahn}
299cbacab26SFlorian Hahn
300cbacab26SFlorian Hahndefine void @test_monotonic_ptr_iv_step_sign_positive_through_assume_multi_exit(ptr %start, i16 %len, i16 %step) {
301cbacab26SFlorian Hahn; CHECK-LABEL: @test_monotonic_ptr_iv_step_sign_positive_through_assume_multi_exit(
302cbacab26SFlorian Hahn; CHECK-NEXT:  entry:
303cbacab26SFlorian Hahn; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0
304cbacab26SFlorian Hahn; CHECK-NEXT:    call void @llvm.assume(i1 [[STEP_POS]])
305cbacab26SFlorian Hahn; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
306cbacab26SFlorian Hahn; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
307cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
308cbacab26SFlorian Hahn; CHECK:       loop.ph:
309cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
310cbacab26SFlorian Hahn; CHECK:       loop.header:
311cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
312cbacab26SFlorian Hahn; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
313cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
314cbacab26SFlorian Hahn; CHECK:       for.body:
315cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
316cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[EXIT]]
317cbacab26SFlorian Hahn; CHECK:       then:
318cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
319cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
320cbacab26SFlorian Hahn; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
321cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
322cbacab26SFlorian Hahn; CHECK:       loop.latch:
323cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
324cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP]]
325cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER]]
326cbacab26SFlorian Hahn; CHECK:       exit:
327cbacab26SFlorian Hahn; CHECK-NEXT:    ret void
328cbacab26SFlorian Hahn;
329cbacab26SFlorian Hahnentry:
330cbacab26SFlorian Hahn  %step.pos = icmp sge i16 %step, 0
331cbacab26SFlorian Hahn  call void @llvm.assume(i1 %step.pos)
332cbacab26SFlorian Hahn  %upper = getelementptr inbounds i32, ptr %start, i16 %len
333cbacab26SFlorian Hahn  %len.neg = icmp slt i16 %len, 0
334cbacab26SFlorian Hahn  br i1 %len.neg, label %exit, label %loop.ph
335cbacab26SFlorian Hahn
336cbacab26SFlorian Hahnloop.ph:
337cbacab26SFlorian Hahn  br label %loop.header
338cbacab26SFlorian Hahn
339cbacab26SFlorian Hahnloop.header:
340cbacab26SFlorian Hahn  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
341cbacab26SFlorian Hahn  %c = icmp eq ptr %ptr.iv, %upper
342cbacab26SFlorian Hahn  br i1 %c, label %exit, label %for.body
343cbacab26SFlorian Hahn
344cbacab26SFlorian Hahnfor.body:
345cbacab26SFlorian Hahn  %c.1 = call i1 @cond()
346cbacab26SFlorian Hahn  br i1 %c.1, label %then, label %exit
347cbacab26SFlorian Hahn
348cbacab26SFlorian Hahnthen:
349cbacab26SFlorian Hahn  %c.2 = icmp uge ptr %ptr.iv, %start
350cbacab26SFlorian Hahn  %c.3 = icmp ult ptr %ptr.iv, %upper
351cbacab26SFlorian Hahn  %and = and i1 %c.2, %c.3
352cbacab26SFlorian Hahn  br i1 %and, label %loop.latch, label %exit
353cbacab26SFlorian Hahn
354cbacab26SFlorian Hahnloop.latch:
355cbacab26SFlorian Hahn  call void @use(ptr %ptr.iv)
356cbacab26SFlorian Hahn  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 %step
357cbacab26SFlorian Hahn  br label %loop.header
358cbacab26SFlorian Hahn
359cbacab26SFlorian Hahnexit:
360cbacab26SFlorian Hahn  ret void
361cbacab26SFlorian Hahn}
362cbacab26SFlorian Hahn
363cbacab26SFlorian Hahndefine void @test_monotonic_ptr_iv_cond_doesnt_control_exit(ptr %start, i16 %len) {
364cbacab26SFlorian Hahn; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_control_exit(
365cbacab26SFlorian Hahn; CHECK-NEXT:  entry:
366cbacab26SFlorian Hahn; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
367cbacab26SFlorian Hahn; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
368cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
369cbacab26SFlorian Hahn; CHECK:       loop.ph:
370cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
371cbacab26SFlorian Hahn; CHECK:       loop.header:
372cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
373cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
374cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
375cbacab26SFlorian Hahn; CHECK:       for.body:
376cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
377cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
378cbacab26SFlorian Hahn; CHECK:       then:
379cbacab26SFlorian Hahn; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
380cbacab26SFlorian Hahn; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
381cbacab26SFlorian Hahn; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
382cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
383cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_LATCH]]
384cbacab26SFlorian Hahn; CHECK:       loop.latch:
385cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
386cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
387cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER]]
388cbacab26SFlorian Hahn; CHECK:       exit:
389cbacab26SFlorian Hahn; CHECK-NEXT:    ret void
390cbacab26SFlorian Hahn;
391cbacab26SFlorian Hahnentry:
392cbacab26SFlorian Hahn  %upper = getelementptr inbounds i32, ptr %start, i16 %len
393cbacab26SFlorian Hahn  %len.neg = icmp slt i16 %len, 0
394cbacab26SFlorian Hahn  br i1 %len.neg, label %exit, label %loop.ph
395cbacab26SFlorian Hahn
396cbacab26SFlorian Hahnloop.ph:
397cbacab26SFlorian Hahn  br label %loop.header
398cbacab26SFlorian Hahn
399cbacab26SFlorian Hahnloop.header:
400cbacab26SFlorian Hahn  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
401cbacab26SFlorian Hahn  %c.0 = call i1 @cond()
402cbacab26SFlorian Hahn  br i1 %c.0, label %exit, label %for.body
403cbacab26SFlorian Hahn
404cbacab26SFlorian Hahnfor.body:
405cbacab26SFlorian Hahn  %c.1 = icmp ne ptr %ptr.iv, %upper
406cbacab26SFlorian Hahn  br i1 %c.1, label %then, label %loop.latch
407cbacab26SFlorian Hahn
408cbacab26SFlorian Hahnthen:
409cbacab26SFlorian Hahn  %t.1 = icmp uge ptr %ptr.iv, %start
410cbacab26SFlorian Hahn  %t.2 = icmp ult ptr %ptr.iv, %upper
411cbacab26SFlorian Hahn  %and = and i1 %t.1, %t.2
412cbacab26SFlorian Hahn  call void @use.i1(i1 %and)
413cbacab26SFlorian Hahn  br label %loop.latch
414cbacab26SFlorian Hahn
415cbacab26SFlorian Hahnloop.latch:
416cbacab26SFlorian Hahn  call void @use(ptr %ptr.iv)
417cbacab26SFlorian Hahn  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
418cbacab26SFlorian Hahn  br label %loop.header
419cbacab26SFlorian Hahn
420cbacab26SFlorian Hahnexit:
421cbacab26SFlorian Hahn  ret void
422cbacab26SFlorian Hahn}
423cbacab26SFlorian Hahn
424cbacab26SFlorian Hahndefine void @test_monotonic_ptr_iv_cond_doesnt_control_exit2(ptr %start, i16 %len) {
425cbacab26SFlorian Hahn; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_control_exit2(
426cbacab26SFlorian Hahn; CHECK-NEXT:  entry:
427cbacab26SFlorian Hahn; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
428cbacab26SFlorian Hahn; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
429cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
430cbacab26SFlorian Hahn; CHECK:       loop.ph:
431cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
432cbacab26SFlorian Hahn; CHECK:       loop.header:
433cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
434cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
435cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[FOR_BODY:%.*]]
436cbacab26SFlorian Hahn; CHECK:       for.body:
437cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
438cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[LOOP_LATCH]]
439cbacab26SFlorian Hahn; CHECK:       then:
440cbacab26SFlorian Hahn; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
441cbacab26SFlorian Hahn; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
442cbacab26SFlorian Hahn; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
443cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
444cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_LATCH]]
445cbacab26SFlorian Hahn; CHECK:       loop.latch:
446cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
447cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
448cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER]]
449cbacab26SFlorian Hahn; CHECK:       exit:
450cbacab26SFlorian Hahn; CHECK-NEXT:    ret void
451cbacab26SFlorian Hahn;
452cbacab26SFlorian Hahnentry:
453cbacab26SFlorian Hahn  %upper = getelementptr inbounds i32, ptr %start, i16 %len
454cbacab26SFlorian Hahn  %len.neg = icmp slt i16 %len, 0
455cbacab26SFlorian Hahn  br i1 %len.neg, label %exit, label %loop.ph
456cbacab26SFlorian Hahn
457cbacab26SFlorian Hahnloop.ph:
458cbacab26SFlorian Hahn  br label %loop.header
459cbacab26SFlorian Hahn
460cbacab26SFlorian Hahnloop.header:
461cbacab26SFlorian Hahn  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
462cbacab26SFlorian Hahn  %c.1 = icmp ne ptr %ptr.iv, %upper
463cbacab26SFlorian Hahn  br i1 %c.1, label %then, label %for.body
464cbacab26SFlorian Hahn
465cbacab26SFlorian Hahnfor.body:
466cbacab26SFlorian Hahn  %c.0 = call i1 @cond()
467cbacab26SFlorian Hahn  br i1 %c.0, label %exit, label %loop.latch
468cbacab26SFlorian Hahn
469cbacab26SFlorian Hahnthen:
470cbacab26SFlorian Hahn  %t.1 = icmp uge ptr %ptr.iv, %start
471cbacab26SFlorian Hahn  %t.2 = icmp ult ptr %ptr.iv, %upper
472cbacab26SFlorian Hahn  %and = and i1 %t.1, %t.2
473cbacab26SFlorian Hahn  call void @use.i1(i1 %and)
474cbacab26SFlorian Hahn  br label %loop.latch
475cbacab26SFlorian Hahn
476cbacab26SFlorian Hahnloop.latch:
477cbacab26SFlorian Hahn  call void @use(ptr %ptr.iv)
478cbacab26SFlorian Hahn  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
479cbacab26SFlorian Hahn  br label %loop.header
480cbacab26SFlorian Hahn
481cbacab26SFlorian Hahnexit:
482cbacab26SFlorian Hahn  ret void
483cbacab26SFlorian Hahn}
484cbacab26SFlorian Hahn
485cbacab26SFlorian Hahndefine void @test_monotonic_ptr_iv_cond_doesnt_dominate_checks(ptr %start, i16 %len) {
486cbacab26SFlorian Hahn; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_dominate_checks(
487cbacab26SFlorian Hahn; CHECK-NEXT:  entry:
488cbacab26SFlorian Hahn; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
489cbacab26SFlorian Hahn; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
490cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
491cbacab26SFlorian Hahn; CHECK:       loop.ph:
492cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
493cbacab26SFlorian Hahn; CHECK:       loop.header:
494cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
495cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
496cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
497cbacab26SFlorian Hahn; CHECK:       for.body:
498cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
499cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
500cbacab26SFlorian Hahn; CHECK:       then:
501cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_LATCH]]
502cbacab26SFlorian Hahn; CHECK:       loop.latch:
503cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
504cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
505cbacab26SFlorian Hahn; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
506cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
507cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
508cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
509cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER]]
510cbacab26SFlorian Hahn; CHECK:       exit:
511cbacab26SFlorian Hahn; CHECK-NEXT:    ret void
512cbacab26SFlorian Hahn;
513cbacab26SFlorian Hahnentry:
514cbacab26SFlorian Hahn  %upper = getelementptr inbounds i32, ptr %start, i16 %len
515cbacab26SFlorian Hahn  %len.neg = icmp slt i16 %len, 0
516cbacab26SFlorian Hahn  br i1 %len.neg, label %exit, label %loop.ph
517cbacab26SFlorian Hahn
518cbacab26SFlorian Hahnloop.ph:
519cbacab26SFlorian Hahn  br label %loop.header
520cbacab26SFlorian Hahn
521cbacab26SFlorian Hahnloop.header:
522cbacab26SFlorian Hahn  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
523cbacab26SFlorian Hahn  %c.0 = call i1 @cond()
524cbacab26SFlorian Hahn  br i1 %c.0, label %exit, label %for.body
525cbacab26SFlorian Hahn
526cbacab26SFlorian Hahnfor.body:
527cbacab26SFlorian Hahn  %c.1 = icmp ne ptr %ptr.iv, %upper
528cbacab26SFlorian Hahn  br i1 %c.1, label %then, label %loop.latch
529cbacab26SFlorian Hahn
530cbacab26SFlorian Hahnthen:
531cbacab26SFlorian Hahn  br label %loop.latch
532cbacab26SFlorian Hahn
533cbacab26SFlorian Hahnloop.latch:
534cbacab26SFlorian Hahn  %c.2 = icmp uge ptr %ptr.iv, %start
535cbacab26SFlorian Hahn  %c.3 = icmp ult ptr %ptr.iv, %upper
536cbacab26SFlorian Hahn  %and = and i1 %c.2, %c.3
537cbacab26SFlorian Hahn  call void @use.i1(i1 %and)
538cbacab26SFlorian Hahn  call void @use(ptr %ptr.iv)
539cbacab26SFlorian Hahn  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
540cbacab26SFlorian Hahn  br label %loop.header
541cbacab26SFlorian Hahn
542cbacab26SFlorian Hahnexit:
543cbacab26SFlorian Hahn  ret void
544cbacab26SFlorian Hahn}
545cbacab26SFlorian Hahn
546cbacab26SFlorian Hahndefine void @test_monotonic_ptr_iv_step_2_multi_exit(ptr %start, i16 %len) {
547cbacab26SFlorian Hahn; CHECK-LABEL: @test_monotonic_ptr_iv_step_2_multi_exit(
548cbacab26SFlorian Hahn; CHECK-NEXT:  entry:
549cbacab26SFlorian Hahn; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
550cbacab26SFlorian Hahn; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
551cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
552cbacab26SFlorian Hahn; CHECK:       loop.ph:
553cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
554cbacab26SFlorian Hahn; CHECK:       loop.header:
555cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
556cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_1:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
557cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_1]], label [[EXIT]], label [[FOR_BODY:%.*]]
558cbacab26SFlorian Hahn; CHECK:       for.body:
559cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
560cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[THEN:%.*]]
561cbacab26SFlorian Hahn; CHECK:       then:
562cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
563*e6a1657fSFlorian Hahn; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[C_3]]
564cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
565cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_LATCH]]
566cbacab26SFlorian Hahn; CHECK:       loop.latch:
567cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
568cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 2
569cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER]]
570cbacab26SFlorian Hahn; CHECK:       exit:
571cbacab26SFlorian Hahn; CHECK-NEXT:    ret void
572cbacab26SFlorian Hahn;
573cbacab26SFlorian Hahnentry:
574cbacab26SFlorian Hahn  %upper = getelementptr inbounds i32, ptr %start, i16 %len
575cbacab26SFlorian Hahn  %len.neg = icmp slt i16 %len, 0
576cbacab26SFlorian Hahn  br i1 %len.neg, label %exit, label %loop.ph
577cbacab26SFlorian Hahn
578cbacab26SFlorian Hahnloop.ph:
579cbacab26SFlorian Hahn  br label %loop.header
580cbacab26SFlorian Hahn
581cbacab26SFlorian Hahnloop.header:
582cbacab26SFlorian Hahn  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
583cbacab26SFlorian Hahn  %c.1 = icmp eq ptr %ptr.iv, %upper
584cbacab26SFlorian Hahn  br i1 %c.1, label %exit, label %for.body
585cbacab26SFlorian Hahn
586cbacab26SFlorian Hahnfor.body:
587cbacab26SFlorian Hahn  %c.0 = call i1 @cond()
588cbacab26SFlorian Hahn  br i1 %c.0, label %exit, label %then
589cbacab26SFlorian Hahn
590cbacab26SFlorian Hahnthen:
591cbacab26SFlorian Hahn  %c.2 = icmp uge ptr %ptr.iv, %start
592cbacab26SFlorian Hahn  %c.3 = icmp ult ptr %ptr.iv, %upper
593cbacab26SFlorian Hahn  %and = and i1 %c.2, %c.3
594cbacab26SFlorian Hahn  call void @use.i1(i1 %and)
595cbacab26SFlorian Hahn  br label %loop.latch
596cbacab26SFlorian Hahn
597cbacab26SFlorian Hahnloop.latch:
598cbacab26SFlorian Hahn  call void @use(ptr %ptr.iv)
599cbacab26SFlorian Hahn  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 2
600cbacab26SFlorian Hahn  br label %loop.header
601cbacab26SFlorian Hahn
602cbacab26SFlorian Hahnexit:
603cbacab26SFlorian Hahn  ret void
604cbacab26SFlorian Hahn}
605cbacab26SFlorian Hahn
606cbacab26SFlorian Hahndefine void @test_monotonic_ptr_iv_step_2_cond_doesnt_control_exit(ptr %start, i16 %len) {
607cbacab26SFlorian Hahn; CHECK-LABEL: @test_monotonic_ptr_iv_step_2_cond_doesnt_control_exit(
608cbacab26SFlorian Hahn; CHECK-NEXT:  entry:
609cbacab26SFlorian Hahn; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
610cbacab26SFlorian Hahn; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
611cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
612cbacab26SFlorian Hahn; CHECK:       loop.ph:
613cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
614cbacab26SFlorian Hahn; CHECK:       loop.header:
615cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
616cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
617cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
618cbacab26SFlorian Hahn; CHECK:       for.body:
619cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
620cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
621cbacab26SFlorian Hahn; CHECK:       then:
622cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
623cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
624cbacab26SFlorian Hahn; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
625cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
626cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_LATCH]]
627cbacab26SFlorian Hahn; CHECK:       loop.latch:
628cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
629cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 2
630cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER]]
631cbacab26SFlorian Hahn; CHECK:       exit:
632cbacab26SFlorian Hahn; CHECK-NEXT:    ret void
633cbacab26SFlorian Hahn;
634cbacab26SFlorian Hahnentry:
635cbacab26SFlorian Hahn  %upper = getelementptr inbounds i32, ptr %start, i16 %len
636cbacab26SFlorian Hahn  %len.neg = icmp slt i16 %len, 0
637cbacab26SFlorian Hahn  br i1 %len.neg, label %exit, label %loop.ph
638cbacab26SFlorian Hahn
639cbacab26SFlorian Hahnloop.ph:
640cbacab26SFlorian Hahn  br label %loop.header
641cbacab26SFlorian Hahn
642cbacab26SFlorian Hahnloop.header:
643cbacab26SFlorian Hahn  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
644cbacab26SFlorian Hahn  %c.0 = call i1 @cond()
645cbacab26SFlorian Hahn  br i1 %c.0, label %exit, label %for.body
646cbacab26SFlorian Hahn
647cbacab26SFlorian Hahnfor.body:
648cbacab26SFlorian Hahn  %c.1 = icmp ne ptr %ptr.iv, %upper
649cbacab26SFlorian Hahn  br i1 %c.1, label %then, label %loop.latch
650cbacab26SFlorian Hahn
651cbacab26SFlorian Hahnthen:
652cbacab26SFlorian Hahn  %c.2 = icmp uge ptr %ptr.iv, %start
653cbacab26SFlorian Hahn  %c.3 = icmp ult ptr %ptr.iv, %upper
654cbacab26SFlorian Hahn  %and = and i1 %c.2, %c.3
655cbacab26SFlorian Hahn  call void @use.i1(i1 %and)
656cbacab26SFlorian Hahn  br label %loop.latch
657cbacab26SFlorian Hahn
658cbacab26SFlorian Hahnloop.latch:
659cbacab26SFlorian Hahn  call void @use(ptr %ptr.iv)
660cbacab26SFlorian Hahn  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 2
661cbacab26SFlorian Hahn  br label %loop.header
662cbacab26SFlorian Hahn
663cbacab26SFlorian Hahnexit:
664cbacab26SFlorian Hahn  ret void
665cbacab26SFlorian Hahn}
666cbacab26SFlorian Hahn
667e1e7b019SFlorian Hahndefine void @test_monotonic_ptr_iv_step_64_cond_doesnt_control_exit(ptr %start, i16 %len) {
668e1e7b019SFlorian Hahn; CHECK-LABEL: @test_monotonic_ptr_iv_step_64_cond_doesnt_control_exit(
669e1e7b019SFlorian Hahn; CHECK-NEXT:  entry:
670e1e7b019SFlorian Hahn; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i64, ptr [[START:%.*]], i16 [[LEN:%.*]]
671e1e7b019SFlorian Hahn; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
672e1e7b019SFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
673e1e7b019SFlorian Hahn; CHECK:       loop.ph:
674e1e7b019SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
675e1e7b019SFlorian Hahn; CHECK:       loop.header:
676e1e7b019SFlorian Hahn; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
677e1e7b019SFlorian Hahn; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
678e1e7b019SFlorian Hahn; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
679e1e7b019SFlorian Hahn; CHECK:       for.body:
680e1e7b019SFlorian Hahn; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
681e1e7b019SFlorian Hahn; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
682e1e7b019SFlorian Hahn; CHECK:       then:
683e1e7b019SFlorian Hahn; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
684e1e7b019SFlorian Hahn; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
685e1e7b019SFlorian Hahn; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
686e1e7b019SFlorian Hahn; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
687e1e7b019SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_LATCH]]
688e1e7b019SFlorian Hahn; CHECK:       loop.latch:
689e1e7b019SFlorian Hahn; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
690e1e7b019SFlorian Hahn; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 4
691e1e7b019SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER]]
692e1e7b019SFlorian Hahn; CHECK:       exit:
693e1e7b019SFlorian Hahn; CHECK-NEXT:    ret void
694e1e7b019SFlorian Hahn;
695e1e7b019SFlorian Hahnentry:
696e1e7b019SFlorian Hahn  %upper = getelementptr inbounds i64, ptr %start, i16 %len
697e1e7b019SFlorian Hahn  %len.neg = icmp slt i16 %len, 0
698e1e7b019SFlorian Hahn  br i1 %len.neg, label %exit, label %loop.ph
699e1e7b019SFlorian Hahn
700e1e7b019SFlorian Hahnloop.ph:
701e1e7b019SFlorian Hahn  br label %loop.header
702e1e7b019SFlorian Hahn
703e1e7b019SFlorian Hahnloop.header:
704e1e7b019SFlorian Hahn  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
705e1e7b019SFlorian Hahn  %c.0 = call i1 @cond()
706e1e7b019SFlorian Hahn  br i1 %c.0, label %exit, label %for.body
707e1e7b019SFlorian Hahn
708e1e7b019SFlorian Hahnfor.body:
709e1e7b019SFlorian Hahn  %c.1 = icmp ne ptr %ptr.iv, %upper
710e1e7b019SFlorian Hahn  br i1 %c.1, label %then, label %loop.latch
711e1e7b019SFlorian Hahn
712e1e7b019SFlorian Hahnthen:
713e1e7b019SFlorian Hahn  %c.2 = icmp uge ptr %ptr.iv, %start
714e1e7b019SFlorian Hahn  %c.3 = icmp ult ptr %ptr.iv, %upper
715e1e7b019SFlorian Hahn  %and = and i1 %c.2, %c.3
716e1e7b019SFlorian Hahn  call void @use.i1(i1 %and)
717e1e7b019SFlorian Hahn  br label %loop.latch
718e1e7b019SFlorian Hahn
719e1e7b019SFlorian Hahnloop.latch:
720e1e7b019SFlorian Hahn  call void @use(ptr %ptr.iv)
721e1e7b019SFlorian Hahn  %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 4
722e1e7b019SFlorian Hahn  br label %loop.header
723e1e7b019SFlorian Hahn
724e1e7b019SFlorian Hahnexit:
725e1e7b019SFlorian Hahn  ret void
726e1e7b019SFlorian Hahn}
727e1e7b019SFlorian Hahn
728e1e7b019SFlorian Hahndefine void @test_monotonic_ptr_iv_step_80_cond_doesnt_control_exit(ptr %start, i16 %len) {
729e1e7b019SFlorian Hahn; CHECK-LABEL: @test_monotonic_ptr_iv_step_80_cond_doesnt_control_exit(
730e1e7b019SFlorian Hahn; CHECK-NEXT:  entry:
731e1e7b019SFlorian Hahn; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i64, ptr [[START:%.*]], i16 [[LEN:%.*]]
732e1e7b019SFlorian Hahn; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
733e1e7b019SFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
734e1e7b019SFlorian Hahn; CHECK:       loop.ph:
735e1e7b019SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
736e1e7b019SFlorian Hahn; CHECK:       loop.header:
737e1e7b019SFlorian Hahn; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
738e1e7b019SFlorian Hahn; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
739e1e7b019SFlorian Hahn; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
740e1e7b019SFlorian Hahn; CHECK:       for.body:
741e1e7b019SFlorian Hahn; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
742e1e7b019SFlorian Hahn; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
743e1e7b019SFlorian Hahn; CHECK:       then:
744e1e7b019SFlorian Hahn; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
745e1e7b019SFlorian Hahn; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
746e1e7b019SFlorian Hahn; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
747e1e7b019SFlorian Hahn; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
748e1e7b019SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_LATCH]]
749e1e7b019SFlorian Hahn; CHECK:       loop.latch:
750e1e7b019SFlorian Hahn; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
751e1e7b019SFlorian Hahn; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 5
752e1e7b019SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER]]
753e1e7b019SFlorian Hahn; CHECK:       exit:
754e1e7b019SFlorian Hahn; CHECK-NEXT:    ret void
755e1e7b019SFlorian Hahn;
756e1e7b019SFlorian Hahnentry:
757e1e7b019SFlorian Hahn  %upper = getelementptr inbounds i64, ptr %start, i16 %len
758e1e7b019SFlorian Hahn  %len.neg = icmp slt i16 %len, 0
759e1e7b019SFlorian Hahn  br i1 %len.neg, label %exit, label %loop.ph
760e1e7b019SFlorian Hahn
761e1e7b019SFlorian Hahnloop.ph:
762e1e7b019SFlorian Hahn  br label %loop.header
763e1e7b019SFlorian Hahn
764e1e7b019SFlorian Hahnloop.header:
765e1e7b019SFlorian Hahn  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
766e1e7b019SFlorian Hahn  %c.0 = call i1 @cond()
767e1e7b019SFlorian Hahn  br i1 %c.0, label %exit, label %for.body
768e1e7b019SFlorian Hahn
769e1e7b019SFlorian Hahnfor.body:
770e1e7b019SFlorian Hahn  %c.1 = icmp ne ptr %ptr.iv, %upper
771e1e7b019SFlorian Hahn  br i1 %c.1, label %then, label %loop.latch
772e1e7b019SFlorian Hahn
773e1e7b019SFlorian Hahnthen:
774e1e7b019SFlorian Hahn  %c.2 = icmp uge ptr %ptr.iv, %start
775e1e7b019SFlorian Hahn  %c.3 = icmp ult ptr %ptr.iv, %upper
776e1e7b019SFlorian Hahn  %and = and i1 %c.2, %c.3
777e1e7b019SFlorian Hahn  call void @use.i1(i1 %and)
778e1e7b019SFlorian Hahn  br label %loop.latch
779e1e7b019SFlorian Hahn
780e1e7b019SFlorian Hahnloop.latch:
781e1e7b019SFlorian Hahn  call void @use(ptr %ptr.iv)
782e1e7b019SFlorian Hahn  %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 5
783e1e7b019SFlorian Hahn  br label %loop.header
784e1e7b019SFlorian Hahn
785e1e7b019SFlorian Hahnexit:
786e1e7b019SFlorian Hahn  ret void
787e1e7b019SFlorian Hahn}
788cbacab26SFlorian Hahn
789cbacab26SFlorian Hahndefine void @test_monotonic_ptr_iv_inc_1_check_outside_loop(ptr %start, i16 %len) {
790cbacab26SFlorian Hahn; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_check_outside_loop(
791cbacab26SFlorian Hahn; CHECK-NEXT:  entry:
792cbacab26SFlorian Hahn; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
793cbacab26SFlorian Hahn; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp sge i16 [[LEN]], 0
794cbacab26SFlorian Hahn; CHECK-NEXT:    call void @llvm.assume(i1 [[LEN_NEG]])
795cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_PH:%.*]]
796cbacab26SFlorian Hahn; CHECK:       loop.ph:
797cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
798cbacab26SFlorian Hahn; CHECK:       loop.header:
799cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
800cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
801cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
802cbacab26SFlorian Hahn; CHECK:       loop.latch:
803cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
804cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
805cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER]]
806cbacab26SFlorian Hahn; CHECK:       exit:
807cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
808cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[EXIT_2:%.*]]
809cbacab26SFlorian Hahn; CHECK:       then:
810cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
811cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
812cbacab26SFlorian Hahn; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
813cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
814cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[EXIT_2]]
815cbacab26SFlorian Hahn; CHECK:       exit.2:
816cbacab26SFlorian Hahn; CHECK-NEXT:    ret void
817cbacab26SFlorian Hahn;
818cbacab26SFlorian Hahnentry:
819cbacab26SFlorian Hahn  %upper = getelementptr inbounds i32, ptr %start, i16 %len
820cbacab26SFlorian Hahn  %len.neg = icmp sge i16 %len, 0
821cbacab26SFlorian Hahn  call void @llvm.assume(i1 %len.neg)
822cbacab26SFlorian Hahn  br label %loop.ph
823cbacab26SFlorian Hahn
824cbacab26SFlorian Hahnloop.ph:
825cbacab26SFlorian Hahn  br label %loop.header
826cbacab26SFlorian Hahn
827cbacab26SFlorian Hahnloop.header:
828cbacab26SFlorian Hahn  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
829cbacab26SFlorian Hahn  %c.0 = call i1 @cond()
830cbacab26SFlorian Hahn  br i1 %c.0, label %exit, label %loop.latch
831cbacab26SFlorian Hahn
832cbacab26SFlorian Hahnloop.latch:
833cbacab26SFlorian Hahn  call void @use(ptr %ptr.iv)
834cbacab26SFlorian Hahn  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
835cbacab26SFlorian Hahn  br label %loop.header
836cbacab26SFlorian Hahn
837cbacab26SFlorian Hahnexit:
838cbacab26SFlorian Hahn  %c.1 = icmp ne ptr %ptr.iv, %upper
839cbacab26SFlorian Hahn  br i1 %c.1, label %then, label %exit.2
840cbacab26SFlorian Hahn
841cbacab26SFlorian Hahnthen:
842cbacab26SFlorian Hahn  %c.2 = icmp uge ptr %ptr.iv, %start
843cbacab26SFlorian Hahn  %c.3 = icmp ult ptr %ptr.iv, %upper
844cbacab26SFlorian Hahn  %and = and i1 %c.2, %c.3
845cbacab26SFlorian Hahn  call void @use.i1(i1 %and)
846cbacab26SFlorian Hahn  br label %exit.2
847cbacab26SFlorian Hahn
848cbacab26SFlorian Hahnexit.2:
849cbacab26SFlorian Hahn  ret void
850cbacab26SFlorian Hahn}
851cbacab26SFlorian Hahn
852cbacab26SFlorian Hahndefine void @test_step_gep_doesnt_use_ptr_iv_phi(ptr %start, ptr %other, i16 %len) {
853cbacab26SFlorian Hahn; CHECK-LABEL: @test_step_gep_doesnt_use_ptr_iv_phi(
854cbacab26SFlorian Hahn; CHECK-NEXT:  entry:
855cbacab26SFlorian Hahn; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds float, ptr [[START:%.*]], i16 [[LEN:%.*]]
856cbacab26SFlorian Hahn; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
857cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
858cbacab26SFlorian Hahn; CHECK:       loop.ph:
859cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
860cbacab26SFlorian Hahn; CHECK:       loop.header:
861cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
862cbacab26SFlorian Hahn; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
863cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
864cbacab26SFlorian Hahn; CHECK:       for.body:
865cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
866cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
867cbacab26SFlorian Hahn; CHECK:       loop.next:
868cbacab26SFlorian Hahn; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
869cbacab26SFlorian Hahn; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
870cbacab26SFlorian Hahn; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
871cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
872cbacab26SFlorian Hahn; CHECK:       loop.latch:
873cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
874cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds float, ptr [[OTHER:%.*]], i16 1
875cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER]]
876cbacab26SFlorian Hahn; CHECK:       exit:
877cbacab26SFlorian Hahn; CHECK-NEXT:    ret void
878cbacab26SFlorian Hahn;
879cbacab26SFlorian Hahnentry:
880cbacab26SFlorian Hahn  %upper = getelementptr inbounds float, ptr %start, i16 %len
881cbacab26SFlorian Hahn  %len.neg = icmp slt i16 %len, 0
882cbacab26SFlorian Hahn  br i1 %len.neg, label %exit, label %loop.ph
883cbacab26SFlorian Hahn
884cbacab26SFlorian Hahnloop.ph:
885cbacab26SFlorian Hahn  br label %loop.header
886cbacab26SFlorian Hahn
887cbacab26SFlorian Hahnloop.header:
888cbacab26SFlorian Hahn  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
889cbacab26SFlorian Hahn  %c = icmp eq ptr %ptr.iv, %upper
890cbacab26SFlorian Hahn  br i1 %c, label %exit, label %for.body
891cbacab26SFlorian Hahn
892cbacab26SFlorian Hahnfor.body:
893cbacab26SFlorian Hahn  %c.1 = call i1 @cond()
894cbacab26SFlorian Hahn  br i1 %c.1, label %loop.next, label %exit
895cbacab26SFlorian Hahn
896cbacab26SFlorian Hahnloop.next:
897cbacab26SFlorian Hahn  %t.1 = icmp uge ptr %ptr.iv, %start
898cbacab26SFlorian Hahn  %t.2 = icmp ult ptr %ptr.iv, %upper
899cbacab26SFlorian Hahn  %and = and i1 %t.1, %t.2
900cbacab26SFlorian Hahn  br i1 %and, label %loop.latch, label %exit
901cbacab26SFlorian Hahn
902cbacab26SFlorian Hahnloop.latch:
903cbacab26SFlorian Hahn  call void @use(ptr %ptr.iv)
904cbacab26SFlorian Hahn  %ptr.iv.next = getelementptr inbounds float, ptr %other, i16 1
905cbacab26SFlorian Hahn  br label %loop.header
906cbacab26SFlorian Hahn
907cbacab26SFlorian Hahnexit:
908cbacab26SFlorian Hahn  ret void
909cbacab26SFlorian Hahn}
910cbacab26SFlorian Hahn
911cbacab26SFlorian Hahndefine void @test_step_gep_not_inbounds(ptr %start, ptr %end, i16 %len) {
912cbacab26SFlorian Hahn; CHECK-LABEL: @test_step_gep_not_inbounds(
913cbacab26SFlorian Hahn; CHECK-NEXT:  entry:
914cbacab26SFlorian Hahn; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds float, ptr [[START:%.*]], i16 [[LEN:%.*]]
915cbacab26SFlorian Hahn; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
916cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
917cbacab26SFlorian Hahn; CHECK:       loop.ph:
918cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
919cbacab26SFlorian Hahn; CHECK:       loop.header:
920cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
921cbacab26SFlorian Hahn; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
922cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
923cbacab26SFlorian Hahn; CHECK:       for.body:
924cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
925cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
926cbacab26SFlorian Hahn; CHECK:       loop.next:
927*e6a1657fSFlorian Hahn; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
928cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
929cbacab26SFlorian Hahn; CHECK:       loop.latch:
930cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
931cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr float, ptr [[PTR_IV]], i16 1
932cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER]]
933cbacab26SFlorian Hahn; CHECK:       exit:
934cbacab26SFlorian Hahn; CHECK-NEXT:    ret void
935cbacab26SFlorian Hahn;
936cbacab26SFlorian Hahnentry:
937cbacab26SFlorian Hahn  %upper = getelementptr inbounds float, ptr %start, i16 %len
938cbacab26SFlorian Hahn  %len.neg = icmp slt i16 %len, 0
939cbacab26SFlorian Hahn  br i1 %len.neg, label %exit, label %loop.ph
940cbacab26SFlorian Hahn
941cbacab26SFlorian Hahnloop.ph:
942cbacab26SFlorian Hahn  br label %loop.header
943cbacab26SFlorian Hahn
944cbacab26SFlorian Hahnloop.header:
945cbacab26SFlorian Hahn  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
946cbacab26SFlorian Hahn  %c = icmp eq ptr %ptr.iv, %upper
947cbacab26SFlorian Hahn  br i1 %c, label %exit, label %for.body
948cbacab26SFlorian Hahn
949cbacab26SFlorian Hahnfor.body:
950cbacab26SFlorian Hahn  %c.1 = call i1 @cond()
951cbacab26SFlorian Hahn  br i1 %c.1, label %loop.next, label %exit
952cbacab26SFlorian Hahn
953cbacab26SFlorian Hahnloop.next:
954cbacab26SFlorian Hahn  %t.1 = icmp uge ptr %ptr.iv, %start
955cbacab26SFlorian Hahn  %t.2 = icmp ult ptr %ptr.iv, %upper
956cbacab26SFlorian Hahn  %and = and i1 %t.1, %t.2
957cbacab26SFlorian Hahn  br i1 %and, label %loop.latch, label %exit
958cbacab26SFlorian Hahn
959cbacab26SFlorian Hahnloop.latch:
960cbacab26SFlorian Hahn  call void @use(ptr %ptr.iv)
961cbacab26SFlorian Hahn  %ptr.iv.next = getelementptr float, ptr %ptr.iv, i16 1
962cbacab26SFlorian Hahn  br label %loop.header
963cbacab26SFlorian Hahn
964cbacab26SFlorian Hahnexit:
965cbacab26SFlorian Hahn  ret void
966cbacab26SFlorian Hahn}
967cbacab26SFlorian Hahn
968cbacab26SFlorian Hahndefine void @test_upper_gep_not_inbounds(ptr %start, ptr %end, i16 %len) {
969cbacab26SFlorian Hahn; CHECK-LABEL: @test_upper_gep_not_inbounds(
970cbacab26SFlorian Hahn; CHECK-NEXT:  entry:
971cbacab26SFlorian Hahn; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr float, ptr [[START:%.*]], i16 [[LEN:%.*]]
972cbacab26SFlorian Hahn; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
973cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
974cbacab26SFlorian Hahn; CHECK:       loop.ph:
975cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
976cbacab26SFlorian Hahn; CHECK:       loop.header:
977cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
978cbacab26SFlorian Hahn; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
979cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
980cbacab26SFlorian Hahn; CHECK:       for.body:
981cbacab26SFlorian Hahn; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
982cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
983cbacab26SFlorian Hahn; CHECK:       loop.next:
984cbacab26SFlorian Hahn; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
985*e6a1657fSFlorian Hahn; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
986cbacab26SFlorian Hahn; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
987cbacab26SFlorian Hahn; CHECK:       loop.latch:
988cbacab26SFlorian Hahn; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
989cbacab26SFlorian Hahn; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds float, ptr [[PTR_IV]], i16 1
990cbacab26SFlorian Hahn; CHECK-NEXT:    br label [[LOOP_HEADER]]
991cbacab26SFlorian Hahn; CHECK:       exit:
992cbacab26SFlorian Hahn; CHECK-NEXT:    ret void
993cbacab26SFlorian Hahn;
994cbacab26SFlorian Hahnentry:
995cbacab26SFlorian Hahn  %upper = getelementptr float, ptr %start, i16 %len
996cbacab26SFlorian Hahn  %len.neg = icmp slt i16 %len, 0
997cbacab26SFlorian Hahn  br i1 %len.neg, label %exit, label %loop.ph
998cbacab26SFlorian Hahn
999cbacab26SFlorian Hahnloop.ph:
1000cbacab26SFlorian Hahn  br label %loop.header
1001cbacab26SFlorian Hahn
1002cbacab26SFlorian Hahnloop.header:
1003cbacab26SFlorian Hahn  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
1004cbacab26SFlorian Hahn  %c = icmp eq ptr %ptr.iv, %upper
1005cbacab26SFlorian Hahn  br i1 %c, label %exit, label %for.body
1006cbacab26SFlorian Hahn
1007cbacab26SFlorian Hahnfor.body:
1008cbacab26SFlorian Hahn  %c.1 = call i1 @cond()
1009cbacab26SFlorian Hahn  br i1 %c.1, label %loop.next, label %exit
1010cbacab26SFlorian Hahn
1011cbacab26SFlorian Hahnloop.next:
1012cbacab26SFlorian Hahn  %t.1 = icmp uge ptr %ptr.iv, %start
1013cbacab26SFlorian Hahn  %t.2 = icmp ult ptr %ptr.iv, %upper
1014cbacab26SFlorian Hahn  %and = and i1 %t.1, %t.2
1015cbacab26SFlorian Hahn  br i1 %and, label %loop.latch, label %exit
1016cbacab26SFlorian Hahn
1017cbacab26SFlorian Hahnloop.latch:
1018cbacab26SFlorian Hahn  call void @use(ptr %ptr.iv)
1019cbacab26SFlorian Hahn  %ptr.iv.next = getelementptr inbounds float, ptr %ptr.iv, i16 1
1020cbacab26SFlorian Hahn  br label %loop.header
1021cbacab26SFlorian Hahn
1022cbacab26SFlorian Hahnexit:
1023cbacab26SFlorian Hahn  ret void
1024cbacab26SFlorian Hahn}
1025