1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
4 ; Tests for cases with explicit checks that %ptr + x >= %ptr. The information can
5 ; be used to determine that certain GEPs do not overflow.
7 define i1 @overflow_check_1(ptr %dst) {
8 ; CHECK-LABEL: @overflow_check_1(
10 ; CHECK-NEXT: [[DST_5:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 5
11 ; CHECK-NEXT: [[DST_5_UGE:%.*]] = icmp uge ptr [[DST_5]], [[DST]]
12 ; CHECK-NEXT: br i1 [[DST_5_UGE]], label [[THEN:%.*]], label [[ELSE:%.*]]
14 ; CHECK-NEXT: [[DST_4:%.*]] = getelementptr i32, ptr [[DST]], i64 4
15 ; CHECK-NEXT: [[TRUE_DST_4_UGE:%.*]] = icmp uge ptr [[DST_4]], [[DST]]
16 ; CHECK-NEXT: ret i1 [[TRUE_DST_4_UGE]]
18 ; CHECK-NEXT: ret i1 false
21 %dst.5 = getelementptr i32, ptr %dst, i64 5
22 %dst.5.uge = icmp uge ptr %dst.5, %dst
23 br i1 %dst.5.uge, label %then, label %else
26 %dst.4 = getelementptr i32, ptr %dst, i64 4
27 %true.dst.4.uge = icmp uge ptr %dst.4, %dst
28 ret i1 %true.dst.4.uge
34 define i1 @overflow_check_2_and(ptr %dst) {
35 ; CHECK-LABEL: @overflow_check_2_and(
37 ; CHECK-NEXT: [[DST_5:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 5
38 ; CHECK-NEXT: [[DST_5_UGE:%.*]] = icmp uge ptr [[DST_5]], [[DST]]
39 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[DST_5_UGE]]
40 ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
42 ; CHECK-NEXT: [[DST_4:%.*]] = getelementptr i32, ptr [[DST]], i64 4
43 ; CHECK-NEXT: [[TRUE_DST_4_UGE:%.*]] = icmp uge ptr [[DST_4]], [[DST]]
44 ; CHECK-NEXT: ret i1 [[TRUE_DST_4_UGE]]
46 ; CHECK-NEXT: ret i1 true
49 %dst.5 = getelementptr i32, ptr %dst, i64 5
50 %dst.5.uge = icmp uge ptr %dst.5, %dst
51 %and = and i1 %dst.5.uge, %dst.5.uge
52 br i1 %and, label %then, label %else
55 %dst.4 = getelementptr i32, ptr %dst, i64 4
56 %true.dst.4.uge = icmp uge ptr %dst.4, %dst
57 ret i1 %true.dst.4.uge
63 define i1 @overflow_check_3_and(ptr %dst) {
64 ; CHECK-LABEL: @overflow_check_3_and(
66 ; CHECK-NEXT: [[DST_5:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 5
67 ; CHECK-NEXT: [[DST_5_UGE:%.*]] = icmp uge ptr [[DST_5]], [[DST]]
68 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[DST_5_UGE]]
69 ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
71 ; CHECK-NEXT: [[DST_4:%.*]] = getelementptr i32, ptr [[DST]], i64 4
72 ; CHECK-NEXT: [[DST_4_UGE:%.*]] = icmp uge ptr [[DST_4]], [[DST]]
73 ; CHECK-NEXT: ret i1 [[DST_4_UGE]]
75 ; CHECK-NEXT: [[ELSE_DST_4:%.*]] = getelementptr i32, ptr [[DST]], i64 4
76 ; CHECK-NEXT: [[ELSE_DST_4_UGE:%.*]] = icmp uge ptr [[ELSE_DST_4]], [[DST]]
77 ; CHECK-NEXT: ret i1 [[ELSE_DST_4_UGE]]
80 %dst.5 = getelementptr i32, ptr %dst, i64 5
81 %dst.5.uge = icmp uge ptr %dst.5, %dst
82 %and = and i1 %dst.5.uge, %dst.5.uge
83 br i1 %and, label %then, label %else
86 %dst.4 = getelementptr i32, ptr %dst, i64 4
87 %dst.4.uge = icmp uge ptr %dst.4, %dst
91 %else.dst.4 = getelementptr i32, ptr %dst, i64 4
92 %else.dst.4.uge = icmp uge ptr %else.dst.4, %dst
93 ret i1 %else.dst.4.uge
96 define i1 @overflow_check_4_and(ptr %dst) {
97 ; CHECK-LABEL: @overflow_check_4_and(
99 ; CHECK-NEXT: [[DST_5:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 5
100 ; CHECK-NEXT: [[DST_5_UGE:%.*]] = icmp uge ptr [[DST_5]], [[DST]]
101 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[DST_5_UGE]]
102 ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
104 ; CHECK-NEXT: [[DST_4:%.*]] = getelementptr i32, ptr [[DST]], i64 4
105 ; CHECK-NEXT: [[TRUE_DST_4_UGE:%.*]] = icmp uge ptr [[DST_4]], [[DST]]
106 ; CHECK-NEXT: [[DST_5_2:%.*]] = getelementptr i32, ptr [[DST]], i64 5
107 ; CHECK-NEXT: [[TRUE_DST_5_UGE:%.*]] = icmp uge ptr [[DST_5_2]], [[DST]]
108 ; CHECK-NEXT: [[RES_0:%.*]] = xor i1 [[TRUE_DST_4_UGE]], [[TRUE_DST_5_UGE]]
109 ; CHECK-NEXT: [[DST_6:%.*]] = getelementptr i32, ptr [[DST]], i64 6
110 ; CHECK-NEXT: [[C_DST_6_UGE:%.*]] = icmp uge ptr [[DST_6]], [[DST]]
111 ; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[RES_0]], [[C_DST_6_UGE]]
112 ; CHECK-NEXT: ret i1 [[RES_1]]
114 ; CHECK-NEXT: [[ELSE_DST_4:%.*]] = getelementptr i32, ptr [[DST]], i64 4
115 ; CHECK-NEXT: [[ELSE_DST_4_UGE:%.*]] = icmp uge ptr [[ELSE_DST_4]], [[DST]]
116 ; CHECK-NEXT: [[ELSE_DST_6:%.*]] = getelementptr i32, ptr [[DST]], i64 6
117 ; CHECK-NEXT: [[ELSE_DST_6_UGE:%.*]] = icmp uge ptr [[ELSE_DST_6]], [[DST]]
118 ; CHECK-NEXT: [[ELSE_RES_0:%.*]] = xor i1 [[ELSE_DST_4_UGE]], [[ELSE_DST_6_UGE]]
119 ; CHECK-NEXT: ret i1 [[ELSE_RES_0]]
122 %dst.5 = getelementptr i32, ptr %dst, i64 5
123 %dst.5.uge = icmp uge ptr %dst.5, %dst
124 %and = and i1 %dst.5.uge, %dst.5.uge
125 br i1 %and, label %then, label %else
128 %dst.4 = getelementptr i32, ptr %dst, i64 4
129 %true.dst.4.uge = icmp uge ptr %dst.4, %dst
130 %dst.5.2 = getelementptr i32, ptr %dst, i64 5
131 %true.dst.5.uge = icmp uge ptr %dst.5.2, %dst
132 %res.0 = xor i1 %true.dst.4.uge, %true.dst.5.uge
134 %dst.6 = getelementptr i32, ptr %dst, i64 6
135 %c.dst.6.uge = icmp uge ptr %dst.6, %dst
136 %res.1 = xor i1 %res.0, %c.dst.6.uge
141 %else.dst.4 = getelementptr i32, ptr %dst, i64 4
142 %else.dst.4.uge = icmp uge ptr %else.dst.4, %dst
143 %else.dst.6 = getelementptr i32, ptr %dst, i64 6
144 %else.dst.6.uge = icmp uge ptr %else.dst.6, %dst
145 %else.res.0 = xor i1 %else.dst.4.uge, %else.dst.6.uge
150 define i1 @overflow_check_3_or(ptr %dst) {
151 ; CHECK-LABEL: @overflow_check_3_or(
153 ; CHECK-NEXT: [[DST_5:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 5
154 ; CHECK-NEXT: [[DST_5_UGE:%.*]] = icmp uge ptr [[DST_5]], [[DST]]
155 ; CHECK-NEXT: [[OR:%.*]] = or i1 false, [[DST_5_UGE]]
156 ; CHECK-NEXT: br i1 [[OR]], label [[THEN:%.*]], label [[ELSE:%.*]]
158 ; CHECK-NEXT: [[DST_4:%.*]] = getelementptr i32, ptr [[DST]], i64 4
159 ; CHECK-NEXT: [[TRUE_DST_4_UGE:%.*]] = icmp uge ptr [[DST_4]], [[DST]]
160 ; CHECK-NEXT: ret i1 [[TRUE_DST_4_UGE]]
162 ; CHECK-NEXT: ret i1 false
165 %dst.5 = getelementptr i32, ptr %dst, i64 5
166 %dst.5.uge = icmp uge ptr %dst.5, %dst
167 %or = or i1 %dst.5.uge, %dst.5.uge
168 br i1 %or, label %then, label %else
171 %dst.4 = getelementptr i32, ptr %dst, i64 4
172 %true.dst.4.uge = icmp uge ptr %dst.4, %dst
173 ret i1 %true.dst.4.uge
179 define i1 @upper_and_lower_checks_1(ptr %dst, i32 %n) {
180 ; CHECK-LABEL: @upper_and_lower_checks_1(
182 ; CHECK-NEXT: [[N_EXT:%.*]] = zext i32 [[N:%.*]] to i64
183 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[DST:%.*]], i64 [[N_EXT]]
184 ; CHECK-NEXT: [[DST_5:%.*]] = getelementptr i32, ptr [[DST]], i64 5
185 ; CHECK-NEXT: [[DST_5_ULT:%.*]] = icmp ult ptr [[DST_5]], [[UPPER]]
186 ; CHECK-NEXT: [[DST_5_UGE:%.*]] = icmp uge ptr [[DST_5]], [[DST]]
187 ; CHECK-NEXT: [[AND_1:%.*]] = and i1 [[DST_5_ULT]], [[DST_5_UGE]]
188 ; CHECK-NEXT: br i1 [[AND_1]], label [[THEN:%.*]], label [[ELSE:%.*]]
190 ; CHECK-NEXT: [[DST_4:%.*]] = getelementptr i32, ptr [[DST]], i64 4
191 ; CHECK-NEXT: [[TRUE_DST_4_ULT:%.*]] = icmp ult ptr [[DST_4]], [[UPPER]]
192 ; CHECK-NEXT: [[TRUE_DST_4_UGE:%.*]] = icmp uge ptr [[DST_4]], [[DST]]
193 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[TRUE_DST_4_ULT]], [[TRUE_DST_4_UGE]]
194 ; CHECK-NEXT: ret i1 [[AND]]
196 ; CHECK-NEXT: ret i1 false
199 %n.ext = zext i32 %n to i64
200 %upper = getelementptr inbounds i32, ptr %dst, i64 %n.ext
201 %dst.5 = getelementptr i32, ptr %dst, i64 5
202 %dst.5.ult = icmp ult ptr %dst.5, %upper
203 %dst.5.uge = icmp uge ptr %dst.5, %dst
204 %and.1 = and i1 %dst.5.ult, %dst.5.uge
205 br i1 %and.1, label %then, label %else
208 %dst.4 = getelementptr i32, ptr %dst, i64 4
209 %true.dst.4.ult = icmp ult ptr %dst.4, %upper
210 %true.dst.4.uge = icmp uge ptr %dst.4, %dst
211 %and = and i1 %true.dst.4.ult, %true.dst.4.uge
218 define i1 @upper_and_lower_checks_2_dst6(ptr %dst, i32 %n) {
219 ; CHECK-LABEL: @upper_and_lower_checks_2_dst6(
221 ; CHECK-NEXT: [[N_EXT:%.*]] = zext i32 [[N:%.*]] to i64
222 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[DST:%.*]], i64 [[N_EXT]]
223 ; CHECK-NEXT: [[DST_5:%.*]] = getelementptr i32, ptr [[DST]], i64 5
224 ; CHECK-NEXT: [[DST_5_ULT:%.*]] = icmp ult ptr [[DST_5]], [[UPPER]]
225 ; CHECK-NEXT: [[DST_5_UGE:%.*]] = icmp uge ptr [[DST_5]], [[DST]]
226 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[DST_5_ULT]], [[DST_5_UGE]]
227 ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
229 ; CHECK-NEXT: [[DST_6:%.*]] = getelementptr i32, ptr [[DST]], i64 6
230 ; CHECK-NEXT: [[C_DST_6_ULT:%.*]] = icmp ult ptr [[DST_6]], [[UPPER]]
231 ; CHECK-NEXT: [[TRUE_DST_6_UGE:%.*]] = icmp uge ptr [[DST_6]], [[DST]]
232 ; CHECK-NEXT: [[RES:%.*]] = and i1 [[C_DST_6_ULT]], [[TRUE_DST_6_UGE]]
233 ; CHECK-NEXT: ret i1 [[RES]]
235 ; CHECK-NEXT: ret i1 false
238 %n.ext = zext i32 %n to i64
239 %upper = getelementptr inbounds i32, ptr %dst, i64 %n.ext
240 %dst.5 = getelementptr i32, ptr %dst, i64 5
241 %dst.5.ult = icmp ult ptr %dst.5, %upper
242 %dst.5.uge = icmp uge ptr %dst.5, %dst
243 %and = and i1 %dst.5.ult, %dst.5.uge
244 br i1 %and, label %then, label %else
247 %dst.6 = getelementptr i32, ptr %dst, i64 6
248 %c.dst.6.ult = icmp ult ptr %dst.6, %upper
249 %true.dst.6.uge = icmp uge ptr %dst.6, %dst
250 %res = and i1 %c.dst.6.ult, %true.dst.6.uge
257 define i1 @upper_and_lower_checks_2_dst7(ptr %dst, i32 %n) {
258 ; CHECK-LABEL: @upper_and_lower_checks_2_dst7(
260 ; CHECK-NEXT: [[N_EXT:%.*]] = zext i32 [[N:%.*]] to i64
261 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[DST:%.*]], i64 [[N_EXT]]
262 ; CHECK-NEXT: [[DST_5:%.*]] = getelementptr i32, ptr [[DST]], i64 5
263 ; CHECK-NEXT: [[DST_5_ULT:%.*]] = icmp ult ptr [[DST_5]], [[UPPER]]
264 ; CHECK-NEXT: [[DST_5_UGE:%.*]] = icmp uge ptr [[DST_5]], [[DST]]
265 ; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[DST_5_ULT]], [[DST_5_UGE]]
266 ; CHECK-NEXT: br i1 [[OR_COND]], label [[THEN:%.*]], label [[ELSE:%.*]]
268 ; CHECK-NEXT: [[DST_7:%.*]] = getelementptr i32, ptr [[DST]], i64 7
269 ; CHECK-NEXT: [[C_DST_7_ULT:%.*]] = icmp ult ptr [[DST_7]], [[UPPER]]
270 ; CHECK-NEXT: [[C_DST_7_UGE:%.*]] = icmp uge ptr [[DST_7]], [[DST]]
271 ; CHECK-NEXT: [[RES:%.*]] = and i1 [[C_DST_7_ULT]], [[C_DST_7_UGE]]
272 ; CHECK-NEXT: ret i1 [[RES]]
274 ; CHECK-NEXT: ret i1 false
277 %n.ext = zext i32 %n to i64
278 %upper = getelementptr inbounds i32, ptr %dst, i64 %n.ext
279 %dst.5 = getelementptr i32, ptr %dst, i64 5
280 %dst.5.ult = icmp ult ptr %dst.5, %upper
281 %dst.5.uge = icmp uge ptr %dst.5, %dst
282 %or.cond = and i1 %dst.5.ult, %dst.5.uge
283 br i1 %or.cond, label %then, label %else
286 %dst.7 = getelementptr i32, ptr %dst, i64 7
287 %c.dst.7.ult = icmp ult ptr %dst.7, %upper
288 %c.dst.7.uge = icmp uge ptr %dst.7, %dst
289 %res = and i1 %c.dst.7.ult, %c.dst.7.uge
296 define i1 @upper_and_lower_checks_lt(ptr %dst, i32 %n) {
297 ; CHECK-LABEL: @upper_and_lower_checks_lt(
299 ; CHECK-NEXT: [[N_EXT:%.*]] = zext i32 [[N:%.*]] to i64
300 ; CHECK-NEXT: [[DST_5:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 [[N_EXT]]
301 ; CHECK-NEXT: [[DST_5_UGE:%.*]] = icmp uge ptr [[DST_5]], [[DST]]
302 ; CHECK-NEXT: [[N_EXT_UGE:%.*]] = icmp uge i64 [[N_EXT]], 3
303 ; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[DST_5_UGE]], [[N_EXT_UGE]]
304 ; CHECK-NEXT: br i1 [[OR_COND]], label [[THEN:%.*]], label [[ELSE:%.*]]
306 ; CHECK-NEXT: [[DST_3:%.*]] = getelementptr i32, ptr [[DST]], i64 3
307 ; CHECK-NEXT: [[TRUE_DST_3_UGE:%.*]] = icmp uge ptr [[DST_3]], [[DST]]
308 ; CHECK-NEXT: [[DST_4:%.*]] = getelementptr i32, ptr [[DST]], i64 4
309 ; CHECK-NEXT: [[C_DST_4_UGE:%.*]] = icmp uge ptr [[DST_4]], [[DST]]
310 ; CHECK-NEXT: [[RES_0:%.*]] = xor i1 [[TRUE_DST_3_UGE]], [[C_DST_4_UGE]]
311 ; CHECK-NEXT: ret i1 [[RES_0]]
313 ; CHECK-NEXT: ret i1 false
316 %n.ext = zext i32 %n to i64
317 %dst.5 = getelementptr i32, ptr %dst, i64 %n.ext
318 %dst.5.uge = icmp uge ptr %dst.5, %dst
319 %n.ext.uge = icmp uge i64 %n.ext, 3
320 %or.cond = and i1 %dst.5.uge, %n.ext.uge
321 br i1 %or.cond, label %then, label %else
324 %dst.3 = getelementptr i32, ptr %dst, i64 3
325 %true.dst.3.uge = icmp uge ptr %dst.3, %dst
326 %dst.4 = getelementptr i32, ptr %dst, i64 4
327 %c.dst.4.uge = icmp uge ptr %dst.4, %dst
328 %res.0 = xor i1 %true.dst.3.uge, %c.dst.4.uge