1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=correlated-propagation < %s | FileCheck %s
4 declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32)
6 declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32)
8 declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32)
10 declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32)
12 declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32)
14 declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32)
16 declare { i8, i1 } @llvm.umul.with.overflow.i8(i8, i8)
18 declare { <2 x i32>, <2 x i1> } @llvm.uadd.with.overflow.v2i32(<2 x i32>, <2 x i32>)
20 declare i8 @llvm.uadd.sat.i8(i8, i8)
21 declare i8 @llvm.sadd.sat.i8(i8, i8)
22 declare i8 @llvm.usub.sat.i8(i8, i8)
23 declare i8 @llvm.ssub.sat.i8(i8, i8)
24 declare <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8>, <2 x i8>)
26 declare void @llvm.trap()
29 define i32 @signed_add(i32 %x, i32 %y) {
30 ; CHECK-LABEL: @signed_add(
32 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[Y:%.*]], 0
33 ; CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LOR_LHS_FALSE:%.*]]
34 ; CHECK: land.lhs.true:
35 ; CHECK-NEXT: [[TMP0:%.*]] = sub nuw nsw i32 2147483647, [[Y]]
36 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[TMP0]], 0
37 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
38 ; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[CONT:%.*]]
40 ; CHECK-NEXT: tail call void @llvm.trap()
41 ; CHECK-NEXT: unreachable
43 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
44 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[TMP3]], [[X:%.*]]
45 ; CHECK-NEXT: br i1 [[CMP1]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
46 ; CHECK: lor.lhs.false:
47 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[Y]], 0
48 ; CHECK-NEXT: br i1 [[CMP2]], label [[LAND_LHS_TRUE3:%.*]], label [[COND_FALSE]]
49 ; CHECK: land.lhs.true3:
50 ; CHECK-NEXT: [[TMP4:%.*]] = sub nsw i32 -2147483648, [[Y]]
51 ; CHECK-NEXT: [[TMP5:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[TMP4]], 0
52 ; CHECK-NEXT: [[TMP6:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
53 ; CHECK-NEXT: br i1 [[TMP6]], label [[TRAP]], label [[CONT4:%.*]]
55 ; CHECK-NEXT: [[TMP7:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
56 ; CHECK-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[TMP7]], [[X]]
57 ; CHECK-NEXT: br i1 [[CMP5]], label [[COND_END]], label [[COND_FALSE]]
59 ; CHECK-NEXT: [[TMP8:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X]], i32 [[Y]])
60 ; CHECK-NEXT: [[TMP9:%.*]] = extractvalue { i32, i1 } [[TMP8]], 0
61 ; CHECK-NEXT: [[TMP10:%.*]] = extractvalue { i32, i1 } [[TMP8]], 1
62 ; CHECK-NEXT: br i1 [[TMP10]], label [[TRAP]], label [[COND_END]]
64 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[CONT4]] ], [ 0, [[CONT]] ], [ [[TMP9]], [[COND_FALSE]] ]
65 ; CHECK-NEXT: ret i32 [[COND]]
68 %cmp = icmp sgt i32 %y, 0
69 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
71 land.lhs.true: ; preds = %entry
72 %0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 2147483647, i32 %y)
73 %1 = extractvalue { i32, i1 } %0, 1
74 br i1 %1, label %trap, label %cont
76 trap: ; preds = %land.lhs.true, %land.lhs.true3, %cond.false
77 tail call void @llvm.trap()
80 cont: ; preds = %land.lhs.true
81 %2 = extractvalue { i32, i1 } %0, 0
82 %cmp1 = icmp slt i32 %2, %x
83 br i1 %cmp1, label %cond.end, label %cond.false
85 lor.lhs.false: ; preds = %entry
86 %cmp2 = icmp slt i32 %y, 0
87 br i1 %cmp2, label %land.lhs.true3, label %cond.false
89 land.lhs.true3: ; preds = %lor.lhs.false
90 %3 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 -2147483648, i32 %y)
91 %4 = extractvalue { i32, i1 } %3, 1
92 br i1 %4, label %trap, label %cont4
94 cont4: ; preds = %land.lhs.true3
95 %5 = extractvalue { i32, i1 } %3, 0
96 %cmp5 = icmp sgt i32 %5, %x
97 br i1 %cmp5, label %cond.end, label %cond.false
99 cond.false: ; preds = %cont, %cont4, %lor.lhs.false
100 %6 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 %y)
101 %7 = extractvalue { i32, i1 } %6, 0
102 %8 = extractvalue { i32, i1 } %6, 1
103 br i1 %8, label %trap, label %cond.end
105 cond.end: ; preds = %cond.false, %cont, %cont4
106 %cond = phi i32 [ 0, %cont4 ], [ 0, %cont ], [ %7, %cond.false ]
110 define i32 @unsigned_add(i32 %x, i32 %y) {
111 ; CHECK-LABEL: @unsigned_add(
113 ; CHECK-NEXT: [[TMP0:%.*]] = sub nuw nsw i32 -1, [[Y:%.*]]
114 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[TMP0]], 0
115 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
116 ; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[CONT:%.*]]
118 ; CHECK-NEXT: tail call void @llvm.trap()
119 ; CHECK-NEXT: unreachable
121 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
122 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[TMP3]], [[X:%.*]]
123 ; CHECK-NEXT: br i1 [[CMP1]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
125 ; CHECK-NEXT: [[TMP4:%.*]] = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X]], i32 [[Y]])
126 ; CHECK-NEXT: [[TMP5:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0
127 ; CHECK-NEXT: [[TMP6:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1
128 ; CHECK-NEXT: br i1 [[TMP6]], label [[TRAP]], label [[COND_END]]
130 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[CONT]] ], [ [[TMP5]], [[COND_FALSE]] ]
131 ; CHECK-NEXT: ret i32 [[COND]]
134 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 -1, i32 %y)
135 %1 = extractvalue { i32, i1 } %0, 1
136 br i1 %1, label %trap, label %cont
138 trap: ; preds = %cond.false, %entry
139 tail call void @llvm.trap()
142 cont: ; preds = %entry
143 %2 = extractvalue { i32, i1 } %0, 0
144 %cmp1 = icmp ult i32 %2, %x
145 br i1 %cmp1, label %cond.end, label %cond.false
147 cond.false: ; preds = %cont
148 %3 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)
149 %4 = extractvalue { i32, i1 } %3, 0
150 %5 = extractvalue { i32, i1 } %3, 1
151 br i1 %5, label %trap, label %cond.end
153 cond.end: ; preds = %cond.false, %cont
154 %cond = phi i32 [ 0, %cont ], [ %4, %cond.false ]
158 define i32 @signed_sub(i32 %x, i32 %y) {
159 ; CHECK-LABEL: @signed_sub(
161 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[Y:%.*]], 0
162 ; CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LOR_LHS_FALSE:%.*]]
163 ; CHECK: land.lhs.true:
164 ; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[Y]], 2147483647
165 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[TMP0]], 0
166 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
167 ; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[CONT:%.*]]
169 ; CHECK-NEXT: tail call void @llvm.trap()
170 ; CHECK-NEXT: unreachable
172 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
173 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[TMP3]], [[X:%.*]]
174 ; CHECK-NEXT: br i1 [[CMP1]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
175 ; CHECK: lor.lhs.false:
176 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[Y]], 0
177 ; CHECK-NEXT: br i1 [[CMP2]], label [[COND_FALSE]], label [[LAND_LHS_TRUE3:%.*]]
178 ; CHECK: land.lhs.true3:
179 ; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i32 [[Y]], -2147483648
180 ; CHECK-NEXT: [[TMP5:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[TMP4]], 0
181 ; CHECK-NEXT: [[TMP6:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
182 ; CHECK-NEXT: br i1 [[TMP6]], label [[TRAP]], label [[CONT4:%.*]]
184 ; CHECK-NEXT: [[TMP7:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
185 ; CHECK-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[TMP7]], [[X]]
186 ; CHECK-NEXT: br i1 [[CMP5]], label [[COND_END]], label [[COND_FALSE]]
188 ; CHECK-NEXT: [[TMP8:%.*]] = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 [[X]], i32 [[Y]])
189 ; CHECK-NEXT: [[TMP9:%.*]] = extractvalue { i32, i1 } [[TMP8]], 0
190 ; CHECK-NEXT: [[TMP10:%.*]] = extractvalue { i32, i1 } [[TMP8]], 1
191 ; CHECK-NEXT: br i1 [[TMP10]], label [[TRAP]], label [[COND_END]]
193 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[CONT4]] ], [ 0, [[CONT]] ], [ [[TMP9]], [[COND_FALSE]] ]
194 ; CHECK-NEXT: ret i32 [[COND]]
197 %cmp = icmp slt i32 %y, 0
198 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
200 land.lhs.true: ; preds = %entry
201 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %y, i32 2147483647)
202 %1 = extractvalue { i32, i1 } %0, 1
203 br i1 %1, label %trap, label %cont
205 trap: ; preds = %land.lhs.true, %land.lhs.true3, %cond.false
206 tail call void @llvm.trap()
209 cont: ; preds = %land.lhs.true
210 %2 = extractvalue { i32, i1 } %0, 0
211 %cmp1 = icmp slt i32 %2, %x
212 br i1 %cmp1, label %cond.end, label %cond.false
214 lor.lhs.false: ; preds = %entry
215 %cmp2 = icmp eq i32 %y, 0
216 br i1 %cmp2, label %cond.false, label %land.lhs.true3
218 land.lhs.true3: ; preds = %lor.lhs.false
219 %3 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %y, i32 -2147483648)
220 %4 = extractvalue { i32, i1 } %3, 1
221 br i1 %4, label %trap, label %cont4
223 cont4: ; preds = %land.lhs.true3
224 %5 = extractvalue { i32, i1 } %3, 0
225 %cmp5 = icmp sgt i32 %5, %x
226 br i1 %cmp5, label %cond.end, label %cond.false
228 cond.false: ; preds = %lor.lhs.false, %cont, %cont4
229 %6 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %x, i32 %y)
230 %7 = extractvalue { i32, i1 } %6, 0
231 %8 = extractvalue { i32, i1 } %6, 1
232 br i1 %8, label %trap, label %cond.end
234 cond.end: ; preds = %cond.false, %cont, %cont4
235 %cond = phi i32 [ 0, %cont4 ], [ 0, %cont ], [ %7, %cond.false ]
239 define i32 @unsigned_sub(i32 %x, i32 %y) {
240 ; CHECK-LABEL: @unsigned_sub(
242 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
243 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
245 ; CHECK-NEXT: [[TMP0:%.*]] = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 [[X]], i32 [[Y]])
246 ; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
247 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1
248 ; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[COND_END]]
250 ; CHECK-NEXT: tail call void @llvm.trap()
251 ; CHECK-NEXT: unreachable
253 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP1]], [[COND_FALSE]] ]
254 ; CHECK-NEXT: ret i32 [[COND]]
257 %cmp = icmp ult i32 %x, %y
258 br i1 %cmp, label %cond.end, label %cond.false
260 cond.false: ; preds = %entry
261 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %x, i32 %y)
262 %1 = extractvalue { i32, i1 } %0, 0
263 %2 = extractvalue { i32, i1 } %0, 1
264 br i1 %2, label %trap, label %cond.end
266 trap: ; preds = %cond.false
267 tail call void @llvm.trap()
270 cond.end: ; preds = %cond.false, %entry
271 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
275 define i32 @signed_add_r1(i32 %x) {
276 ; CHECK-LABEL: @signed_add_r1(
278 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 2147483647
279 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
281 ; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[X]], 1
282 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[TMP0]], 0
283 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
284 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
285 ; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]]
287 ; CHECK-NEXT: tail call void @llvm.trap()
288 ; CHECK-NEXT: unreachable
290 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ]
291 ; CHECK-NEXT: ret i32 [[COND]]
294 %cmp = icmp eq i32 %x, 2147483647
295 br i1 %cmp, label %cond.end, label %cond.false
297 cond.false: ; preds = %entry
298 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 1)
299 %1 = extractvalue { i32, i1 } %0, 0
300 %2 = extractvalue { i32, i1 } %0, 1
301 br i1 %2, label %trap, label %cond.end
303 trap: ; preds = %cond.false
304 tail call void @llvm.trap()
307 cond.end: ; preds = %cond.false, %entry
308 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
312 define i32 @unsigned_add_r1(i32 %x) {
313 ; CHECK-LABEL: @unsigned_add_r1(
315 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], -1
316 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
318 ; CHECK-NEXT: [[TMP0:%.*]] = add nuw i32 [[X]], 1
319 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[TMP0]], 0
320 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
321 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
322 ; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]]
324 ; CHECK-NEXT: tail call void @llvm.trap()
325 ; CHECK-NEXT: unreachable
327 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ]
328 ; CHECK-NEXT: ret i32 [[COND]]
331 %cmp = icmp eq i32 %x, -1
332 br i1 %cmp, label %cond.end, label %cond.false
334 cond.false: ; preds = %entry
335 %0 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 1)
336 %1 = extractvalue { i32, i1 } %0, 0
337 %2 = extractvalue { i32, i1 } %0, 1
338 br i1 %2, label %trap, label %cond.end
340 trap: ; preds = %cond.false
341 tail call void @llvm.trap()
344 cond.end: ; preds = %cond.false, %entry
345 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
349 define i32 @signed_sub_r1(i32 %x) {
350 ; CHECK-LABEL: @signed_sub_r1(
352 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], -2147483648
353 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
355 ; CHECK-NEXT: [[TMP0:%.*]] = sub nsw i32 [[X]], 1
356 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[TMP0]], 0
357 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
358 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
359 ; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]]
361 ; CHECK-NEXT: tail call void @llvm.trap()
362 ; CHECK-NEXT: unreachable
364 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ]
365 ; CHECK-NEXT: ret i32 [[COND]]
368 %cmp = icmp eq i32 %x, -2147483648
369 br i1 %cmp, label %cond.end, label %cond.false
371 cond.false: ; preds = %entry
372 %0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %x, i32 1)
373 %1 = extractvalue { i32, i1 } %0, 0
374 %2 = extractvalue { i32, i1 } %0, 1
375 br i1 %2, label %trap, label %cond.end
377 trap: ; preds = %cond.false
378 tail call void @llvm.trap()
381 cond.end: ; preds = %cond.false, %entry
382 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
386 define i32 @unsigned_sub_r1(i32 %x) {
387 ; CHECK-LABEL: @unsigned_sub_r1(
389 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
390 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
392 ; CHECK-NEXT: [[TMP0:%.*]] = sub nuw i32 [[X]], 1
393 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[TMP0]], 0
394 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
395 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
396 ; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]]
398 ; CHECK-NEXT: tail call void @llvm.trap()
399 ; CHECK-NEXT: unreachable
401 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ]
402 ; CHECK-NEXT: ret i32 [[COND]]
405 %cmp = icmp eq i32 %x, 0
406 br i1 %cmp, label %cond.end, label %cond.false
408 cond.false: ; preds = %entry
409 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %x, i32 1)
410 %1 = extractvalue { i32, i1 } %0, 0
411 %2 = extractvalue { i32, i1 } %0, 1
412 br i1 %2, label %trap, label %cond.end
414 trap: ; preds = %cond.false
415 tail call void @llvm.trap()
418 cond.end: ; preds = %cond.false, %entry
419 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
423 define i32 @signed_add_rn1(i32 %x) {
424 ; CHECK-LABEL: @signed_add_rn1(
426 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], -2147483648
427 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
429 ; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[X]], -1
430 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[TMP0]], 0
431 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
432 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
433 ; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]]
435 ; CHECK-NEXT: tail call void @llvm.trap()
436 ; CHECK-NEXT: unreachable
438 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ]
439 ; CHECK-NEXT: ret i32 [[COND]]
442 %cmp = icmp eq i32 %x, -2147483648
443 br i1 %cmp, label %cond.end, label %cond.false
445 cond.false: ; preds = %entry
446 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 -1)
447 %1 = extractvalue { i32, i1 } %0, 0
448 %2 = extractvalue { i32, i1 } %0, 1
449 br i1 %2, label %trap, label %cond.end
451 trap: ; preds = %cond.false
452 tail call void @llvm.trap()
455 cond.end: ; preds = %cond.false, %entry
456 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
460 define i32 @signed_sub_rn1(i32 %x) {
461 ; CHECK-LABEL: @signed_sub_rn1(
463 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 2147483647
464 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
466 ; CHECK-NEXT: [[TMP0:%.*]] = sub nsw i32 [[X]], -1
467 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[TMP0]], 0
468 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
469 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
470 ; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]]
472 ; CHECK-NEXT: tail call void @llvm.trap()
473 ; CHECK-NEXT: unreachable
475 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ]
476 ; CHECK-NEXT: ret i32 [[COND]]
479 %cmp = icmp eq i32 %x, 2147483647
480 br i1 %cmp, label %cond.end, label %cond.false
482 cond.false: ; preds = %entry
483 %0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %x, i32 -1)
484 %1 = extractvalue { i32, i1 } %0, 0
485 %2 = extractvalue { i32, i1 } %0, 1
486 br i1 %2, label %trap, label %cond.end
488 trap: ; preds = %cond.false
489 tail call void @llvm.trap()
492 cond.end: ; preds = %cond.false, %entry
493 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
497 define i32 @unsigned_mul(i32 %x) {
498 ; CHECK-LABEL: @unsigned_mul(
500 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], 10000
501 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
503 ; CHECK-NEXT: [[MULO1:%.*]] = mul nuw nsw i32 [[X]], 100
504 ; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[MULO1]], 0
505 ; CHECK-NEXT: [[RES:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
506 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1
507 ; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[COND_END]]
509 ; CHECK-NEXT: tail call void @llvm.trap()
510 ; CHECK-NEXT: unreachable
512 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RES]], [[COND_FALSE]] ]
513 ; CHECK-NEXT: ret i32 [[COND]]
516 %cmp = icmp ugt i32 %x, 10000
517 br i1 %cmp, label %cond.end, label %cond.false
519 cond.false: ; preds = %entry
520 %mulo = tail call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 100)
521 %res = extractvalue { i32, i1 } %mulo, 0
522 %ov = extractvalue { i32, i1 } %mulo, 1
523 br i1 %ov, label %trap, label %cond.end
525 trap: ; preds = %cond.false
526 tail call void @llvm.trap()
529 cond.end: ; preds = %cond.false, %entry
530 %cond = phi i32 [ 0, %entry ], [ %res, %cond.false ]
534 define i32 @signed_mul(i32 %x) {
535 ; CHECK-LABEL: @signed_mul(
537 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[X:%.*]], 10000
538 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], -10000
539 ; CHECK-NEXT: [[CMP3:%.*]] = or i1 [[CMP1]], [[CMP2]]
540 ; CHECK-NEXT: br i1 [[CMP3]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
542 ; CHECK-NEXT: [[MULO1:%.*]] = mul nsw i32 [[X]], 100
543 ; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[MULO1]], 0
544 ; CHECK-NEXT: [[RES:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
545 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1
546 ; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[COND_END]]
548 ; CHECK-NEXT: tail call void @llvm.trap()
549 ; CHECK-NEXT: unreachable
551 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RES]], [[COND_FALSE]] ]
552 ; CHECK-NEXT: ret i32 [[COND]]
555 %cmp1 = icmp sgt i32 %x, 10000
556 %cmp2 = icmp slt i32 %x, -10000
557 %cmp3 = or i1 %cmp1, %cmp2
558 br i1 %cmp3, label %cond.end, label %cond.false
560 cond.false: ; preds = %entry
561 %mulo = tail call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %x, i32 100)
562 %res = extractvalue { i32, i1 } %mulo, 0
563 %ov = extractvalue { i32, i1 } %mulo, 1
564 br i1 %ov, label %trap, label %cond.end
566 trap: ; preds = %cond.false
567 tail call void @llvm.trap()
570 cond.end: ; preds = %cond.false, %entry
571 %cond = phi i32 [ 0, %entry ], [ %res, %cond.false ]
575 declare i32 @bar(i32)
577 define void @unsigned_loop(i32 %i) {
578 ; CHECK-LABEL: @unsigned_loop(
580 ; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[I:%.*]], 0
581 ; CHECK-NEXT: br i1 [[CMP3]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
582 ; CHECK: while.body.preheader:
583 ; CHECK-NEXT: br label [[WHILE_BODY:%.*]]
585 ; CHECK-NEXT: [[I_ADDR_04:%.*]] = phi i32 [ [[TMP3:%.*]], [[CONT:%.*]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
586 ; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @bar(i32 [[I_ADDR_04]])
587 ; CHECK-NEXT: [[TMP0:%.*]] = sub nuw i32 [[I_ADDR_04]], 1
588 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[TMP0]], 0
589 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
590 ; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[CONT]]
592 ; CHECK-NEXT: tail call void @llvm.trap()
593 ; CHECK-NEXT: unreachable
595 ; CHECK-NEXT: [[TMP3]] = extractvalue { i32, i1 } [[TMP1]], 0
596 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP3]], 0
597 ; CHECK-NEXT: br i1 [[CMP]], label [[WHILE_END]], label [[WHILE_BODY]]
599 ; CHECK-NEXT: ret void
602 %cmp3 = icmp eq i32 %i, 0
603 br i1 %cmp3, label %while.end, label %while.body.preheader
605 while.body.preheader: ; preds = %entry
608 while.body: ; preds = %while.body.preheader, %cont
609 %i.addr.04 = phi i32 [ %2, %cont ], [ %i, %while.body.preheader ]
610 %call = tail call i32 @bar(i32 %i.addr.04)
611 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %i.addr.04, i32 1)
612 %1 = extractvalue { i32, i1 } %0, 1
613 br i1 %1, label %trap, label %cont
615 trap: ; preds = %while.body
616 tail call void @llvm.trap()
619 cont: ; preds = %while.body
620 %2 = extractvalue { i32, i1 } %0, 0
621 %cmp = icmp eq i32 %2, 0
622 br i1 %cmp, label %while.end, label %while.body
624 while.end: ; preds = %cont, %entry
628 define void @intrinsic_into_phi(i32 %n) {
629 ; CHECK-LABEL: @intrinsic_into_phi(
631 ; CHECK-NEXT: br label [[CONT:%.*]]
633 ; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[DOTLCSSA:%.*]], 1
634 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[TMP0]], 0
635 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
636 ; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[CONT]]
638 ; CHECK-NEXT: tail call void @llvm.trap()
639 ; CHECK-NEXT: unreachable
641 ; CHECK-NEXT: [[TMP3:%.*]] = phi { i32, i1 } [ zeroinitializer, [[ENTRY:%.*]] ], [ [[TMP1]], [[FOR_COND:%.*]] ]
642 ; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i32, i1 } [[TMP3]], 0
643 ; CHECK-NEXT: [[CALL9:%.*]] = tail call i32 @bar(i32 [[TMP4]])
644 ; CHECK-NEXT: [[TOBOOL10:%.*]] = icmp eq i32 [[CALL9]], 0
645 ; CHECK-NEXT: br i1 [[TOBOOL10]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
646 ; CHECK: while.body.preheader:
647 ; CHECK-NEXT: br label [[WHILE_BODY:%.*]]
649 ; CHECK-NEXT: [[TMP5:%.*]] = extractvalue { i32, i1 } [[TMP7:%.*]], 0
650 ; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @bar(i32 [[TMP5]])
651 ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[CALL]], 0
652 ; CHECK-NEXT: br i1 [[TOBOOL]], label [[WHILE_END]], label [[WHILE_BODY]]
654 ; CHECK-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP5]], [[WHILE_COND:%.*]] ], [ [[TMP4]], [[WHILE_BODY_PREHEADER]] ]
655 ; CHECK-NEXT: [[TMP7]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[TMP6]], i32 1)
656 ; CHECK-NEXT: [[TMP8:%.*]] = extractvalue { i32, i1 } [[TMP7]], 1
657 ; CHECK-NEXT: br i1 [[TMP8]], label [[TRAP]], label [[WHILE_COND]]
659 ; CHECK-NEXT: [[DOTLCSSA]] = phi i32 [ [[TMP4]], [[CONT]] ], [ [[TMP5]], [[WHILE_COND]] ]
660 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[DOTLCSSA]], [[N:%.*]]
661 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_COND]], label [[CLEANUP2:%.*]]
663 ; CHECK-NEXT: ret void
668 for.cond: ; preds = %while.end
669 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %.lcssa, i32 1)
670 %1 = extractvalue { i32, i1 } %0, 1
671 br i1 %1, label %trap, label %cont
673 trap: ; preds = %for.cond, %while.body
674 tail call void @llvm.trap()
677 cont: ; preds = %entry, %for.cond
678 %2 = phi { i32, i1 } [ zeroinitializer, %entry ], [ %0, %for.cond ]
679 %3 = extractvalue { i32, i1 } %2, 0
680 %call9 = tail call i32 @bar(i32 %3)
681 %tobool10 = icmp eq i32 %call9, 0
682 br i1 %tobool10, label %while.end, label %while.body.preheader
684 while.body.preheader: ; preds = %cont
687 while.cond: ; preds = %while.body
688 %4 = extractvalue { i32, i1 } %6, 0
689 %call = tail call i32 @bar(i32 %4)
690 %tobool = icmp eq i32 %call, 0
691 br i1 %tobool, label %while.end, label %while.body
693 while.body: ; preds = %while.body.preheader, %while.cond
694 %5 = phi i32 [ %4, %while.cond ], [ %3, %while.body.preheader ]
695 %6 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %5, i32 1)
696 %7 = extractvalue { i32, i1 } %6, 1
697 br i1 %7, label %trap, label %while.cond
699 while.end: ; preds = %while.cond, %cont
700 %.lcssa = phi i32 [ %3, %cont ], [ %4, %while.cond ]
701 %cmp = icmp slt i32 %.lcssa, %n
702 br i1 %cmp, label %for.cond, label %cleanup2
704 cleanup2: ; preds = %while.end
708 define { i8, i1 } @signed_mul_constant_folding() {
709 ; CHECK-LABEL: @signed_mul_constant_folding(
710 ; CHECK-NEXT: ret { i8, i1 } { i8 2, i1 false }
712 %mul = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 1, i8 2)
716 define { <2 x i32>, <2 x i1> } @uaddo_vec(<2 x i32> %a) {
717 ; CHECK-LABEL: @uaddo_vec(
718 ; CHECK-NEXT: [[ADD:%.*]] = call { <2 x i32>, <2 x i1> } @llvm.uadd.with.overflow.v2i32(<2 x i32> [[A:%.*]], <2 x i32> splat (i32 1))
719 ; CHECK-NEXT: ret { <2 x i32>, <2 x i1> } [[ADD]]
721 %add = call { <2 x i32>, <2 x i1> } @llvm.uadd.with.overflow.v2i32(<2 x i32> %a, <2 x i32> <i32 1, i32 1>)
722 ret { <2 x i32>, <2 x i1> } %add
726 define i8 @uadd_sat_no_unsigned_overflow(i8 %x) {
727 ; CHECK-LABEL: @uadd_sat_no_unsigned_overflow(
728 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], 100
729 ; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]]
731 ; CHECK-NEXT: call void @llvm.trap()
732 ; CHECK-NEXT: unreachable
734 ; CHECK-NEXT: [[RES1:%.*]] = add nuw i8 [[X]], 100
735 ; CHECK-NEXT: ret i8 [[RES1]]
737 %cmp = icmp ugt i8 %x, 100
738 br i1 %cmp, label %trap, label %cont
741 call void @llvm.trap()
745 %res = call i8 @llvm.uadd.sat.i8(i8 %x, i8 100)
749 define i8 @uadd_sat_no_overflow(i8 %x) {
750 ; CHECK-LABEL: @uadd_sat_no_overflow(
751 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], 27
752 ; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]]
754 ; CHECK-NEXT: call void @llvm.trap()
755 ; CHECK-NEXT: unreachable
757 ; CHECK-NEXT: [[RES1:%.*]] = add nuw nsw i8 [[X]], 100
758 ; CHECK-NEXT: ret i8 [[RES1]]
760 %cmp = icmp ugt i8 %x, 27
761 br i1 %cmp, label %trap, label %cont
764 call void @llvm.trap()
768 %res = call i8 @llvm.uadd.sat.i8(i8 %x, i8 100)
772 define i8 @sadd_sat_no_signed_overflow(i8 %x) {
773 ; CHECK-LABEL: @sadd_sat_no_signed_overflow(
774 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], 100
775 ; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]]
777 ; CHECK-NEXT: call void @llvm.trap()
778 ; CHECK-NEXT: unreachable
780 ; CHECK-NEXT: [[RES1:%.*]] = add nsw i8 [[X]], 20
781 ; CHECK-NEXT: ret i8 [[RES1]]
783 %cmp = icmp sgt i8 %x, 100
784 br i1 %cmp, label %trap, label %cont
787 call void @llvm.trap()
791 %res = call i8 @llvm.sadd.sat.i8(i8 %x, i8 20)
795 define i8 @sadd_sat_no_overflow(i8 %x) {
796 ; CHECK-LABEL: @sadd_sat_no_overflow(
797 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], 107
798 ; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]]
800 ; CHECK-NEXT: call void @llvm.trap()
801 ; CHECK-NEXT: unreachable
803 ; CHECK-NEXT: [[RES1:%.*]] = add nuw nsw i8 [[X]], 20
804 ; CHECK-NEXT: ret i8 [[RES1]]
806 %cmp = icmp ugt i8 %x, 107
807 br i1 %cmp, label %trap, label %cont
810 call void @llvm.trap()
814 %res = call i8 @llvm.sadd.sat.i8(i8 %x, i8 20)
818 define i8 @usub_sat_no_unsigned_overflow(i8 %x) {
819 ; CHECK-LABEL: @usub_sat_no_unsigned_overflow(
820 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], 100
821 ; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]]
823 ; CHECK-NEXT: call void @llvm.trap()
824 ; CHECK-NEXT: unreachable
826 ; CHECK-NEXT: [[RES1:%.*]] = sub nuw i8 [[X]], 100
827 ; CHECK-NEXT: ret i8 [[RES1]]
829 %cmp = icmp ult i8 %x, 100
830 br i1 %cmp, label %trap, label %cont
833 call void @llvm.trap()
837 %res = call i8 @llvm.usub.sat.i8(i8 %x, i8 100)
841 define i8 @usub_sat_no_overflow(i8 %x) {
842 ; CHECK-LABEL: @usub_sat_no_overflow(
843 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], -28
844 ; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]]
846 ; CHECK-NEXT: call void @llvm.trap()
847 ; CHECK-NEXT: unreachable
849 ; CHECK-NEXT: [[RES1:%.*]] = sub nuw nsw i8 [[X]], 100
850 ; CHECK-NEXT: ret i8 [[RES1]]
852 %cmp = icmp ult i8 %x, 228
853 br i1 %cmp, label %trap, label %cont
856 call void @llvm.trap()
860 %res = call i8 @llvm.usub.sat.i8(i8 %x, i8 100)
864 define i8 @ssub_sat_no_signed_overflow(i8 %x) {
865 ; CHECK-LABEL: @ssub_sat_no_signed_overflow(
866 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], -100
867 ; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]]
869 ; CHECK-NEXT: call void @llvm.trap()
870 ; CHECK-NEXT: unreachable
872 ; CHECK-NEXT: [[RES1:%.*]] = sub nsw i8 [[X]], 20
873 ; CHECK-NEXT: ret i8 [[RES1]]
875 %cmp = icmp slt i8 %x, -100
876 br i1 %cmp, label %trap, label %cont
879 call void @llvm.trap()
883 %res = call i8 @llvm.ssub.sat.i8(i8 %x, i8 20)
887 define i8 @ssub_sat_no_overflow(i8 %x) {
888 ; CHECK-LABEL: @ssub_sat_no_overflow(
889 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], -108
890 ; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]]
892 ; CHECK-NEXT: call void @llvm.trap()
893 ; CHECK-NEXT: unreachable
895 ; CHECK-NEXT: [[RES1:%.*]] = sub nuw nsw i8 [[X]], 20
896 ; CHECK-NEXT: ret i8 [[RES1]]
898 %cmp = icmp ult i8 %x, 148
899 br i1 %cmp, label %trap, label %cont
902 call void @llvm.trap()
906 %res = call i8 @llvm.ssub.sat.i8(i8 %x, i8 20)
910 define <2 x i8> @uadd_sat_vec(<2 x i8> %a) {
911 ; CHECK-LABEL: @uadd_sat_vec(
912 ; CHECK-NEXT: [[ADD:%.*]] = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> splat (i8 1))
913 ; CHECK-NEXT: ret <2 x i8> [[ADD]]
915 %add = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 1, i8 1>)
919 ; In the following tests, we should first simplify a with.overflow intrinsic
920 ; to a simple arithmetic operation and insertvalue, but also simplify the
921 ; subsequent comparison that is based on it.
923 define i1 @sadd_and_cmp(i32 %x, i32 %y) #0 {
924 ; CHECK-LABEL: @sadd_and_cmp(
926 ; CHECK-NEXT: [[X_OFFSET:%.*]] = add i32 [[X:%.*]], 9
927 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X_OFFSET]], 19
928 ; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]]
930 ; CHECK-NEXT: [[Y_OFFSET:%.*]] = add i32 [[Y:%.*]], 9
931 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y_OFFSET]], 19
932 ; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]]
934 ; CHECK-NEXT: [[RES1:%.*]] = add nsw i32 [[X]], [[Y]]
935 ; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[RES1]], 0
936 ; CHECK-NEXT: [[ADD:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
937 ; CHECK-NEXT: br label [[OUT]]
939 ; CHECK-NEXT: ret i1 true
942 %x.offset = add i32 %x, 9
943 %cmp1 = icmp ult i32 %x.offset, 19
944 br i1 %cmp1, label %cont1, label %out
947 %y.offset = add i32 %y, 9
948 %cmp2 = icmp ult i32 %y.offset, 19
949 br i1 %cmp2, label %cont2, label %out
952 ; x = [-9,10), y = [-9,10)
953 %res = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 %y)
954 %add = extractvalue { i32, i1 } %res, 0
956 %cmp3 = icmp slt i32 %add, 19
960 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont2 ]
965 define i1 @uadd_and_cmp(i32 %x, i32 %y) #0 {
966 ; CHECK-LABEL: @uadd_and_cmp(
968 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 10
969 ; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]]
971 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 10
972 ; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]]
974 ; CHECK-NEXT: [[RES1:%.*]] = add nuw nsw i32 [[X]], [[Y]]
975 ; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[RES1]], 0
976 ; CHECK-NEXT: [[ADD:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
977 ; CHECK-NEXT: br label [[OUT]]
979 ; CHECK-NEXT: ret i1 true
982 %cmp1 = icmp ult i32 %x, 10
983 br i1 %cmp1, label %cont1, label %out
986 %cmp2 = icmp ult i32 %y, 10
987 br i1 %cmp2, label %cont2, label %out
990 %res = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)
991 %add = extractvalue { i32, i1 } %res, 0
992 %cmp3 = icmp ult i32 %add, 19
996 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont2 ]
1000 define i1 @ssub_and_cmp(i32 %x, i32 %y) #0 {
1001 ; CHECK-LABEL: @ssub_and_cmp(
1002 ; CHECK-NEXT: entry:
1003 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 10
1004 ; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]]
1006 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 10
1007 ; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]]
1009 ; CHECK-NEXT: [[OFFSET:%.*]] = add nuw nsw i32 [[X]], 9
1010 ; CHECK-NEXT: [[RES1:%.*]] = sub nuw nsw i32 [[OFFSET]], [[Y]]
1011 ; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[RES1]], 0
1012 ; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
1013 ; CHECK-NEXT: br label [[OUT]]
1015 ; CHECK-NEXT: ret i1 true
1018 %cmp1 = icmp ult i32 %x, 10
1019 br i1 %cmp1, label %cont1, label %out
1022 %cmp2 = icmp ult i32 %y, 10
1023 br i1 %cmp2, label %cont2, label %out
1026 %offset = add i32 %x, 9
1027 ; x = [0,10), y = [0,10), offset = [9,19)
1028 %res = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %offset, i32 %y)
1029 %sub = extractvalue { i32, i1 } %res, 0
1030 %cmp3 = icmp ult i32 %sub, 19
1034 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont2 ]
1038 define i1 @usub_and_cmp(i32 %x, i32 %y) #0 {
1039 ; CHECK-LABEL: @usub_and_cmp(
1040 ; CHECK-NEXT: entry:
1041 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 10
1042 ; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]]
1044 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 10
1045 ; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]]
1047 ; CHECK-NEXT: [[OFFSET:%.*]] = add nuw nsw i32 [[X]], 9
1048 ; CHECK-NEXT: [[RES1:%.*]] = sub nuw nsw i32 [[OFFSET]], [[Y]]
1049 ; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[RES1]], 0
1050 ; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
1051 ; CHECK-NEXT: br label [[OUT]]
1053 ; CHECK-NEXT: ret i1 true
1056 %cmp1 = icmp ult i32 %x, 10
1057 br i1 %cmp1, label %cont1, label %out
1060 %cmp2 = icmp ult i32 %y, 10
1061 br i1 %cmp2, label %cont2, label %out
1064 %offset = add i32 %x, 9
1065 ; x = [0,10), y = [0,10), offset = [9,19)
1066 %res = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %offset, i32 %y)
1067 %sub = extractvalue { i32, i1 } %res, 0
1068 %cmp3 = icmp ult i32 %sub, 19
1072 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont2 ]
1076 define i1 @smul_and_cmp(i32 %x, i32 %y) #0 {
1077 ; CHECK-LABEL: @smul_and_cmp(
1078 ; CHECK-NEXT: entry:
1079 ; CHECK-NEXT: [[X_OFFSET:%.*]] = add i32 [[X:%.*]], 9
1080 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X_OFFSET]], 19
1081 ; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]]
1083 ; CHECK-NEXT: [[Y_OFFSET:%.*]] = add i32 [[Y:%.*]], 9
1084 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y_OFFSET]], 19
1085 ; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]]
1087 ; CHECK-NEXT: [[RES1:%.*]] = mul nsw i32 [[X]], [[Y]]
1088 ; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[RES1]], 0
1089 ; CHECK-NEXT: [[MUL:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
1090 ; CHECK-NEXT: br label [[OUT]]
1092 ; CHECK-NEXT: ret i1 true
1095 %x.offset = add i32 %x, 9
1096 %cmp1 = icmp ult i32 %x.offset, 19
1097 br i1 %cmp1, label %cont1, label %out
1100 %y.offset = add i32 %y, 9
1101 %cmp2 = icmp ult i32 %y.offset, 19
1102 br i1 %cmp2, label %cont2, label %out
1105 ; x = [-9,10), y = [-9,10)
1106 %res = tail call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %x, i32 %y)
1107 %mul = extractvalue { i32, i1 } %res, 0
1108 %cmp3 = icmp sle i32 %mul, 81
1109 %cmp4 = icmp sge i32 %mul, -81
1110 %cmp5 = and i1 %cmp3, %cmp4
1114 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp5, %cont2 ]
1118 define i1 @umul_and_cmp(i32 %x, i32 %y) #0 {
1119 ; CHECK-LABEL: @umul_and_cmp(
1120 ; CHECK-NEXT: entry:
1121 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 100
1122 ; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]]
1124 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 100
1125 ; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]]
1127 ; CHECK-NEXT: [[RES1:%.*]] = mul nuw nsw i32 [[X]], [[Y]]
1128 ; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[RES1]], 0
1129 ; CHECK-NEXT: [[MUL:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
1130 ; CHECK-NEXT: br label [[OUT]]
1132 ; CHECK-NEXT: ret i1 true
1135 %cmp1 = icmp ult i32 %x, 100
1136 br i1 %cmp1, label %cont1, label %out
1139 %cmp2 = icmp ult i32 %y, 100
1140 br i1 %cmp2, label %cont2, label %out
1143 %res = tail call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y)
1144 %mul = extractvalue { i32, i1 } %res, 0
1145 %cmp3 = icmp ule i32 %mul, 9801
1149 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont2 ]
1153 define i8 @uadd_sat_undef_range(i8 %x) {
1154 ; CHECK-LABEL: @uadd_sat_undef_range(
1155 ; CHECK-NEXT: entry:
1156 ; CHECK-NEXT: switch i8 [[X:%.*]], label [[JOIN:%.*]] [
1157 ; CHECK-NEXT: i8 1, label [[CASE1:%.*]]
1158 ; CHECK-NEXT: i8 2, label [[CASE2:%.*]]
1161 ; CHECK-NEXT: br label [[JOIN]]
1163 ; CHECK-NEXT: br label [[JOIN]]
1165 ; CHECK-NEXT: [[PHI:%.*]] = phi i8 [ 1, [[CASE1]] ], [ 2, [[CASE2]] ], [ undef, [[ENTRY:%.*]] ]
1166 ; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[PHI]], i8 100)
1167 ; CHECK-NEXT: ret i8 [[RES]]
1170 switch i8 %x, label %join [
1182 %phi = phi i8 [ 1, %case1 ], [ 2, %case2 ], [ undef, %entry ]
1183 %res = call i8 @llvm.uadd.sat.i8(i8 %phi, i8 100)