diff options
| author | David Green <david.green@arm.com> | 2019-10-21 09:11:29 +0100 |
|---|---|---|
| committer | David Green <david.green@arm.com> | 2019-10-28 13:47:09 +0000 |
| commit | d2ec416c7babe65947ab841f9c9eb08844af3549 (patch) | |
| tree | a5fc1044ed54caf400cf35f28fff4c57bb1749b3 | |
| parent | 4c430a7c6f6b11105963c6a0ff1e6ee31517a1c8 (diff) | |
| download | bcm5719-llvm-d2ec416c7babe65947ab841f9c9eb08844af3549.tar.gz bcm5719-llvm-d2ec416c7babe65947ab841f9c9eb08844af3549.zip | |
[InstCombine][NFC] Tests for uadd.sat and sadd.sat canonicalisation.
| -rw-r--r-- | llvm/test/Transforms/InstCombine/overflow_to_sat.ll | 730 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/saturating-add-sub.ll | 48 |
2 files changed, 778 insertions, 0 deletions
diff --git a/llvm/test/Transforms/InstCombine/overflow_to_sat.ll b/llvm/test/Transforms/InstCombine/overflow_to_sat.ll new file mode 100644 index 00000000000..4bc989648e6 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/overflow_to_sat.ll @@ -0,0 +1,730 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -instcombine < %s | FileCheck %s + +define i32 @uadd(i32 %x, i32 %y) { +; CHECK-LABEL: @uadd( +; CHECK-NEXT: [[AO:%.*]] = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i32, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i32, i1 } [[AO]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[O]], i32 -1, i32 [[A]] +; CHECK-NEXT: ret i32 [[S]] +; + %ao = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y) + %o = extractvalue { i32, i1 } %ao, 1 + %a = extractvalue { i32, i1 } %ao, 0 + %s = select i1 %o, i32 -1, i32 %a + ret i32 %s +} + +define i32 @usub(i32 %x, i32 %y) { +; CHECK-LABEL: @usub( +; CHECK-NEXT: [[AO:%.*]] = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i32, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i32, i1 } [[AO]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[O]], i32 0, i32 [[A]] +; CHECK-NEXT: ret i32 [[S]] +; + %ao = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %x, i32 %y) + %o = extractvalue { i32, i1 } %ao, 1 + %a = extractvalue { i32, i1 } %ao, 0 + %s = select i1 %o, i32 0, i32 %a + ret i32 %s +} + + +define i8 @sadd_x_lt_min(i8 %x, i8 %y) { +; CHECK-LABEL: @sadd_x_lt_min( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp slt i8 %x, 0 + %s = select i1 %c, i8 127, i8 -128 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @sadd_x_lt_max(i8 %x, i8 %y) { +; CHECK-LABEL: @sadd_x_lt_max( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp slt i8 %x, 0 + %s = select i1 %c, i8 -128, i8 127 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @sadd_x_le_min(i8 %x, i8 %y) { +; CHECK-LABEL: @sadd_x_le_min( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X]], 1 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sle i8 %x, 0 + %s = select i1 %c, i8 127, i8 -128 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @sadd_x_le_max(i8 %x, i8 %y) { +; CHECK-LABEL: @sadd_x_le_max( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X]], 1 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sle i8 %x, 0 + %s = select i1 %c, i8 -128, i8 127 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @sadd_x_gt_min(i8 %x, i8 %y) { +; CHECK-LABEL: @sadd_x_gt_min( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[X]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sgt i8 %x, 0 + %s = select i1 %c, i8 127, i8 -128 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @sadd_x_gt_max(i8 %x, i8 %y) { +; CHECK-LABEL: @sadd_x_gt_max( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[X]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sgt i8 %x, 0 + %s = select i1 %c, i8 -128, i8 127 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @sadd_x_ge_min(i8 %x, i8 %y) { +; CHECK-LABEL: @sadd_x_ge_min( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[X]], -1 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sge i8 %x, 0 + %s = select i1 %c, i8 127, i8 -128 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @sadd_x_ge_max(i8 %x, i8 %y) { +; CHECK-LABEL: @sadd_x_ge_max( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[X]], -1 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sge i8 %x, 0 + %s = select i1 %c, i8 -128, i8 127 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + + +define i8 @sadd_y_lt_min(i8 %x, i8 %y) { +; CHECK-LABEL: @sadd_y_lt_min( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[Y]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp slt i8 %y, 0 + %s = select i1 %c, i8 127, i8 -128 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @sadd_y_lt_max(i8 %x, i8 %y) { +; CHECK-LABEL: @sadd_y_lt_max( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[Y]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp slt i8 %y, 0 + %s = select i1 %c, i8 -128, i8 127 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @sadd_y_le_min(i8 %x, i8 %y) { +; CHECK-LABEL: @sadd_y_le_min( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[Y]], 1 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sle i8 %y, 0 + %s = select i1 %c, i8 127, i8 -128 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @sadd_y_le_max(i8 %x, i8 %y) { +; CHECK-LABEL: @sadd_y_le_max( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[Y]], 1 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sle i8 %y, 0 + %s = select i1 %c, i8 -128, i8 127 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @sadd_y_gt_min(i8 %x, i8 %y) { +; CHECK-LABEL: @sadd_y_gt_min( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[Y]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sgt i8 %y, 0 + %s = select i1 %c, i8 127, i8 -128 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @sadd_y_gt_max(i8 %x, i8 %y) { +; CHECK-LABEL: @sadd_y_gt_max( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[Y]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sgt i8 %y, 0 + %s = select i1 %c, i8 -128, i8 127 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @sadd_y_ge_min(i8 %x, i8 %y) { +; CHECK-LABEL: @sadd_y_ge_min( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[Y]], -1 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sge i8 %y, 0 + %s = select i1 %c, i8 127, i8 -128 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @sadd_y_ge_max(i8 %x, i8 %y) { +; CHECK-LABEL: @sadd_y_ge_max( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[Y]], -1 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sge i8 %y, 0 + %s = select i1 %c, i8 -128, i8 127 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + + + + +define i8 @ssub_x_lt_min(i8 %x, i8 %y) { +; CHECK-LABEL: @ssub_x_lt_min( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp slt i8 %x, 0 + %s = select i1 %c, i8 127, i8 -128 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @ssub_x_lt_max(i8 %x, i8 %y) { +; CHECK-LABEL: @ssub_x_lt_max( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp slt i8 %x, 0 + %s = select i1 %c, i8 -128, i8 127 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @ssub_x_le_min(i8 %x, i8 %y) { +; CHECK-LABEL: @ssub_x_le_min( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X]], 1 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sle i8 %x, 0 + %s = select i1 %c, i8 127, i8 -128 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @ssub_x_le_max(i8 %x, i8 %y) { +; CHECK-LABEL: @ssub_x_le_max( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X]], 1 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sle i8 %x, 0 + %s = select i1 %c, i8 -128, i8 127 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @ssub_x_gt_min(i8 %x, i8 %y) { +; CHECK-LABEL: @ssub_x_gt_min( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[X]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sgt i8 %x, 0 + %s = select i1 %c, i8 127, i8 -128 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @ssub_x_gt_max(i8 %x, i8 %y) { +; CHECK-LABEL: @ssub_x_gt_max( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[X]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sgt i8 %x, 0 + %s = select i1 %c, i8 -128, i8 127 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @ssub_x_ge_min(i8 %x, i8 %y) { +; CHECK-LABEL: @ssub_x_ge_min( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[X]], -1 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sge i8 %x, 0 + %s = select i1 %c, i8 127, i8 -128 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @ssub_x_ge_max(i8 %x, i8 %y) { +; CHECK-LABEL: @ssub_x_ge_max( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[X]], -1 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sge i8 %x, 0 + %s = select i1 %c, i8 -128, i8 127 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + + +define i8 @ssub_y_lt_min(i8 %x, i8 %y) { +; CHECK-LABEL: @ssub_y_lt_min( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[Y]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp slt i8 %y, 0 + %s = select i1 %c, i8 127, i8 -128 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @ssub_y_lt_max(i8 %x, i8 %y) { +; CHECK-LABEL: @ssub_y_lt_max( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[Y]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp slt i8 %y, 0 + %s = select i1 %c, i8 -128, i8 127 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @ssub_y_le_min(i8 %x, i8 %y) { +; CHECK-LABEL: @ssub_y_le_min( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[Y]], 1 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sle i8 %y, 0 + %s = select i1 %c, i8 127, i8 -128 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @ssub_y_le_max(i8 %x, i8 %y) { +; CHECK-LABEL: @ssub_y_le_max( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[Y]], 1 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sle i8 %y, 0 + %s = select i1 %c, i8 -128, i8 127 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @ssub_y_gt_min(i8 %x, i8 %y) { +; CHECK-LABEL: @ssub_y_gt_min( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[Y]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sgt i8 %y, 0 + %s = select i1 %c, i8 127, i8 -128 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @ssub_y_gt_max(i8 %x, i8 %y) { +; CHECK-LABEL: @ssub_y_gt_max( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[Y]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sgt i8 %y, 0 + %s = select i1 %c, i8 -128, i8 127 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @ssub_y_ge_min(i8 %x, i8 %y) { +; CHECK-LABEL: @ssub_y_ge_min( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[Y]], -1 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 127, i8 -128 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sge i8 %y, 0 + %s = select i1 %c, i8 127, i8 -128 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + +define i8 @ssub_y_ge_max(i8 %x, i8 %y) { +; CHECK-LABEL: @ssub_y_ge_max( +; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i8, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i8, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[Y]], -1 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 -128, i8 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i8 [[S]], i8 [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %ao = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y) + %o = extractvalue { i8, i1 } %ao, 1 + %a = extractvalue { i8, i1 } %ao, 0 + %c = icmp sge i8 %y, 0 + %s = select i1 %c, i8 -128, i8 127 + %r = select i1 %o, i8 %s, i8 %a + ret i8 %r +} + + +define i32 @sadd_i32(i32 %x, i32 %y) { +; CHECK-LABEL: @sadd_i32( +; CHECK-NEXT: [[AO:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i32, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i32, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[X]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i32 -2147483648, i32 2147483647 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i32 [[S]], i32 [[A]] +; CHECK-NEXT: ret i32 [[R]] +; + %ao = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 %y) + %o = extractvalue { i32, i1 } %ao, 1 + %a = extractvalue { i32, i1 } %ao, 0 + %c = icmp slt i32 %x, 0 + %s = select i1 %c, i32 -2147483648, i32 2147483647 + %r = select i1 %o, i32 %s, i32 %a + ret i32 %r +} + +define i32 @ssub_i32(i32 %x, i32 %y) { +; CHECK-LABEL: @ssub_i32( +; CHECK-NEXT: [[AO:%.*]] = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i32, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i32, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[X]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i32 -2147483648, i32 2147483647 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i32 [[S]], i32 [[A]] +; CHECK-NEXT: ret i32 [[R]] +; + %ao = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %x, i32 %y) + %o = extractvalue { i32, i1 } %ao, 1 + %a = extractvalue { i32, i1 } %ao, 0 + %c = icmp slt i32 %x, 0 + %s = select i1 %c, i32 -2147483648, i32 2147483647 + %r = select i1 %o, i32 %s, i32 %a + ret i32 %r +} + +define i32 @sadd_bounds(i32 %x, i32 %y) { +; CHECK-LABEL: @sadd_bounds( +; CHECK-NEXT: [[AO:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i32, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i32, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[X]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i32 -128, i32 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i32 [[S]], i32 [[A]] +; CHECK-NEXT: ret i32 [[R]] +; + %ao = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 %y) + %o = extractvalue { i32, i1 } %ao, 1 + %a = extractvalue { i32, i1 } %ao, 0 + %c = icmp slt i32 %x, 0 + %s = select i1 %c, i32 -128, i32 127 + %r = select i1 %o, i32 %s, i32 %a + ret i32 %r +} + +define i32 @ssub_bounds(i32 %x, i32 %y) { +; CHECK-LABEL: @ssub_bounds( +; CHECK-NEXT: [[AO:%.*]] = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) +; CHECK-NEXT: [[O:%.*]] = extractvalue { i32, i1 } [[AO]], 1 +; CHECK-NEXT: [[A:%.*]] = extractvalue { i32, i1 } [[AO]], 0 +; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[X]], 0 +; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i32 -128, i32 127 +; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i32 [[S]], i32 [[A]] +; CHECK-NEXT: ret i32 [[R]] +; + %ao = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %x, i32 %y) + %o = extractvalue { i32, i1 } %ao, 1 + %a = extractvalue { i32, i1 } %ao, 0 + %c = icmp slt i32 %x, 0 + %s = select i1 %c, i32 -128, i32 127 + %r = select i1 %o, i32 %s, i32 %a + ret i32 %r +} + +declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %0, i32 %1) +declare { i32, i1 } @llvm.usub.with.overflow.i32(i32 %0, i32 %1) +declare { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %0, i8 %1) +declare { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %0, i8 %1) +declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %0, i32 %1) +declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %0, i32 %1) diff --git a/llvm/test/Transforms/InstCombine/saturating-add-sub.ll b/llvm/test/Transforms/InstCombine/saturating-add-sub.ll index f5f719864b0..06232070421 100644 --- a/llvm/test/Transforms/InstCombine/saturating-add-sub.ll +++ b/llvm/test/Transforms/InstCombine/saturating-add-sub.ll @@ -1484,6 +1484,54 @@ define i32 @uadd_sat_constant_commute(i32 %x) { ret i32 %r } +define i32 @uadd_sat_canon(i32 %x, i32 %y) { +; CHECK-LABEL: @uadd_sat_canon( +; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[A]], [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 -1, i32 [[A]] +; CHECK-NEXT: ret i32 [[R]] +; + %a = add i32 %x, %y + %c = icmp ult i32 %a, %x + %r = select i1 %c, i32 -1, i32 %a + ret i32 %r +} + +define i32 @uadd_sat_canon_y(i32 %x, i32 %y) { +; CHECK-LABEL: @uadd_sat_canon_y( +; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[A]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 -1, i32 [[A]] +; CHECK-NEXT: ret i32 [[R]] +; + %a = add i32 %x, %y + %c = icmp ult i32 %a, %y + %r = select i1 %c, i32 -1, i32 %a + ret i32 %r +} + +define i32 @uadd_sat_canon_nuw(i32 %x, i32 %y) { +; CHECK-LABEL: @uadd_sat_canon_nuw( +; CHECK-NEXT: [[A:%.*]] = add nuw i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: ret i32 [[A]] +; + %a = add nuw i32 %x, %y + %c = icmp ult i32 %a, %x + %r = select i1 %c, i32 -1, i32 %a + ret i32 %r +} + +define i32 @uadd_sat_canon_y_nuw(i32 %x, i32 %y) { +; CHECK-LABEL: @uadd_sat_canon_y_nuw( +; CHECK-NEXT: [[A:%.*]] = add nuw i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: ret i32 [[A]] +; + %a = add nuw i32 %x, %y + %c = icmp ult i32 %a, %y + %r = select i1 %c, i32 -1, i32 %a + ret i32 %r +} + define <4 x i32> @uadd_sat_constant_vec(<4 x i32> %x) { ; CHECK-LABEL: @uadd_sat_constant_vec( ; CHECK-NEXT: [[A:%.*]] = add <4 x i32> [[X:%.*]], <i32 42, i32 42, i32 42, i32 42> |

