1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
4 target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
9 define void @test_monotonic_ptr_iv_inc_1_different_element_types_1_chain_of_2_exit_condition_unrelated_condition_in_header(ptr %start, i16 %len, i16 %x) {
10 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_1_chain_of_2_exit_condition_unrelated_condition_in_header(
12 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
13 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
14 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
16 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
18 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
19 ; CHECK-NEXT: [[C_0:%.*]] = icmp eq i16 [[X:%.*]], 1
20 ; CHECK-NEXT: br i1 [[C_0]], label [[EXIT]], label [[THEN:%.*]]
22 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
23 ; CHECK-NEXT: br i1 [[C_1]], label [[EXIT]], label [[FOR_BODY:%.*]]
25 ; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
26 ; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
28 ; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
29 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
30 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
31 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
33 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
34 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
35 ; CHECK-NEXT: br label [[LOOP_HEADER]]
37 ; CHECK-NEXT: ret void
40 %upper = getelementptr inbounds i32, ptr %start, i16 %len
41 %len.neg = icmp slt i16 %len, 0
42 br i1 %len.neg, label %exit, label %loop.ph
48 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
49 %c.0 = icmp eq i16 %x, 1
50 br i1 %c.0, label %exit, label %then
53 %c.1 = icmp eq ptr %ptr.iv, %upper
54 br i1 %c.1, label %exit, label %for.body
57 %c.2 = call i1 @cond()
58 br i1 %c.2, label %loop.next, label %exit
61 %t.1 = icmp uge ptr %ptr.iv, %start
62 %t.2 = icmp ult ptr %ptr.iv, %upper
63 %and = and i1 %t.1, %t.2
64 br i1 %and, label %loop.latch, label %exit
67 call void @use(ptr %ptr.iv)
68 %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
75 define void @test_monotonic_ptr_iv_inc_1_different_element_types_1_chain_of_3_exit_condition_unrelated_condition_in_header(ptr %start, i16 %len, i16 %x) {
76 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_1_chain_of_3_exit_condition_unrelated_condition_in_header(
78 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
79 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
80 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
82 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
84 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
85 ; CHECK-NEXT: [[C_0:%.*]] = icmp eq i16 [[X:%.*]], 1
86 ; CHECK-NEXT: br i1 [[C_0]], label [[EXIT]], label [[THEN_1:%.*]]
88 ; CHECK-NEXT: [[C_00:%.*]] = icmp ult i16 [[X]], 100
89 ; CHECK-NEXT: br i1 [[C_0]], label [[EXIT]], label [[THEN_2:%.*]]
91 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
92 ; CHECK-NEXT: br i1 [[C_1]], label [[EXIT]], label [[FOR_BODY:%.*]]
94 ; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
95 ; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
97 ; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
98 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
99 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
100 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
102 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
103 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
104 ; CHECK-NEXT: br label [[LOOP_HEADER]]
106 ; CHECK-NEXT: ret void
109 %upper = getelementptr inbounds i32, ptr %start, i16 %len
110 %len.neg = icmp slt i16 %len, 0
111 br i1 %len.neg, label %exit, label %loop.ph
114 br label %loop.header
117 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
118 %c.0 = icmp eq i16 %x, 1
119 br i1 %c.0, label %exit, label %then.1
122 %c.00 = icmp ult i16 %x, 100
123 br i1 %c.0, label %exit, label %then.2
126 %c.1 = icmp eq ptr %ptr.iv, %upper
127 br i1 %c.1, label %exit, label %for.body
130 %c.2 = call i1 @cond()
131 br i1 %c.2, label %loop.next, label %exit
134 %t.1 = icmp uge ptr %ptr.iv, %start
135 %t.2 = icmp ult ptr %ptr.iv, %upper
136 %and = and i1 %t.1, %t.2
137 br i1 %and, label %loop.latch, label %exit
140 call void @use(ptr %ptr.iv)
141 %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
142 br label %loop.header
148 define void @test_monotonic_ptr_iv_inc_1_different_element_types_1_chain_of_2_exit_conditions_with_slt_in_header(ptr %start, i16 %len, i16 %x) {
149 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_1_chain_of_2_exit_conditions_with_slt_in_header(
151 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
152 ; CHECK-NEXT: br label [[LOOP_PH:%.*]]
154 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
155 ; CHECK: loop.header:
156 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
157 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
158 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[THEN:%.*]]
160 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
161 ; CHECK-NEXT: br i1 [[C_1]], label [[EXIT]], label [[FOR_BODY:%.*]]
163 ; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
164 ; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
166 ; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
167 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
168 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
169 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
171 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
172 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
173 ; CHECK-NEXT: br label [[LOOP_HEADER]]
175 ; CHECK-NEXT: ret void
178 %upper = getelementptr inbounds i32, ptr %start, i16 %len
182 br label %loop.header
185 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
186 %len.neg = icmp slt i16 %len, 0
187 br i1 %len.neg, label %exit, label %then
190 %c.1 = icmp eq ptr %ptr.iv, %upper
191 br i1 %c.1, label %exit, label %for.body
194 %c.2 = call i1 @cond()
195 br i1 %c.2, label %loop.next, label %exit
198 %t.1 = icmp uge ptr %ptr.iv, %start
199 %t.2 = icmp ult ptr %ptr.iv, %upper
200 %and = and i1 %t.1, %t.2
201 br i1 %and, label %loop.latch, label %exit
204 call void @use(ptr %ptr.iv)
205 %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
206 br label %loop.header
212 define void @test_header_not_exiting(ptr %start, i16 %len, i16 %x) {
213 ; CHECK-LABEL: @test_header_not_exiting(
215 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
216 ; CHECK-NEXT: br label [[LOOP_PH:%.*]]
218 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
219 ; CHECK: loop.header:
220 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
221 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
222 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[THEN:%.*]], label [[FOR_BODY:%.*]]
224 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
225 ; CHECK-NEXT: br i1 [[C_1]], label [[EXIT:%.*]], label [[FOR_BODY]]
227 ; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
228 ; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
230 ; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
231 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
232 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
233 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
235 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
236 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
237 ; CHECK-NEXT: br label [[LOOP_HEADER]]
239 ; CHECK-NEXT: ret void
242 %upper = getelementptr inbounds i32, ptr %start, i16 %len
246 br label %loop.header
249 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
250 %len.neg = icmp slt i16 %len, 0
251 br i1 %len.neg, label %then, label %for.body
254 %c.1 = icmp eq ptr %ptr.iv, %upper
255 br i1 %c.1, label %exit, label %for.body
258 %c.2 = call i1 @cond()
259 br i1 %c.2, label %loop.next, label %exit
262 %t.1 = icmp uge ptr %ptr.iv, %start
263 %t.2 = icmp ult ptr %ptr.iv, %upper
264 %and = and i1 %t.1, %t.2
265 br i1 %and, label %loop.latch, label %exit
268 call void @use(ptr %ptr.iv)
269 %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
270 br label %loop.header
278 define i32 @test_latch_exiting1(i32 %N) {
279 ; CHECK-LABEL: @test_latch_exiting1(
281 ; CHECK-NEXT: br label [[LOOP:%.*]]
283 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
284 ; CHECK-NEXT: call void @foo()
285 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
286 ; CHECK-NEXT: [[EC:%.*]] = icmp eq i32 [[IV]], [[N:%.*]]
287 ; CHECK-NEXT: br i1 [[EC]], label [[EXIT_1:%.*]], label [[LOOP]]
289 ; CHECK-NEXT: ret i32 10
295 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
297 %iv.next = add i32 %iv, 1
298 %ec = icmp eq i32 %iv, %N
299 br i1 %ec, label %exit.1, label %loop
305 define i32 @test_latch_exiting2(i1 %c, i32 %N) {
306 ; CHECK-LABEL: @test_latch_exiting2(
308 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
309 ; CHECK: loop.header:
310 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
311 ; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP_LATCH]], label [[EXIT_1:%.*]]
313 ; CHECK-NEXT: call void @foo()
314 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
315 ; CHECK-NEXT: [[EC:%.*]] = icmp eq i32 [[IV]], [[N:%.*]]
316 ; CHECK-NEXT: br i1 [[EC]], label [[EXIT_2:%.*]], label [[LOOP_HEADER]]
318 ; CHECK-NEXT: ret i32 10
320 ; CHECK-NEXT: ret i32 0
323 br label %loop.header
326 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
327 br i1 %c, label %loop.latch, label %exit.1
331 %iv.next = add i32 %iv, 1
332 %ec = icmp eq i32 %iv, %N
333 br i1 %ec, label %exit.2, label %loop.header