1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -correlated-propagation < %s | FileCheck %s
4 ; Check that debug locations are preserved. For more info see:
5 ; https://llvm.org/docs/SourceLevelDebugging.html#fixing-errors
6 ; RUN: opt < %s -enable-debugify -correlated-propagation -S 2>&1 | \
7 ; RUN: FileCheck %s -check-prefix=DEBUG
8 ; DEBUG: CheckModuleDebugify: PASS
10 declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32)
12 declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32)
14 declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32)
16 declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32)
18 declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32)
20 declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32)
22 declare { i8, i1 } @llvm.umul.with.overflow.i8(i8, i8)
24 declare { <2 x i32>, <2 x i1> } @llvm.uadd.with.overflow.v2i32(<2 x i32>, <2 x i32>)
26 declare i8 @llvm.uadd.sat.i8(i8, i8)
27 declare i8 @llvm.sadd.sat.i8(i8, i8)
28 declare i8 @llvm.usub.sat.i8(i8, i8)
29 declare i8 @llvm.ssub.sat.i8(i8, i8)
30 declare <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8>, <2 x i8>)
32 declare void @llvm.trap()
35 define i32 @signed_add(i32 %x, i32 %y) {
36 ; CHECK-LABEL: @signed_add(
38 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[Y:%.*]], 0
39 ; CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LOR_LHS_FALSE:%.*]]
40 ; CHECK: land.lhs.true:
41 ; CHECK-NEXT: [[TMP0:%.*]] = sub nuw nsw i32 2147483647, [[Y]]
42 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0
43 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
44 ; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[CONT:%.*]]
46 ; CHECK-NEXT: tail call void @llvm.trap()
47 ; CHECK-NEXT: unreachable
49 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
50 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[TMP3]], [[X:%.*]]
51 ; CHECK-NEXT: br i1 [[CMP1]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
52 ; CHECK: lor.lhs.false:
53 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[Y]], 0
54 ; CHECK-NEXT: br i1 [[CMP2]], label [[LAND_LHS_TRUE3:%.*]], label [[COND_FALSE]]
55 ; CHECK: land.lhs.true3:
56 ; CHECK-NEXT: [[TMP4:%.*]] = sub nsw i32 -2147483648, [[Y]]
57 ; CHECK-NEXT: [[TMP5:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP4]], 0
58 ; CHECK-NEXT: [[TMP6:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
59 ; CHECK-NEXT: br i1 [[TMP6]], label [[TRAP]], label [[CONT4:%.*]]
61 ; CHECK-NEXT: [[TMP7:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
62 ; CHECK-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[TMP7]], [[X]]
63 ; CHECK-NEXT: br i1 [[CMP5]], label [[COND_END]], label [[COND_FALSE]]
65 ; CHECK-NEXT: [[TMP8:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X]], i32 [[Y]])
66 ; CHECK-NEXT: [[TMP9:%.*]] = extractvalue { i32, i1 } [[TMP8]], 0
67 ; CHECK-NEXT: [[TMP10:%.*]] = extractvalue { i32, i1 } [[TMP8]], 1
68 ; CHECK-NEXT: br i1 [[TMP10]], label [[TRAP]], label [[COND_END]]
70 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[CONT4]] ], [ 0, [[CONT]] ], [ [[TMP9]], [[COND_FALSE]] ]
71 ; CHECK-NEXT: ret i32 [[COND]]
74 %cmp = icmp sgt i32 %y, 0
75 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
77 land.lhs.true: ; preds = %entry
78 %0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 2147483647, i32 %y)
79 %1 = extractvalue { i32, i1 } %0, 1
80 br i1 %1, label %trap, label %cont
82 trap: ; preds = %land.lhs.true, %land.lhs.true3, %cond.false
83 tail call void @llvm.trap()
86 cont: ; preds = %land.lhs.true
87 %2 = extractvalue { i32, i1 } %0, 0
88 %cmp1 = icmp slt i32 %2, %x
89 br i1 %cmp1, label %cond.end, label %cond.false
91 lor.lhs.false: ; preds = %entry
92 %cmp2 = icmp slt i32 %y, 0
93 br i1 %cmp2, label %land.lhs.true3, label %cond.false
95 land.lhs.true3: ; preds = %lor.lhs.false
96 %3 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 -2147483648, i32 %y)
97 %4 = extractvalue { i32, i1 } %3, 1
98 br i1 %4, label %trap, label %cont4
100 cont4: ; preds = %land.lhs.true3
101 %5 = extractvalue { i32, i1 } %3, 0
102 %cmp5 = icmp sgt i32 %5, %x
103 br i1 %cmp5, label %cond.end, label %cond.false
105 cond.false: ; preds = %cont, %cont4, %lor.lhs.false
106 %6 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 %y)
107 %7 = extractvalue { i32, i1 } %6, 0
108 %8 = extractvalue { i32, i1 } %6, 1
109 br i1 %8, label %trap, label %cond.end
111 cond.end: ; preds = %cond.false, %cont, %cont4
112 %cond = phi i32 [ 0, %cont4 ], [ 0, %cont ], [ %7, %cond.false ]
116 define i32 @unsigned_add(i32 %x, i32 %y) {
117 ; CHECK-LABEL: @unsigned_add(
119 ; CHECK-NEXT: [[TMP0:%.*]] = sub nuw nsw i32 -1, [[Y:%.*]]
120 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0
121 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
122 ; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[CONT:%.*]]
124 ; CHECK-NEXT: tail call void @llvm.trap()
125 ; CHECK-NEXT: unreachable
127 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
128 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[TMP3]], [[X:%.*]]
129 ; CHECK-NEXT: br i1 [[CMP1]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
131 ; CHECK-NEXT: [[TMP4:%.*]] = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X]], i32 [[Y]])
132 ; CHECK-NEXT: [[TMP5:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0
133 ; CHECK-NEXT: [[TMP6:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1
134 ; CHECK-NEXT: br i1 [[TMP6]], label [[TRAP]], label [[COND_END]]
136 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[CONT]] ], [ [[TMP5]], [[COND_FALSE]] ]
137 ; CHECK-NEXT: ret i32 [[COND]]
140 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 -1, i32 %y)
141 %1 = extractvalue { i32, i1 } %0, 1
142 br i1 %1, label %trap, label %cont
144 trap: ; preds = %cond.false, %entry
145 tail call void @llvm.trap()
148 cont: ; preds = %entry
149 %2 = extractvalue { i32, i1 } %0, 0
150 %cmp1 = icmp ult i32 %2, %x
151 br i1 %cmp1, label %cond.end, label %cond.false
153 cond.false: ; preds = %cont
154 %3 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)
155 %4 = extractvalue { i32, i1 } %3, 0
156 %5 = extractvalue { i32, i1 } %3, 1
157 br i1 %5, label %trap, label %cond.end
159 cond.end: ; preds = %cond.false, %cont
160 %cond = phi i32 [ 0, %cont ], [ %4, %cond.false ]
164 define i32 @signed_sub(i32 %x, i32 %y) {
165 ; CHECK-LABEL: @signed_sub(
167 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[Y:%.*]], 0
168 ; CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LOR_LHS_FALSE:%.*]]
169 ; CHECK: land.lhs.true:
170 ; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[Y]], 2147483647
171 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0
172 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
173 ; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[CONT:%.*]]
175 ; CHECK-NEXT: tail call void @llvm.trap()
176 ; CHECK-NEXT: unreachable
178 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
179 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[TMP3]], [[X:%.*]]
180 ; CHECK-NEXT: br i1 [[CMP1]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
181 ; CHECK: lor.lhs.false:
182 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[Y]], 0
183 ; CHECK-NEXT: br i1 [[CMP2]], label [[COND_FALSE]], label [[LAND_LHS_TRUE3:%.*]]
184 ; CHECK: land.lhs.true3:
185 ; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i32 [[Y]], -2147483648
186 ; CHECK-NEXT: [[TMP5:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP4]], 0
187 ; CHECK-NEXT: [[TMP6:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
188 ; CHECK-NEXT: br i1 [[TMP6]], label [[TRAP]], label [[CONT4:%.*]]
190 ; CHECK-NEXT: [[TMP7:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
191 ; CHECK-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[TMP7]], [[X]]
192 ; CHECK-NEXT: br i1 [[CMP5]], label [[COND_END]], label [[COND_FALSE]]
194 ; CHECK-NEXT: [[TMP8:%.*]] = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 [[X]], i32 [[Y]])
195 ; CHECK-NEXT: [[TMP9:%.*]] = extractvalue { i32, i1 } [[TMP8]], 0
196 ; CHECK-NEXT: [[TMP10:%.*]] = extractvalue { i32, i1 } [[TMP8]], 1
197 ; CHECK-NEXT: br i1 [[TMP10]], label [[TRAP]], label [[COND_END]]
199 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[CONT4]] ], [ 0, [[CONT]] ], [ [[TMP9]], [[COND_FALSE]] ]
200 ; CHECK-NEXT: ret i32 [[COND]]
203 %cmp = icmp slt i32 %y, 0
204 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
206 land.lhs.true: ; preds = %entry
207 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %y, i32 2147483647)
208 %1 = extractvalue { i32, i1 } %0, 1
209 br i1 %1, label %trap, label %cont
211 trap: ; preds = %land.lhs.true, %land.lhs.true3, %cond.false
212 tail call void @llvm.trap()
215 cont: ; preds = %land.lhs.true
216 %2 = extractvalue { i32, i1 } %0, 0
217 %cmp1 = icmp slt i32 %2, %x
218 br i1 %cmp1, label %cond.end, label %cond.false
220 lor.lhs.false: ; preds = %entry
221 %cmp2 = icmp eq i32 %y, 0
222 br i1 %cmp2, label %cond.false, label %land.lhs.true3
224 land.lhs.true3: ; preds = %lor.lhs.false
225 %3 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %y, i32 -2147483648)
226 %4 = extractvalue { i32, i1 } %3, 1
227 br i1 %4, label %trap, label %cont4
229 cont4: ; preds = %land.lhs.true3
230 %5 = extractvalue { i32, i1 } %3, 0
231 %cmp5 = icmp sgt i32 %5, %x
232 br i1 %cmp5, label %cond.end, label %cond.false
234 cond.false: ; preds = %lor.lhs.false, %cont, %cont4
235 %6 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %x, i32 %y)
236 %7 = extractvalue { i32, i1 } %6, 0
237 %8 = extractvalue { i32, i1 } %6, 1
238 br i1 %8, label %trap, label %cond.end
240 cond.end: ; preds = %cond.false, %cont, %cont4
241 %cond = phi i32 [ 0, %cont4 ], [ 0, %cont ], [ %7, %cond.false ]
245 define i32 @unsigned_sub(i32 %x, i32 %y) {
246 ; CHECK-LABEL: @unsigned_sub(
248 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
249 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
251 ; CHECK-NEXT: [[TMP0:%.*]] = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 [[X]], i32 [[Y]])
252 ; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
253 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1
254 ; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[COND_END]]
256 ; CHECK-NEXT: tail call void @llvm.trap()
257 ; CHECK-NEXT: unreachable
259 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP1]], [[COND_FALSE]] ]
260 ; CHECK-NEXT: ret i32 [[COND]]
263 %cmp = icmp ult i32 %x, %y
264 br i1 %cmp, label %cond.end, label %cond.false
266 cond.false: ; preds = %entry
267 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %x, i32 %y)
268 %1 = extractvalue { i32, i1 } %0, 0
269 %2 = extractvalue { i32, i1 } %0, 1
270 br i1 %2, label %trap, label %cond.end
272 trap: ; preds = %cond.false
273 tail call void @llvm.trap()
276 cond.end: ; preds = %cond.false, %entry
277 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
281 define i32 @signed_add_r1(i32 %x) {
282 ; CHECK-LABEL: @signed_add_r1(
284 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 2147483647
285 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
287 ; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[X]], 1
288 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0
289 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
290 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
291 ; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]]
293 ; CHECK-NEXT: tail call void @llvm.trap()
294 ; CHECK-NEXT: unreachable
296 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ]
297 ; CHECK-NEXT: ret i32 [[COND]]
300 %cmp = icmp eq i32 %x, 2147483647
301 br i1 %cmp, label %cond.end, label %cond.false
303 cond.false: ; preds = %entry
304 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 1)
305 %1 = extractvalue { i32, i1 } %0, 0
306 %2 = extractvalue { i32, i1 } %0, 1
307 br i1 %2, label %trap, label %cond.end
309 trap: ; preds = %cond.false
310 tail call void @llvm.trap()
313 cond.end: ; preds = %cond.false, %entry
314 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
318 define i32 @unsigned_add_r1(i32 %x) {
319 ; CHECK-LABEL: @unsigned_add_r1(
321 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], -1
322 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
324 ; CHECK-NEXT: [[TMP0:%.*]] = add nuw i32 [[X]], 1
325 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0
326 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
327 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
328 ; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]]
330 ; CHECK-NEXT: tail call void @llvm.trap()
331 ; CHECK-NEXT: unreachable
333 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ]
334 ; CHECK-NEXT: ret i32 [[COND]]
337 %cmp = icmp eq i32 %x, -1
338 br i1 %cmp, label %cond.end, label %cond.false
340 cond.false: ; preds = %entry
341 %0 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 1)
342 %1 = extractvalue { i32, i1 } %0, 0
343 %2 = extractvalue { i32, i1 } %0, 1
344 br i1 %2, label %trap, label %cond.end
346 trap: ; preds = %cond.false
347 tail call void @llvm.trap()
350 cond.end: ; preds = %cond.false, %entry
351 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
355 define i32 @signed_sub_r1(i32 %x) {
356 ; CHECK-LABEL: @signed_sub_r1(
358 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], -2147483648
359 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
361 ; CHECK-NEXT: [[TMP0:%.*]] = sub nsw i32 [[X]], 1
362 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0
363 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
364 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
365 ; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]]
367 ; CHECK-NEXT: tail call void @llvm.trap()
368 ; CHECK-NEXT: unreachable
370 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ]
371 ; CHECK-NEXT: ret i32 [[COND]]
374 %cmp = icmp eq i32 %x, -2147483648
375 br i1 %cmp, label %cond.end, label %cond.false
377 cond.false: ; preds = %entry
378 %0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %x, i32 1)
379 %1 = extractvalue { i32, i1 } %0, 0
380 %2 = extractvalue { i32, i1 } %0, 1
381 br i1 %2, label %trap, label %cond.end
383 trap: ; preds = %cond.false
384 tail call void @llvm.trap()
387 cond.end: ; preds = %cond.false, %entry
388 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
392 define i32 @unsigned_sub_r1(i32 %x) {
393 ; CHECK-LABEL: @unsigned_sub_r1(
395 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
396 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
398 ; CHECK-NEXT: [[TMP0:%.*]] = sub nuw i32 [[X]], 1
399 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0
400 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
401 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
402 ; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]]
404 ; CHECK-NEXT: tail call void @llvm.trap()
405 ; CHECK-NEXT: unreachable
407 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ]
408 ; CHECK-NEXT: ret i32 [[COND]]
411 %cmp = icmp eq i32 %x, 0
412 br i1 %cmp, label %cond.end, label %cond.false
414 cond.false: ; preds = %entry
415 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %x, i32 1)
416 %1 = extractvalue { i32, i1 } %0, 0
417 %2 = extractvalue { i32, i1 } %0, 1
418 br i1 %2, label %trap, label %cond.end
420 trap: ; preds = %cond.false
421 tail call void @llvm.trap()
424 cond.end: ; preds = %cond.false, %entry
425 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
429 define i32 @signed_add_rn1(i32 %x) {
430 ; CHECK-LABEL: @signed_add_rn1(
432 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], -2147483648
433 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
435 ; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[X]], -1
436 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0
437 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
438 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
439 ; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]]
441 ; CHECK-NEXT: tail call void @llvm.trap()
442 ; CHECK-NEXT: unreachable
444 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ]
445 ; CHECK-NEXT: ret i32 [[COND]]
448 %cmp = icmp eq i32 %x, -2147483648
449 br i1 %cmp, label %cond.end, label %cond.false
451 cond.false: ; preds = %entry
452 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 -1)
453 %1 = extractvalue { i32, i1 } %0, 0
454 %2 = extractvalue { i32, i1 } %0, 1
455 br i1 %2, label %trap, label %cond.end
457 trap: ; preds = %cond.false
458 tail call void @llvm.trap()
461 cond.end: ; preds = %cond.false, %entry
462 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
466 define i32 @signed_sub_rn1(i32 %x) {
467 ; CHECK-LABEL: @signed_sub_rn1(
469 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 2147483647
470 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
472 ; CHECK-NEXT: [[TMP0:%.*]] = sub nsw i32 [[X]], -1
473 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0
474 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
475 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
476 ; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]]
478 ; CHECK-NEXT: tail call void @llvm.trap()
479 ; CHECK-NEXT: unreachable
481 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ]
482 ; CHECK-NEXT: ret i32 [[COND]]
485 %cmp = icmp eq i32 %x, 2147483647
486 br i1 %cmp, label %cond.end, label %cond.false
488 cond.false: ; preds = %entry
489 %0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %x, i32 -1)
490 %1 = extractvalue { i32, i1 } %0, 0
491 %2 = extractvalue { i32, i1 } %0, 1
492 br i1 %2, label %trap, label %cond.end
494 trap: ; preds = %cond.false
495 tail call void @llvm.trap()
498 cond.end: ; preds = %cond.false, %entry
499 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ]
503 define i32 @unsigned_mul(i32 %x) {
504 ; CHECK-LABEL: @unsigned_mul(
506 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], 10000
507 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
509 ; CHECK-NEXT: [[MULO1:%.*]] = mul nuw nsw i32 [[X]], 100
510 ; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[MULO1]], 0
511 ; CHECK-NEXT: [[RES:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
512 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1
513 ; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[COND_END]]
515 ; CHECK-NEXT: tail call void @llvm.trap()
516 ; CHECK-NEXT: unreachable
518 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RES]], [[COND_FALSE]] ]
519 ; CHECK-NEXT: ret i32 [[COND]]
522 %cmp = icmp ugt i32 %x, 10000
523 br i1 %cmp, label %cond.end, label %cond.false
525 cond.false: ; preds = %entry
526 %mulo = tail call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 100)
527 %res = extractvalue { i32, i1 } %mulo, 0
528 %ov = extractvalue { i32, i1 } %mulo, 1
529 br i1 %ov, label %trap, label %cond.end
531 trap: ; preds = %cond.false
532 tail call void @llvm.trap()
535 cond.end: ; preds = %cond.false, %entry
536 %cond = phi i32 [ 0, %entry ], [ %res, %cond.false ]
540 define i32 @signed_mul(i32 %x) {
541 ; CHECK-LABEL: @signed_mul(
543 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[X:%.*]], 10000
544 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], -10000
545 ; CHECK-NEXT: [[CMP3:%.*]] = or i1 [[CMP1]], [[CMP2]]
546 ; CHECK-NEXT: br i1 [[CMP3]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
548 ; CHECK-NEXT: [[MULO1:%.*]] = mul nsw i32 [[X]], 100
549 ; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[MULO1]], 0
550 ; CHECK-NEXT: [[RES:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
551 ; CHECK-NEXT: [[OV:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1
552 ; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[COND_END]]
554 ; CHECK-NEXT: tail call void @llvm.trap()
555 ; CHECK-NEXT: unreachable
557 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RES]], [[COND_FALSE]] ]
558 ; CHECK-NEXT: ret i32 [[COND]]
561 %cmp1 = icmp sgt i32 %x, 10000
562 %cmp2 = icmp slt i32 %x, -10000
563 %cmp3 = or i1 %cmp1, %cmp2
564 br i1 %cmp3, label %cond.end, label %cond.false
566 cond.false: ; preds = %entry
567 %mulo = tail call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %x, i32 100)
568 %res = extractvalue { i32, i1 } %mulo, 0
569 %ov = extractvalue { i32, i1 } %mulo, 1
570 br i1 %ov, label %trap, label %cond.end
572 trap: ; preds = %cond.false
573 tail call void @llvm.trap()
576 cond.end: ; preds = %cond.false, %entry
577 %cond = phi i32 [ 0, %entry ], [ %res, %cond.false ]
581 declare i32 @bar(i32)
583 define void @unsigned_loop(i32 %i) {
584 ; CHECK-LABEL: @unsigned_loop(
586 ; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[I:%.*]], 0
587 ; CHECK-NEXT: br i1 [[CMP3]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
588 ; CHECK: while.body.preheader:
589 ; CHECK-NEXT: br label [[WHILE_BODY:%.*]]
591 ; CHECK-NEXT: [[I_ADDR_04:%.*]] = phi i32 [ [[TMP3:%.*]], [[CONT:%.*]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
592 ; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @bar(i32 [[I_ADDR_04]])
593 ; CHECK-NEXT: [[TMP0:%.*]] = sub nuw i32 [[I_ADDR_04]], 1
594 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0
595 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
596 ; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[CONT]]
598 ; CHECK-NEXT: tail call void @llvm.trap()
599 ; CHECK-NEXT: unreachable
601 ; CHECK-NEXT: [[TMP3]] = extractvalue { i32, i1 } [[TMP1]], 0
602 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP3]], 0
603 ; CHECK-NEXT: br i1 [[CMP]], label [[WHILE_END]], label [[WHILE_BODY]]
605 ; CHECK-NEXT: ret void
608 %cmp3 = icmp eq i32 %i, 0
609 br i1 %cmp3, label %while.end, label %while.body.preheader
611 while.body.preheader: ; preds = %entry
614 while.body: ; preds = %while.body.preheader, %cont
615 %i.addr.04 = phi i32 [ %2, %cont ], [ %i, %while.body.preheader ]
616 %call = tail call i32 @bar(i32 %i.addr.04)
617 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %i.addr.04, i32 1)
618 %1 = extractvalue { i32, i1 } %0, 1
619 br i1 %1, label %trap, label %cont
621 trap: ; preds = %while.body
622 tail call void @llvm.trap()
625 cont: ; preds = %while.body
626 %2 = extractvalue { i32, i1 } %0, 0
627 %cmp = icmp eq i32 %2, 0
628 br i1 %cmp, label %while.end, label %while.body
630 while.end: ; preds = %cont, %entry
634 define void @intrinsic_into_phi(i32 %n) {
635 ; CHECK-LABEL: @intrinsic_into_phi(
637 ; CHECK-NEXT: br label [[CONT:%.*]]
639 ; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[DOTLCSSA:%.*]], 1
640 ; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0
641 ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
642 ; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[CONT]]
644 ; CHECK-NEXT: tail call void @llvm.trap()
645 ; CHECK-NEXT: unreachable
647 ; CHECK-NEXT: [[TMP3:%.*]] = phi { i32, i1 } [ zeroinitializer, [[ENTRY:%.*]] ], [ [[TMP1]], [[FOR_COND:%.*]] ]
648 ; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i32, i1 } [[TMP3]], 0
649 ; CHECK-NEXT: [[CALL9:%.*]] = tail call i32 @bar(i32 [[TMP4]])
650 ; CHECK-NEXT: [[TOBOOL10:%.*]] = icmp eq i32 [[CALL9]], 0
651 ; CHECK-NEXT: br i1 [[TOBOOL10]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
652 ; CHECK: while.body.preheader:
653 ; CHECK-NEXT: br label [[WHILE_BODY:%.*]]
655 ; CHECK-NEXT: [[TMP5:%.*]] = extractvalue { i32, i1 } [[TMP7:%.*]], 0
656 ; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @bar(i32 [[TMP5]])
657 ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[CALL]], 0
658 ; CHECK-NEXT: br i1 [[TOBOOL]], label [[WHILE_END]], label [[WHILE_BODY]]
660 ; CHECK-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP5]], [[WHILE_COND:%.*]] ], [ [[TMP4]], [[WHILE_BODY_PREHEADER]] ]
661 ; CHECK-NEXT: [[TMP7]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[TMP6]], i32 1)
662 ; CHECK-NEXT: [[TMP8:%.*]] = extractvalue { i32, i1 } [[TMP7]], 1
663 ; CHECK-NEXT: br i1 [[TMP8]], label [[TRAP]], label [[WHILE_COND]]
665 ; CHECK-NEXT: [[DOTLCSSA]] = phi i32 [ [[TMP4]], [[CONT]] ], [ [[TMP5]], [[WHILE_COND]] ]
666 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[DOTLCSSA]], [[N:%.*]]
667 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_COND]], label [[CLEANUP2:%.*]]
669 ; CHECK-NEXT: ret void
674 for.cond: ; preds = %while.end
675 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %.lcssa, i32 1)
676 %1 = extractvalue { i32, i1 } %0, 1
677 br i1 %1, label %trap, label %cont
679 trap: ; preds = %for.cond, %while.body
680 tail call void @llvm.trap()
683 cont: ; preds = %entry, %for.cond
684 %2 = phi { i32, i1 } [ zeroinitializer, %entry ], [ %0, %for.cond ]
685 %3 = extractvalue { i32, i1 } %2, 0
686 %call9 = tail call i32 @bar(i32 %3)
687 %tobool10 = icmp eq i32 %call9, 0
688 br i1 %tobool10, label %while.end, label %while.body.preheader
690 while.body.preheader: ; preds = %cont
693 while.cond: ; preds = %while.body
694 %4 = extractvalue { i32, i1 } %6, 0
695 %call = tail call i32 @bar(i32 %4)
696 %tobool = icmp eq i32 %call, 0
697 br i1 %tobool, label %while.end, label %while.body
699 while.body: ; preds = %while.body.preheader, %while.cond
700 %5 = phi i32 [ %4, %while.cond ], [ %3, %while.body.preheader ]
701 %6 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %5, i32 1)
702 %7 = extractvalue { i32, i1 } %6, 1
703 br i1 %7, label %trap, label %while.cond
705 while.end: ; preds = %while.cond, %cont
706 %.lcssa = phi i32 [ %3, %cont ], [ %4, %while.cond ]
707 %cmp = icmp slt i32 %.lcssa, %n
708 br i1 %cmp, label %for.cond, label %cleanup2
710 cleanup2: ; preds = %while.end
714 define { i8, i1 } @signed_mul_constant_folding() {
715 ; CHECK-LABEL: @signed_mul_constant_folding(
716 ; CHECK-NEXT: ret { i8, i1 } { i8 2, i1 false }
718 %mul = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 1, i8 2)
722 define { <2 x i32>, <2 x i1> } @uaddo_vec(<2 x i32> %a) {
723 ; CHECK-LABEL: @uaddo_vec(
724 ; CHECK-NEXT: [[ADD:%.*]] = call { <2 x i32>, <2 x i1> } @llvm.uadd.with.overflow.v2i32(<2 x i32> [[A:%.*]], <2 x i32> <i32 1, i32 1>)
725 ; CHECK-NEXT: ret { <2 x i32>, <2 x i1> } [[ADD]]
727 %add = call { <2 x i32>, <2 x i1> } @llvm.uadd.with.overflow.v2i32(<2 x i32> %a, <2 x i32> <i32 1, i32 1>)
728 ret { <2 x i32>, <2 x i1> } %add
732 define i8 @uadd_sat_no_unsigned_overflow(i8 %x) {
733 ; CHECK-LABEL: @uadd_sat_no_unsigned_overflow(
734 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], 100
735 ; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]]
737 ; CHECK-NEXT: call void @llvm.trap()
738 ; CHECK-NEXT: unreachable
740 ; CHECK-NEXT: [[RES1:%.*]] = add nuw i8 [[X]], 100
741 ; CHECK-NEXT: ret i8 [[RES1]]
743 %cmp = icmp ugt i8 %x, 100
744 br i1 %cmp, label %trap, label %cont
747 call void @llvm.trap()
751 %res = call i8 @llvm.uadd.sat.i8(i8 %x, i8 100)
755 define i8 @uadd_sat_no_overflow(i8 %x) {
756 ; CHECK-LABEL: @uadd_sat_no_overflow(
757 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], 27
758 ; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]]
760 ; CHECK-NEXT: call void @llvm.trap()
761 ; CHECK-NEXT: unreachable
763 ; CHECK-NEXT: [[RES1:%.*]] = add nuw nsw i8 [[X]], 100
764 ; CHECK-NEXT: ret i8 [[RES1]]
766 %cmp = icmp ugt i8 %x, 27
767 br i1 %cmp, label %trap, label %cont
770 call void @llvm.trap()
774 %res = call i8 @llvm.uadd.sat.i8(i8 %x, i8 100)
778 define i8 @sadd_sat_no_signed_overflow(i8 %x) {
779 ; CHECK-LABEL: @sadd_sat_no_signed_overflow(
780 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], 100
781 ; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]]
783 ; CHECK-NEXT: call void @llvm.trap()
784 ; CHECK-NEXT: unreachable
786 ; CHECK-NEXT: [[RES1:%.*]] = add nsw i8 [[X]], 20
787 ; CHECK-NEXT: ret i8 [[RES1]]
789 %cmp = icmp sgt i8 %x, 100
790 br i1 %cmp, label %trap, label %cont
793 call void @llvm.trap()
797 %res = call i8 @llvm.sadd.sat.i8(i8 %x, i8 20)
801 define i8 @sadd_sat_no_overflow(i8 %x) {
802 ; CHECK-LABEL: @sadd_sat_no_overflow(
803 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], 107
804 ; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]]
806 ; CHECK-NEXT: call void @llvm.trap()
807 ; CHECK-NEXT: unreachable
809 ; CHECK-NEXT: [[RES1:%.*]] = add nuw nsw i8 [[X]], 20
810 ; CHECK-NEXT: ret i8 [[RES1]]
812 %cmp = icmp ugt i8 %x, 107
813 br i1 %cmp, label %trap, label %cont
816 call void @llvm.trap()
820 %res = call i8 @llvm.sadd.sat.i8(i8 %x, i8 20)
824 define i8 @usub_sat_no_unsigned_overflow(i8 %x) {
825 ; CHECK-LABEL: @usub_sat_no_unsigned_overflow(
826 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], 100
827 ; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]]
829 ; CHECK-NEXT: call void @llvm.trap()
830 ; CHECK-NEXT: unreachable
832 ; CHECK-NEXT: [[RES1:%.*]] = sub nuw i8 [[X]], 100
833 ; CHECK-NEXT: ret i8 [[RES1]]
835 %cmp = icmp ult i8 %x, 100
836 br i1 %cmp, label %trap, label %cont
839 call void @llvm.trap()
843 %res = call i8 @llvm.usub.sat.i8(i8 %x, i8 100)
847 define i8 @usub_sat_no_overflow(i8 %x) {
848 ; CHECK-LABEL: @usub_sat_no_overflow(
849 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], -28
850 ; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]]
852 ; CHECK-NEXT: call void @llvm.trap()
853 ; CHECK-NEXT: unreachable
855 ; CHECK-NEXT: [[RES1:%.*]] = sub nuw nsw i8 [[X]], 100
856 ; CHECK-NEXT: ret i8 [[RES1]]
858 %cmp = icmp ult i8 %x, 228
859 br i1 %cmp, label %trap, label %cont
862 call void @llvm.trap()
866 %res = call i8 @llvm.usub.sat.i8(i8 %x, i8 100)
870 define i8 @ssub_sat_no_signed_overflow(i8 %x) {
871 ; CHECK-LABEL: @ssub_sat_no_signed_overflow(
872 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], -100
873 ; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]]
875 ; CHECK-NEXT: call void @llvm.trap()
876 ; CHECK-NEXT: unreachable
878 ; CHECK-NEXT: [[RES1:%.*]] = sub nsw i8 [[X]], 20
879 ; CHECK-NEXT: ret i8 [[RES1]]
881 %cmp = icmp slt i8 %x, -100
882 br i1 %cmp, label %trap, label %cont
885 call void @llvm.trap()
889 %res = call i8 @llvm.ssub.sat.i8(i8 %x, i8 20)
893 define i8 @ssub_sat_no_overflow(i8 %x) {
894 ; CHECK-LABEL: @ssub_sat_no_overflow(
895 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], -108
896 ; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]]
898 ; CHECK-NEXT: call void @llvm.trap()
899 ; CHECK-NEXT: unreachable
901 ; CHECK-NEXT: [[RES1:%.*]] = sub nuw nsw i8 [[X]], 20
902 ; CHECK-NEXT: ret i8 [[RES1]]
904 %cmp = icmp ult i8 %x, 148
905 br i1 %cmp, label %trap, label %cont
908 call void @llvm.trap()
912 %res = call i8 @llvm.ssub.sat.i8(i8 %x, i8 20)
916 define <2 x i8> @uadd_sat_vec(<2 x i8> %a) {
917 ; CHECK-LABEL: @uadd_sat_vec(
918 ; CHECK-NEXT: [[ADD:%.*]] = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 1, i8 1>)
919 ; CHECK-NEXT: ret <2 x i8> [[ADD]]
921 %add = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 1, i8 1>)
925 ; In the following tests, we should first simplify a with.overflow intrinsic
926 ; to a simple arithmetic operation and insertvalue, but also simplify the
927 ; subsequent comparison that is based on it.
929 define i1 @sadd_and_cmp(i32 %x, i32 %y) #0 {
930 ; CHECK-LABEL: @sadd_and_cmp(
932 ; CHECK-NEXT: [[X_OFFSET:%.*]] = add i32 [[X:%.*]], 9
933 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X_OFFSET]], 19
934 ; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]]
936 ; CHECK-NEXT: [[Y_OFFSET:%.*]] = add i32 [[Y:%.*]], 9
937 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y_OFFSET]], 19
938 ; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]]
940 ; CHECK-NEXT: [[RES1:%.*]] = add nsw i32 [[X]], [[Y]]
941 ; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[RES1]], 0
942 ; CHECK-NEXT: [[ADD:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
943 ; CHECK-NEXT: br label [[CONT3:%.*]]
945 ; CHECK-NEXT: br label [[OUT]]
947 ; CHECK-NEXT: ret i1 true
950 %x.offset = add i32 %x, 9
951 %cmp1 = icmp ult i32 %x.offset, 19
952 br i1 %cmp1, label %cont1, label %out
955 %y.offset = add i32 %y, 9
956 %cmp2 = icmp ult i32 %y.offset, 19
957 br i1 %cmp2, label %cont2, label %out
960 ; x = [-9,10), y = [-9,10)
961 %res = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 %y)
962 %add = extractvalue { i32, i1 } %res, 0
967 %cmp3 = icmp slt i32 %add, 19
971 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont3 ]
976 define i1 @uadd_and_cmp(i32 %x, i32 %y) #0 {
977 ; CHECK-LABEL: @uadd_and_cmp(
979 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 10
980 ; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]]
982 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 10
983 ; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]]
985 ; CHECK-NEXT: [[RES1:%.*]] = add nuw nsw i32 [[X]], [[Y]]
986 ; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[RES1]], 0
987 ; CHECK-NEXT: [[ADD:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
988 ; CHECK-NEXT: br label [[CONT3:%.*]]
990 ; CHECK-NEXT: br label [[OUT]]
992 ; CHECK-NEXT: ret i1 true
995 %cmp1 = icmp ult i32 %x, 10
996 br i1 %cmp1, label %cont1, label %out
999 %cmp2 = icmp ult i32 %y, 10
1000 br i1 %cmp2, label %cont2, label %out
1003 %res = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)
1004 %add = extractvalue { i32, i1 } %res, 0
1008 %cmp3 = icmp ult i32 %add, 19
1012 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont3 ]
1016 define i1 @ssub_and_cmp(i32 %x, i32 %y) #0 {
1017 ; CHECK-LABEL: @ssub_and_cmp(
1018 ; CHECK-NEXT: entry:
1019 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 10
1020 ; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]]
1022 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 10
1023 ; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]]
1025 ; CHECK-NEXT: [[OFFSET:%.*]] = add nuw nsw i32 [[X]], 9
1026 ; CHECK-NEXT: [[RES1:%.*]] = sub nuw nsw i32 [[OFFSET]], [[Y]]
1027 ; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[RES1]], 0
1028 ; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
1029 ; CHECK-NEXT: br label [[CONT3:%.*]]
1031 ; CHECK-NEXT: br label [[OUT]]
1033 ; CHECK-NEXT: ret i1 true
1036 %cmp1 = icmp ult i32 %x, 10
1037 br i1 %cmp1, label %cont1, label %out
1040 %cmp2 = icmp ult i32 %y, 10
1041 br i1 %cmp2, label %cont2, label %out
1044 %offset = add i32 %x, 9
1045 ; x = [0,10), y = [0,10), offset = [9,19)
1046 %res = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %offset, i32 %y)
1047 %sub = extractvalue { i32, i1 } %res, 0
1051 %cmp3 = icmp ult i32 %sub, 19
1055 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont3 ]
1059 define i1 @usub_and_cmp(i32 %x, i32 %y) #0 {
1060 ; CHECK-LABEL: @usub_and_cmp(
1061 ; CHECK-NEXT: entry:
1062 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 10
1063 ; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]]
1065 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 10
1066 ; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]]
1068 ; CHECK-NEXT: [[OFFSET:%.*]] = add nuw nsw i32 [[X]], 9
1069 ; CHECK-NEXT: [[RES1:%.*]] = sub nuw nsw i32 [[OFFSET]], [[Y]]
1070 ; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[RES1]], 0
1071 ; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
1072 ; CHECK-NEXT: br label [[CONT3:%.*]]
1074 ; CHECK-NEXT: br label [[OUT]]
1076 ; CHECK-NEXT: ret i1 true
1079 %cmp1 = icmp ult i32 %x, 10
1080 br i1 %cmp1, label %cont1, label %out
1083 %cmp2 = icmp ult i32 %y, 10
1084 br i1 %cmp2, label %cont2, label %out
1087 %offset = add i32 %x, 9
1088 ; x = [0,10), y = [0,10), offset = [9,19)
1089 %res = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %offset, i32 %y)
1090 %sub = extractvalue { i32, i1 } %res, 0
1094 %cmp3 = icmp ult i32 %sub, 19
1098 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont3 ]
1102 define i1 @smul_and_cmp(i32 %x, i32 %y) #0 {
1103 ; CHECK-LABEL: @smul_and_cmp(
1104 ; CHECK-NEXT: entry:
1105 ; CHECK-NEXT: [[X_OFFSET:%.*]] = add i32 [[X:%.*]], 9
1106 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X_OFFSET]], 19
1107 ; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]]
1109 ; CHECK-NEXT: [[Y_OFFSET:%.*]] = add i32 [[Y:%.*]], 9
1110 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y_OFFSET]], 19
1111 ; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]]
1113 ; CHECK-NEXT: [[RES1:%.*]] = mul nsw i32 [[X]], [[Y]]
1114 ; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[RES1]], 0
1115 ; CHECK-NEXT: [[MUL:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
1116 ; CHECK-NEXT: br label [[CONT3:%.*]]
1118 ; CHECK-NEXT: br label [[OUT]]
1120 ; CHECK-NEXT: ret i1 true
1123 %x.offset = add i32 %x, 9
1124 %cmp1 = icmp ult i32 %x.offset, 19
1125 br i1 %cmp1, label %cont1, label %out
1128 %y.offset = add i32 %y, 9
1129 %cmp2 = icmp ult i32 %y.offset, 19
1130 br i1 %cmp2, label %cont2, label %out
1133 ; x = [-9,10), y = [-9,10)
1134 %res = tail call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %x, i32 %y)
1135 %mul = extractvalue { i32, i1 } %res, 0
1139 %cmp3 = icmp sle i32 %mul, 81
1140 %cmp4 = icmp sge i32 %mul, -81
1141 %cmp5 = and i1 %cmp3, %cmp4
1145 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp5, %cont3 ]
1149 define i1 @umul_and_cmp(i32 %x, i32 %y) #0 {
1150 ; CHECK-LABEL: @umul_and_cmp(
1151 ; CHECK-NEXT: entry:
1152 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 100
1153 ; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]]
1155 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 100
1156 ; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]]
1158 ; CHECK-NEXT: [[RES1:%.*]] = mul nuw nsw i32 [[X]], [[Y]]
1159 ; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[RES1]], 0
1160 ; CHECK-NEXT: [[MUL:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
1161 ; CHECK-NEXT: br label [[CONT3:%.*]]
1163 ; CHECK-NEXT: br label [[OUT]]
1165 ; CHECK-NEXT: ret i1 true
1168 %cmp1 = icmp ult i32 %x, 100
1169 br i1 %cmp1, label %cont1, label %out
1172 %cmp2 = icmp ult i32 %y, 100
1173 br i1 %cmp2, label %cont2, label %out
1176 %res = tail call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y)
1177 %mul = extractvalue { i32, i1 } %res, 0
1181 %cmp3 = icmp ule i32 %mul, 9801
1185 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont3 ]