[LLVM][IR] Use splat syntax when printing ConstantExpr based splats. (#116856)
[llvm-project.git] / llvm / test / Transforms / ConstraintElimination / monotonic-pointer-phis-chain-of-exits.ll
blob6b128d9e525ca365c511431b40f0a60f441b568b
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"
6 declare void @use(ptr)
7 declare i1 @cond()
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(
11 ; CHECK-NEXT:  entry:
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:%.*]]
15 ; CHECK:       loop.ph:
16 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
17 ; CHECK:       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:%.*]]
21 ; CHECK:       then:
22 ; CHECK-NEXT:    [[C_1:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
23 ; CHECK-NEXT:    br i1 [[C_1]], label [[EXIT]], label [[FOR_BODY:%.*]]
24 ; CHECK:       for.body:
25 ; CHECK-NEXT:    [[C_2:%.*]] = call i1 @cond()
26 ; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
27 ; CHECK:       loop.next:
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]]
32 ; CHECK:       loop.latch:
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]]
36 ; CHECK:       exit:
37 ; CHECK-NEXT:    ret void
39 entry:
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
44 loop.ph:
45   br label %loop.header
47 loop.header:
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
52 then:
53   %c.1 = icmp eq ptr %ptr.iv, %upper
54   br i1 %c.1, label %exit, label %for.body
56 for.body:
57   %c.2 = call i1 @cond()
58   br i1 %c.2, label %loop.next, label %exit
60 loop.next:
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
66 loop.latch:
67   call void @use(ptr %ptr.iv)
68   %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
69   br label %loop.header
71 exit:
72   ret void
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(
77 ; CHECK-NEXT:  entry:
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:%.*]]
81 ; CHECK:       loop.ph:
82 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
83 ; CHECK:       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:%.*]]
87 ; CHECK:       then.1:
88 ; CHECK-NEXT:    [[C_00:%.*]] = icmp ult i16 [[X]], 100
89 ; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[THEN_2:%.*]]
90 ; CHECK:       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:%.*]]
93 ; CHECK:       for.body:
94 ; CHECK-NEXT:    [[C_2:%.*]] = call i1 @cond()
95 ; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
96 ; CHECK:       loop.next:
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]]
101 ; CHECK:       loop.latch:
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]]
105 ; CHECK:       exit:
106 ; CHECK-NEXT:    ret void
108 entry:
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
113 loop.ph:
114   br label %loop.header
116 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
121 then.1:
122   %c.00 = icmp ult i16 %x, 100
123   br i1 %c.0, label %exit, label %then.2
125 then.2:
126   %c.1 = icmp eq ptr %ptr.iv, %upper
127   br i1 %c.1, label %exit, label %for.body
129 for.body:
130   %c.2 = call i1 @cond()
131   br i1 %c.2, label %loop.next, label %exit
133 loop.next:
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
139 loop.latch:
140   call void @use(ptr %ptr.iv)
141   %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
142   br label %loop.header
144 exit:
145   ret void
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(
150 ; CHECK-NEXT:  entry:
151 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
152 ; CHECK-NEXT:    br label [[LOOP_PH:%.*]]
153 ; CHECK:       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:%.*]]
159 ; CHECK:       then:
160 ; CHECK-NEXT:    [[C_1:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
161 ; CHECK-NEXT:    br i1 [[C_1]], label [[EXIT]], label [[FOR_BODY:%.*]]
162 ; CHECK:       for.body:
163 ; CHECK-NEXT:    [[C_2:%.*]] = call i1 @cond()
164 ; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
165 ; CHECK:       loop.next:
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]]
170 ; CHECK:       loop.latch:
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]]
174 ; CHECK:       exit:
175 ; CHECK-NEXT:    ret void
177 entry:
178   %upper = getelementptr inbounds i32, ptr %start, i16 %len
179   br label %loop.ph
181 loop.ph:
182   br label %loop.header
184 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
189 then:
190   %c.1 = icmp eq ptr %ptr.iv, %upper
191   br i1 %c.1, label %exit, label %for.body
193 for.body:
194   %c.2 = call i1 @cond()
195   br i1 %c.2, label %loop.next, label %exit
197 loop.next:
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
203 loop.latch:
204   call void @use(ptr %ptr.iv)
205   %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
206   br label %loop.header
208 exit:
209   ret void
212 define void @test_header_not_exiting(ptr %start, i16 %len, i16 %x) {
213 ; CHECK-LABEL: @test_header_not_exiting(
214 ; CHECK-NEXT:  entry:
215 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
216 ; CHECK-NEXT:    br label [[LOOP_PH:%.*]]
217 ; CHECK:       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:%.*]]
223 ; CHECK:       then:
224 ; CHECK-NEXT:    [[C_1:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
225 ; CHECK-NEXT:    br i1 [[C_1]], label [[EXIT:%.*]], label [[FOR_BODY]]
226 ; CHECK:       for.body:
227 ; CHECK-NEXT:    [[C_2:%.*]] = call i1 @cond()
228 ; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
229 ; CHECK:       loop.next:
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]]
234 ; CHECK:       loop.latch:
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]]
238 ; CHECK:       exit:
239 ; CHECK-NEXT:    ret void
241 entry:
242   %upper = getelementptr inbounds i32, ptr %start, i16 %len
243   br label %loop.ph
245 loop.ph:
246   br label %loop.header
248 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
253 then:
254   %c.1 = icmp eq ptr %ptr.iv, %upper
255   br i1 %c.1, label %exit, label %for.body
257 for.body:
258   %c.2 = call i1 @cond()
259   br i1 %c.2, label %loop.next, label %exit
261 loop.next:
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
267 loop.latch:
268   call void @use(ptr %ptr.iv)
269   %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
270   br label %loop.header
272 exit:
273   ret void
276 declare void @foo()
278 define i32 @test_latch_exiting1(i32 %N) {
279 ; CHECK-LABEL: @test_latch_exiting1(
280 ; CHECK-NEXT:  entry:
281 ; CHECK-NEXT:    br label [[LOOP:%.*]]
282 ; CHECK:       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]]
288 ; CHECK:       exit.1:
289 ; CHECK-NEXT:    ret i32 10
291 entry:
292   br label %loop
294 loop:
295   %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
296   call void @foo()
297   %iv.next = add i32 %iv, 1
298   %ec = icmp eq i32 %iv, %N
299   br i1 %ec, label %exit.1, label %loop
301 exit.1:
302   ret i32 10
305 define i32 @test_latch_exiting2(i1 %c, i32 %N) {
306 ; CHECK-LABEL: @test_latch_exiting2(
307 ; CHECK-NEXT:  entry:
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:%.*]]
312 ; CHECK:       loop.latch:
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]]
317 ; CHECK:       exit.1:
318 ; CHECK-NEXT:    ret i32 10
319 ; CHECK:       exit.2:
320 ; CHECK-NEXT:    ret i32 0
322 entry:
323   br label %loop.header
325 loop.header:
326   %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
327   br i1 %c, label %loop.latch, label %exit.1
329 loop.latch:
330   call void @foo()
331   %iv.next = add i32 %iv, 1
332   %ec = icmp eq i32 %iv, %N
333   br i1 %ec, label %exit.2, label %loop.header
335 exit.1:
336   ret i32 10
338 exit.2:
339   ret i32 0