1*261f219fSFlorian Hahn; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes
2*261f219fSFlorian Hahn; RUN: opt -indvars -S %s | FileCheck %s
3*261f219fSFlorian Hahn
4*261f219fSFlorian Hahn; Test cases inspired by PR48965.
5*261f219fSFlorian Hahn
6*261f219fSFlorian Hahn; %len is zero-extended before being used to compute %p.end, which guarantees
7*261f219fSFlorian Hahn; the offset is positive. %i.ult.ext can be simplified.
8*261f219fSFlorian Hahndefine i1 @can_simplify_ult_i32_ptr_len_zext(i32* %p.base, i32 %len) {
9*261f219fSFlorian Hahn; CHECK-LABEL: @can_simplify_ult_i32_ptr_len_zext(
10*261f219fSFlorian Hahn; CHECK-NEXT:  entry:
11*261f219fSFlorian Hahn; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[LEN:%.*]] to i64
12*261f219fSFlorian Hahn; CHECK-NEXT:    [[P_END:%.*]] = getelementptr inbounds i32, i32* [[P_BASE:%.*]], i64 [[EXT]]
13*261f219fSFlorian Hahn; CHECK-NEXT:    [[LEN_NONZERO:%.*]] = icmp ne i32 [[LEN]], 0
14*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NONZERO]], label [[HEADER_PREHEADER:%.*]], label [[TRAP:%.*]]
15*261f219fSFlorian Hahn; CHECK:       header.preheader:
16*261f219fSFlorian Hahn; CHECK-NEXT:    br label [[HEADER:%.*]]
17*261f219fSFlorian Hahn; CHECK:       trap.loopexit:
18*261f219fSFlorian Hahn; CHECK-NEXT:    br label [[TRAP]]
19*261f219fSFlorian Hahn; CHECK:       trap:
20*261f219fSFlorian Hahn; CHECK-NEXT:    ret i1 false
21*261f219fSFlorian Hahn; CHECK:       header:
22*261f219fSFlorian Hahn; CHECK-NEXT:    [[P:%.*]] = phi i32* [ [[P_INC:%.*]], [[LATCH:%.*]] ], [ [[P_BASE]], [[HEADER_PREHEADER]] ]
23*261f219fSFlorian Hahn; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_INC:%.*]], [[LATCH]] ], [ 0, [[HEADER_PREHEADER]] ]
24*261f219fSFlorian Hahn; CHECK-NEXT:    [[I_INC]] = add nuw nsw i64 [[I]], 1
25*261f219fSFlorian Hahn; CHECK-NEXT:    [[I_ULT_EXT:%.*]] = icmp ult i64 [[I]], [[EXT]]
26*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[I_ULT_EXT]], label [[LATCH]], label [[TRAP_LOOPEXIT:%.*]]
27*261f219fSFlorian Hahn; CHECK:       latch:
28*261f219fSFlorian Hahn; CHECK-NEXT:    [[P_INC]] = getelementptr inbounds i32, i32* [[P]], i64 1
29*261f219fSFlorian Hahn; CHECK-NEXT:    [[C:%.*]] = icmp ne i32* [[P_INC]], [[P_END]]
30*261f219fSFlorian Hahn; CHECK-NEXT:    store i32 0, i32* [[P]], align 4
31*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[C]], label [[HEADER]], label [[EXIT:%.*]]
32*261f219fSFlorian Hahn; CHECK:       exit:
33*261f219fSFlorian Hahn; CHECK-NEXT:    ret i1 true
34*261f219fSFlorian Hahn;
35*261f219fSFlorian Hahnentry:
36*261f219fSFlorian Hahn  %ext = zext i32 %len to i64
37*261f219fSFlorian Hahn  %p.end = getelementptr inbounds i32, i32* %p.base, i64 %ext
38*261f219fSFlorian Hahn  %len.nonzero = icmp ne i32 %len, 0
39*261f219fSFlorian Hahn  br i1 %len.nonzero, label %header, label %trap
40*261f219fSFlorian Hahn
41*261f219fSFlorian Hahntrap:
42*261f219fSFlorian Hahn  ret i1 false
43*261f219fSFlorian Hahn
44*261f219fSFlorian Hahnheader:
45*261f219fSFlorian Hahn  %p = phi i32* [ %p.base, %entry ], [ %p.inc, %latch ]
46*261f219fSFlorian Hahn  %i = phi i64 [ 0, %entry ], [ %i.inc, %latch]
47*261f219fSFlorian Hahn  %i.inc = add nsw nuw i64 %i, 1
48*261f219fSFlorian Hahn  %i.ult.ext = icmp ult i64 %i, %ext
49*261f219fSFlorian Hahn  br i1 %i.ult.ext, label %latch, label %trap
50*261f219fSFlorian Hahn
51*261f219fSFlorian Hahnlatch:
52*261f219fSFlorian Hahn  %p.inc = getelementptr inbounds i32, i32* %p, i64 1
53*261f219fSFlorian Hahn  %c = icmp ne i32* %p.inc, %p.end
54*261f219fSFlorian Hahn  store i32 0, i32* %p
55*261f219fSFlorian Hahn  br i1 %c, label %header, label %exit
56*261f219fSFlorian Hahn
57*261f219fSFlorian Hahnexit:
58*261f219fSFlorian Hahn  ret i1 true
59*261f219fSFlorian Hahn}
60*261f219fSFlorian Hahn
61*261f219fSFlorian Hahn; %len may be (signed) negative, %i.ult.ext cannot be simplified.
62*261f219fSFlorian Hahndefine i1 @cannot_simplify_ult_i32_ptr_len_ult(i32* %p.base, i64 %len) {
63*261f219fSFlorian Hahn; CHECK-LABEL: @cannot_simplify_ult_i32_ptr_len_ult(
64*261f219fSFlorian Hahn; CHECK-NEXT:  entry:
65*261f219fSFlorian Hahn; CHECK-NEXT:    [[P_END:%.*]] = getelementptr inbounds i32, i32* [[P_BASE:%.*]], i64 [[LEN:%.*]]
66*261f219fSFlorian Hahn; CHECK-NEXT:    [[LEN_NONZERO:%.*]] = icmp ne i64 [[LEN]], 0
67*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NONZERO]], label [[HEADER_PREHEADER:%.*]], label [[TRAP:%.*]]
68*261f219fSFlorian Hahn; CHECK:       header.preheader:
69*261f219fSFlorian Hahn; CHECK-NEXT:    br label [[HEADER:%.*]]
70*261f219fSFlorian Hahn; CHECK:       trap.loopexit:
71*261f219fSFlorian Hahn; CHECK-NEXT:    br label [[TRAP]]
72*261f219fSFlorian Hahn; CHECK:       trap:
73*261f219fSFlorian Hahn; CHECK-NEXT:    ret i1 false
74*261f219fSFlorian Hahn; CHECK:       header:
75*261f219fSFlorian Hahn; CHECK-NEXT:    [[P:%.*]] = phi i32* [ [[P_INC:%.*]], [[LATCH:%.*]] ], [ [[P_BASE]], [[HEADER_PREHEADER]] ]
76*261f219fSFlorian Hahn; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_INC:%.*]], [[LATCH]] ], [ 0, [[HEADER_PREHEADER]] ]
77*261f219fSFlorian Hahn; CHECK-NEXT:    [[I_INC]] = add nuw nsw i64 [[I]], 1
78*261f219fSFlorian Hahn; CHECK-NEXT:    [[I_ULT_EXT:%.*]] = icmp ult i64 [[I]], [[LEN]]
79*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[I_ULT_EXT]], label [[LATCH]], label [[TRAP_LOOPEXIT:%.*]]
80*261f219fSFlorian Hahn; CHECK:       latch:
81*261f219fSFlorian Hahn; CHECK-NEXT:    [[P_INC]] = getelementptr inbounds i32, i32* [[P]], i64 1
82*261f219fSFlorian Hahn; CHECK-NEXT:    [[C:%.*]] = icmp ne i32* [[P_INC]], [[P_END]]
83*261f219fSFlorian Hahn; CHECK-NEXT:    store i32 0, i32* [[P]], align 4
84*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[C]], label [[HEADER]], label [[EXIT:%.*]]
85*261f219fSFlorian Hahn; CHECK:       exit:
86*261f219fSFlorian Hahn; CHECK-NEXT:    ret i1 true
87*261f219fSFlorian Hahn;
88*261f219fSFlorian Hahnentry:
89*261f219fSFlorian Hahn  %p.end = getelementptr inbounds i32, i32* %p.base, i64 %len
90*261f219fSFlorian Hahn  %len.nonzero = icmp ne i64 %len, 0
91*261f219fSFlorian Hahn  br i1 %len.nonzero, label %header, label %trap
92*261f219fSFlorian Hahn
93*261f219fSFlorian Hahntrap:
94*261f219fSFlorian Hahn  ret i1 false
95*261f219fSFlorian Hahn
96*261f219fSFlorian Hahnheader:
97*261f219fSFlorian Hahn  %p = phi i32* [ %p.base, %entry ], [ %p.inc, %latch ]
98*261f219fSFlorian Hahn  %i = phi i64 [ 0, %entry ], [ %i.inc, %latch]
99*261f219fSFlorian Hahn  %i.inc = add nsw nuw i64 %i, 1
100*261f219fSFlorian Hahn  %i.ult.ext = icmp ult i64 %i, %len
101*261f219fSFlorian Hahn  br i1 %i.ult.ext, label %latch, label %trap
102*261f219fSFlorian Hahn
103*261f219fSFlorian Hahnlatch:
104*261f219fSFlorian Hahn  %p.inc = getelementptr inbounds i32, i32* %p, i64 1
105*261f219fSFlorian Hahn  %c = icmp ne i32* %p.inc, %p.end
106*261f219fSFlorian Hahn  store i32 0, i32* %p
107*261f219fSFlorian Hahn  br i1 %c, label %header, label %exit
108*261f219fSFlorian Hahn
109*261f219fSFlorian Hahnexit:
110*261f219fSFlorian Hahn  ret i1 true
111*261f219fSFlorian Hahn}
112*261f219fSFlorian Hahn
113*261f219fSFlorian Hahn; Similar to can_simplify_ult_i32_ptr_len_zext, but %i has 1 as start value. %i.ult.ext cannot be simplified.
114*261f219fSFlorian Hahndefine i1 @cannot_simplify_ult_i32_ptr_len_zext(i32* %p.base, i32 %len) {
115*261f219fSFlorian Hahn; CHECK-LABEL: @cannot_simplify_ult_i32_ptr_len_zext(
116*261f219fSFlorian Hahn; CHECK-NEXT:  entry:
117*261f219fSFlorian Hahn; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[LEN:%.*]] to i64
118*261f219fSFlorian Hahn; CHECK-NEXT:    [[P_END:%.*]] = getelementptr inbounds i32, i32* [[P_BASE:%.*]], i64 [[EXT]]
119*261f219fSFlorian Hahn; CHECK-NEXT:    [[LEN_NONZERO:%.*]] = icmp ne i32 [[LEN]], 0
120*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NONZERO]], label [[HEADER_PREHEADER:%.*]], label [[TRAP:%.*]]
121*261f219fSFlorian Hahn; CHECK:       header.preheader:
122*261f219fSFlorian Hahn; CHECK-NEXT:    br label [[HEADER:%.*]]
123*261f219fSFlorian Hahn; CHECK:       trap.loopexit:
124*261f219fSFlorian Hahn; CHECK-NEXT:    br label [[TRAP]]
125*261f219fSFlorian Hahn; CHECK:       trap:
126*261f219fSFlorian Hahn; CHECK-NEXT:    ret i1 false
127*261f219fSFlorian Hahn; CHECK:       header:
128*261f219fSFlorian Hahn; CHECK-NEXT:    [[P:%.*]] = phi i32* [ [[P_INC:%.*]], [[LATCH:%.*]] ], [ [[P_BASE]], [[HEADER_PREHEADER]] ]
129*261f219fSFlorian Hahn; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_INC:%.*]], [[LATCH]] ], [ 1, [[HEADER_PREHEADER]] ]
130*261f219fSFlorian Hahn; CHECK-NEXT:    [[I_INC]] = add nuw nsw i64 [[I]], 1
131*261f219fSFlorian Hahn; CHECK-NEXT:    [[I_ULT_EXT:%.*]] = icmp ult i64 [[I]], [[EXT]]
132*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[I_ULT_EXT]], label [[LATCH]], label [[TRAP_LOOPEXIT:%.*]]
133*261f219fSFlorian Hahn; CHECK:       latch:
134*261f219fSFlorian Hahn; CHECK-NEXT:    [[P_INC]] = getelementptr inbounds i32, i32* [[P]], i64 1
135*261f219fSFlorian Hahn; CHECK-NEXT:    [[C:%.*]] = icmp ne i32* [[P_INC]], [[P_END]]
136*261f219fSFlorian Hahn; CHECK-NEXT:    store i32 0, i32* [[P]], align 4
137*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[C]], label [[HEADER]], label [[EXIT:%.*]]
138*261f219fSFlorian Hahn; CHECK:       exit:
139*261f219fSFlorian Hahn; CHECK-NEXT:    ret i1 true
140*261f219fSFlorian Hahn;
141*261f219fSFlorian Hahnentry:
142*261f219fSFlorian Hahn  %ext = zext i32 %len to i64
143*261f219fSFlorian Hahn  %p.end = getelementptr inbounds i32, i32* %p.base, i64 %ext
144*261f219fSFlorian Hahn  %len.nonzero = icmp ne i32 %len, 0
145*261f219fSFlorian Hahn  br i1 %len.nonzero, label %header, label %trap
146*261f219fSFlorian Hahn
147*261f219fSFlorian Hahntrap:
148*261f219fSFlorian Hahn  ret i1 false
149*261f219fSFlorian Hahn
150*261f219fSFlorian Hahnheader:
151*261f219fSFlorian Hahn  %p = phi i32* [ %p.base, %entry ], [ %p.inc, %latch ]
152*261f219fSFlorian Hahn  %i = phi i64 [ 1, %entry ], [ %i.inc, %latch]
153*261f219fSFlorian Hahn  %i.inc = add nsw nuw i64 %i, 1
154*261f219fSFlorian Hahn  %i.ult.ext = icmp ult i64 %i, %ext
155*261f219fSFlorian Hahn  br i1 %i.ult.ext, label %latch, label %trap
156*261f219fSFlorian Hahn
157*261f219fSFlorian Hahnlatch:
158*261f219fSFlorian Hahn  %p.inc = getelementptr inbounds i32, i32* %p, i64 1
159*261f219fSFlorian Hahn  %c = icmp ne i32* %p.inc, %p.end
160*261f219fSFlorian Hahn  store i32 0, i32* %p
161*261f219fSFlorian Hahn  br i1 %c, label %header, label %exit
162*261f219fSFlorian Hahn
163*261f219fSFlorian Hahnexit:
164*261f219fSFlorian Hahn  ret i1 true
165*261f219fSFlorian Hahn}
166*261f219fSFlorian Hahn
167*261f219fSFlorian Hahndefine i1 @can_simplify_ule_i32_ptr_len_zext(i32* %p.base, i32 %len) {
168*261f219fSFlorian Hahn; CHECK-LABEL: @can_simplify_ule_i32_ptr_len_zext(
169*261f219fSFlorian Hahn; CHECK-NEXT:  entry:
170*261f219fSFlorian Hahn; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[LEN:%.*]] to i64
171*261f219fSFlorian Hahn; CHECK-NEXT:    [[P_END:%.*]] = getelementptr inbounds i32, i32* [[P_BASE:%.*]], i64 [[EXT]]
172*261f219fSFlorian Hahn; CHECK-NEXT:    [[LEN_NONZERO:%.*]] = icmp ne i32 [[LEN]], 0
173*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NONZERO]], label [[HEADER_PREHEADER:%.*]], label [[TRAP:%.*]]
174*261f219fSFlorian Hahn; CHECK:       header.preheader:
175*261f219fSFlorian Hahn; CHECK-NEXT:    br label [[HEADER:%.*]]
176*261f219fSFlorian Hahn; CHECK:       trap.loopexit:
177*261f219fSFlorian Hahn; CHECK-NEXT:    br label [[TRAP]]
178*261f219fSFlorian Hahn; CHECK:       trap:
179*261f219fSFlorian Hahn; CHECK-NEXT:    ret i1 false
180*261f219fSFlorian Hahn; CHECK:       header:
181*261f219fSFlorian Hahn; CHECK-NEXT:    [[P:%.*]] = phi i32* [ [[P_INC:%.*]], [[LATCH:%.*]] ], [ [[P_BASE]], [[HEADER_PREHEADER]] ]
182*261f219fSFlorian Hahn; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_INC:%.*]], [[LATCH]] ], [ 1, [[HEADER_PREHEADER]] ]
183*261f219fSFlorian Hahn; CHECK-NEXT:    [[I_INC]] = add nuw nsw i64 [[I]], 1
184*261f219fSFlorian Hahn; CHECK-NEXT:    [[I_ULT_EXT:%.*]] = icmp ule i64 [[I]], [[EXT]]
185*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[I_ULT_EXT]], label [[LATCH]], label [[TRAP_LOOPEXIT:%.*]]
186*261f219fSFlorian Hahn; CHECK:       latch:
187*261f219fSFlorian Hahn; CHECK-NEXT:    [[P_INC]] = getelementptr inbounds i32, i32* [[P]], i64 1
188*261f219fSFlorian Hahn; CHECK-NEXT:    [[C:%.*]] = icmp ne i32* [[P_INC]], [[P_END]]
189*261f219fSFlorian Hahn; CHECK-NEXT:    store i32 0, i32* [[P]], align 4
190*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[C]], label [[HEADER]], label [[EXIT:%.*]]
191*261f219fSFlorian Hahn; CHECK:       exit:
192*261f219fSFlorian Hahn; CHECK-NEXT:    ret i1 true
193*261f219fSFlorian Hahn;
194*261f219fSFlorian Hahnentry:
195*261f219fSFlorian Hahn  %ext = zext i32 %len to i64
196*261f219fSFlorian Hahn  %p.end = getelementptr inbounds i32, i32* %p.base, i64 %ext
197*261f219fSFlorian Hahn  %len.nonzero = icmp ne i32 %len, 0
198*261f219fSFlorian Hahn  br i1 %len.nonzero, label %header, label %trap
199*261f219fSFlorian Hahn
200*261f219fSFlorian Hahntrap:
201*261f219fSFlorian Hahn  ret i1 false
202*261f219fSFlorian Hahn
203*261f219fSFlorian Hahnheader:
204*261f219fSFlorian Hahn  %p = phi i32* [ %p.base, %entry ], [ %p.inc, %latch ]
205*261f219fSFlorian Hahn  %i = phi i64 [ 1, %entry ], [ %i.inc, %latch]
206*261f219fSFlorian Hahn  %i.inc = add nsw nuw i64 %i, 1
207*261f219fSFlorian Hahn  %i.ult.ext = icmp ule i64 %i, %ext
208*261f219fSFlorian Hahn  br i1 %i.ult.ext, label %latch, label %trap
209*261f219fSFlorian Hahn
210*261f219fSFlorian Hahnlatch:
211*261f219fSFlorian Hahn  %p.inc = getelementptr inbounds i32, i32* %p, i64 1
212*261f219fSFlorian Hahn  %c = icmp ne i32* %p.inc, %p.end
213*261f219fSFlorian Hahn  store i32 0, i32* %p
214*261f219fSFlorian Hahn  br i1 %c, label %header, label %exit
215*261f219fSFlorian Hahn
216*261f219fSFlorian Hahnexit:
217*261f219fSFlorian Hahn  ret i1 true
218*261f219fSFlorian Hahn}
219*261f219fSFlorian Hahn
220*261f219fSFlorian Hahn; %len is zero-extended before being used to compute %p.end, which guarantees
221*261f219fSFlorian Hahn; the offset is positive. %i.uge.ext can be simplified.
222*261f219fSFlorian Hahndefine i1 @can_simplify_uge_i32_ptr_len_zext(i32* %p.base, i32 %len) {
223*261f219fSFlorian Hahn; CHECK-LABEL: @can_simplify_uge_i32_ptr_len_zext(
224*261f219fSFlorian Hahn; CHECK-NEXT:  entry:
225*261f219fSFlorian Hahn; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[LEN:%.*]] to i64
226*261f219fSFlorian Hahn; CHECK-NEXT:    [[P_END:%.*]] = getelementptr inbounds i32, i32* [[P_BASE:%.*]], i64 [[EXT]]
227*261f219fSFlorian Hahn; CHECK-NEXT:    [[LEN_NONZERO:%.*]] = icmp ne i32 [[LEN]], 0
228*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NONZERO]], label [[HEADER_PREHEADER:%.*]], label [[TRAP:%.*]]
229*261f219fSFlorian Hahn; CHECK:       header.preheader:
230*261f219fSFlorian Hahn; CHECK-NEXT:    br label [[HEADER:%.*]]
231*261f219fSFlorian Hahn; CHECK:       trap.loopexit:
232*261f219fSFlorian Hahn; CHECK-NEXT:    br label [[TRAP]]
233*261f219fSFlorian Hahn; CHECK:       trap:
234*261f219fSFlorian Hahn; CHECK-NEXT:    ret i1 false
235*261f219fSFlorian Hahn; CHECK:       header:
236*261f219fSFlorian Hahn; CHECK-NEXT:    [[P:%.*]] = phi i32* [ [[P_INC:%.*]], [[LATCH:%.*]] ], [ [[P_BASE]], [[HEADER_PREHEADER]] ]
237*261f219fSFlorian Hahn; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_INC:%.*]], [[LATCH]] ], [ 0, [[HEADER_PREHEADER]] ]
238*261f219fSFlorian Hahn; CHECK-NEXT:    [[I_INC]] = add nuw nsw i64 [[I]], 1
239*261f219fSFlorian Hahn; CHECK-NEXT:    [[I_UGE_EXT:%.*]] = icmp uge i64 [[I]], [[EXT]]
240*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[I_UGE_EXT]], label [[TRAP_LOOPEXIT:%.*]], label [[LATCH]]
241*261f219fSFlorian Hahn; CHECK:       latch:
242*261f219fSFlorian Hahn; CHECK-NEXT:    [[P_INC]] = getelementptr inbounds i32, i32* [[P]], i64 1
243*261f219fSFlorian Hahn; CHECK-NEXT:    [[C:%.*]] = icmp ne i32* [[P_INC]], [[P_END]]
244*261f219fSFlorian Hahn; CHECK-NEXT:    store i32 0, i32* [[P]], align 4
245*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[C]], label [[HEADER]], label [[EXIT:%.*]]
246*261f219fSFlorian Hahn; CHECK:       exit:
247*261f219fSFlorian Hahn; CHECK-NEXT:    ret i1 true
248*261f219fSFlorian Hahn;
249*261f219fSFlorian Hahnentry:
250*261f219fSFlorian Hahn  %ext = zext i32 %len to i64
251*261f219fSFlorian Hahn  %p.end = getelementptr inbounds i32, i32* %p.base, i64 %ext
252*261f219fSFlorian Hahn  %len.nonzero = icmp ne i32 %len, 0
253*261f219fSFlorian Hahn  br i1 %len.nonzero, label %header, label %trap
254*261f219fSFlorian Hahn
255*261f219fSFlorian Hahntrap:
256*261f219fSFlorian Hahn  ret i1 false
257*261f219fSFlorian Hahn
258*261f219fSFlorian Hahnheader:
259*261f219fSFlorian Hahn  %p = phi i32* [ %p.base, %entry ], [ %p.inc, %latch ]
260*261f219fSFlorian Hahn  %i = phi i64 [ 0, %entry ], [ %i.inc, %latch]
261*261f219fSFlorian Hahn  %i.inc = add nsw nuw i64 %i, 1
262*261f219fSFlorian Hahn  %i.uge.ext = icmp uge i64 %i, %ext
263*261f219fSFlorian Hahn  br i1 %i.uge.ext, label %trap, label %latch
264*261f219fSFlorian Hahn
265*261f219fSFlorian Hahnlatch:
266*261f219fSFlorian Hahn  %p.inc = getelementptr inbounds i32, i32* %p, i64 1
267*261f219fSFlorian Hahn  %c = icmp ne i32* %p.inc, %p.end
268*261f219fSFlorian Hahn  store i32 0, i32* %p
269*261f219fSFlorian Hahn  br i1 %c, label %header, label %exit
270*261f219fSFlorian Hahn
271*261f219fSFlorian Hahnexit:
272*261f219fSFlorian Hahn  ret i1 true
273*261f219fSFlorian Hahn}
274*261f219fSFlorian Hahn
275*261f219fSFlorian Hahndefine i1 @cannot_simplify_uge_i32_ptr_len(i32* %p.base, i64 %len) {
276*261f219fSFlorian Hahn; CHECK-LABEL: @cannot_simplify_uge_i32_ptr_len(
277*261f219fSFlorian Hahn; CHECK-NEXT:  entry:
278*261f219fSFlorian Hahn; CHECK-NEXT:    [[P_END:%.*]] = getelementptr inbounds i32, i32* [[P_BASE:%.*]], i64 [[LEN:%.*]]
279*261f219fSFlorian Hahn; CHECK-NEXT:    [[LEN_NONZERO:%.*]] = icmp ne i64 [[LEN]], 0
280*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NONZERO]], label [[HEADER_PREHEADER:%.*]], label [[TRAP:%.*]]
281*261f219fSFlorian Hahn; CHECK:       header.preheader:
282*261f219fSFlorian Hahn; CHECK-NEXT:    br label [[HEADER:%.*]]
283*261f219fSFlorian Hahn; CHECK:       trap.loopexit:
284*261f219fSFlorian Hahn; CHECK-NEXT:    br label [[TRAP]]
285*261f219fSFlorian Hahn; CHECK:       trap:
286*261f219fSFlorian Hahn; CHECK-NEXT:    ret i1 false
287*261f219fSFlorian Hahn; CHECK:       header:
288*261f219fSFlorian Hahn; CHECK-NEXT:    [[P:%.*]] = phi i32* [ [[P_INC:%.*]], [[LATCH:%.*]] ], [ [[P_BASE]], [[HEADER_PREHEADER]] ]
289*261f219fSFlorian Hahn; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_INC:%.*]], [[LATCH]] ], [ 0, [[HEADER_PREHEADER]] ]
290*261f219fSFlorian Hahn; CHECK-NEXT:    [[I_INC]] = add nuw nsw i64 [[I]], 1
291*261f219fSFlorian Hahn; CHECK-NEXT:    [[I_UGE_EXT:%.*]] = icmp uge i64 [[I]], [[LEN]]
292*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[I_UGE_EXT]], label [[TRAP_LOOPEXIT:%.*]], label [[LATCH]]
293*261f219fSFlorian Hahn; CHECK:       latch:
294*261f219fSFlorian Hahn; CHECK-NEXT:    [[P_INC]] = getelementptr inbounds i32, i32* [[P]], i64 1
295*261f219fSFlorian Hahn; CHECK-NEXT:    [[C:%.*]] = icmp ne i32* [[P_INC]], [[P_END]]
296*261f219fSFlorian Hahn; CHECK-NEXT:    store i32 0, i32* [[P]], align 4
297*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[C]], label [[HEADER]], label [[EXIT:%.*]]
298*261f219fSFlorian Hahn; CHECK:       exit:
299*261f219fSFlorian Hahn; CHECK-NEXT:    ret i1 true
300*261f219fSFlorian Hahn;
301*261f219fSFlorian Hahnentry:
302*261f219fSFlorian Hahn  %p.end = getelementptr inbounds i32, i32* %p.base, i64 %len
303*261f219fSFlorian Hahn  %len.nonzero = icmp ne i64 %len, 0
304*261f219fSFlorian Hahn  br i1 %len.nonzero, label %header, label %trap
305*261f219fSFlorian Hahn
306*261f219fSFlorian Hahntrap:
307*261f219fSFlorian Hahn  ret i1 false
308*261f219fSFlorian Hahn
309*261f219fSFlorian Hahnheader:
310*261f219fSFlorian Hahn  %p = phi i32* [ %p.base, %entry ], [ %p.inc, %latch ]
311*261f219fSFlorian Hahn  %i = phi i64 [ 0, %entry ], [ %i.inc, %latch]
312*261f219fSFlorian Hahn  %i.inc = add nsw nuw i64 %i, 1
313*261f219fSFlorian Hahn  %i.uge.ext = icmp uge i64 %i, %len
314*261f219fSFlorian Hahn  br i1 %i.uge.ext, label %trap, label %latch
315*261f219fSFlorian Hahn
316*261f219fSFlorian Hahnlatch:
317*261f219fSFlorian Hahn  %p.inc = getelementptr inbounds i32, i32* %p, i64 1
318*261f219fSFlorian Hahn  %c = icmp ne i32* %p.inc, %p.end
319*261f219fSFlorian Hahn  store i32 0, i32* %p
320*261f219fSFlorian Hahn  br i1 %c, label %header, label %exit
321*261f219fSFlorian Hahn
322*261f219fSFlorian Hahnexit:
323*261f219fSFlorian Hahn  ret i1 true
324*261f219fSFlorian Hahn}
325*261f219fSFlorian Hahn
326*261f219fSFlorian Hahndefine i1 @cannot_simplify_uge_i32_ptr_len_zext_step_2(i32* %p.base, i32 %len) {
327*261f219fSFlorian Hahn; CHECK-LABEL: @cannot_simplify_uge_i32_ptr_len_zext_step_2(
328*261f219fSFlorian Hahn; CHECK-NEXT:  entry:
329*261f219fSFlorian Hahn; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[LEN:%.*]] to i64
330*261f219fSFlorian Hahn; CHECK-NEXT:    [[P_END:%.*]] = getelementptr inbounds i32, i32* [[P_BASE:%.*]], i64 [[EXT]]
331*261f219fSFlorian Hahn; CHECK-NEXT:    [[LEN_NONZERO:%.*]] = icmp ne i32 [[LEN]], 0
332*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[LEN_NONZERO]], label [[HEADER_PREHEADER:%.*]], label [[TRAP:%.*]]
333*261f219fSFlorian Hahn; CHECK:       header.preheader:
334*261f219fSFlorian Hahn; CHECK-NEXT:    br label [[HEADER:%.*]]
335*261f219fSFlorian Hahn; CHECK:       trap.loopexit:
336*261f219fSFlorian Hahn; CHECK-NEXT:    br label [[TRAP]]
337*261f219fSFlorian Hahn; CHECK:       trap:
338*261f219fSFlorian Hahn; CHECK-NEXT:    ret i1 false
339*261f219fSFlorian Hahn; CHECK:       header:
340*261f219fSFlorian Hahn; CHECK-NEXT:    [[P:%.*]] = phi i32* [ [[P_INC:%.*]], [[LATCH:%.*]] ], [ [[P_BASE]], [[HEADER_PREHEADER]] ]
341*261f219fSFlorian Hahn; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_INC:%.*]], [[LATCH]] ], [ 0, [[HEADER_PREHEADER]] ]
342*261f219fSFlorian Hahn; CHECK-NEXT:    [[I_INC]] = add nuw nsw i64 [[I]], 2
343*261f219fSFlorian Hahn; CHECK-NEXT:    [[I_UGE_EXT:%.*]] = icmp uge i64 [[I]], [[EXT]]
344*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[I_UGE_EXT]], label [[TRAP_LOOPEXIT:%.*]], label [[LATCH]]
345*261f219fSFlorian Hahn; CHECK:       latch:
346*261f219fSFlorian Hahn; CHECK-NEXT:    [[P_INC]] = getelementptr inbounds i32, i32* [[P]], i64 1
347*261f219fSFlorian Hahn; CHECK-NEXT:    [[C:%.*]] = icmp ne i32* [[P_INC]], [[P_END]]
348*261f219fSFlorian Hahn; CHECK-NEXT:    store i32 0, i32* [[P]], align 4
349*261f219fSFlorian Hahn; CHECK-NEXT:    br i1 [[C]], label [[HEADER]], label [[EXIT:%.*]]
350*261f219fSFlorian Hahn; CHECK:       exit:
351*261f219fSFlorian Hahn; CHECK-NEXT:    ret i1 true
352*261f219fSFlorian Hahn;
353*261f219fSFlorian Hahnentry:
354*261f219fSFlorian Hahn  %ext = zext i32 %len to i64
355*261f219fSFlorian Hahn  %p.end = getelementptr inbounds i32, i32* %p.base, i64 %ext
356*261f219fSFlorian Hahn  %len.nonzero = icmp ne i32 %len, 0
357*261f219fSFlorian Hahn  br i1 %len.nonzero, label %header, label %trap
358*261f219fSFlorian Hahn
359*261f219fSFlorian Hahntrap:
360*261f219fSFlorian Hahn  ret i1 false
361*261f219fSFlorian Hahn
362*261f219fSFlorian Hahnheader:
363*261f219fSFlorian Hahn  %p = phi i32* [ %p.base, %entry ], [ %p.inc, %latch ]
364*261f219fSFlorian Hahn  %i = phi i64 [ 0, %entry ], [ %i.inc, %latch]
365*261f219fSFlorian Hahn  %i.inc = add nsw nuw i64 %i, 2
366*261f219fSFlorian Hahn  %i.uge.ext = icmp uge i64 %i, %ext
367*261f219fSFlorian Hahn  br i1 %i.uge.ext, label %trap, label %latch
368*261f219fSFlorian Hahn
369*261f219fSFlorian Hahnlatch:
370*261f219fSFlorian Hahn  %p.inc = getelementptr inbounds i32, i32* %p, i64 1
371*261f219fSFlorian Hahn  %c = icmp ne i32* %p.inc, %p.end
372*261f219fSFlorian Hahn  store i32 0, i32* %p
373*261f219fSFlorian Hahn  br i1 %c, label %header, label %exit
374*261f219fSFlorian Hahn
375*261f219fSFlorian Hahnexit:
376*261f219fSFlorian Hahn  ret i1 true
377*261f219fSFlorian Hahn}
378