[llvm-branch-commits] [llvm] [ConstraintElim] Simplify `usub_with_overflow` when A uge B (PR #135785)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Apr 18 03:27:49 PDT 2025
https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/135785
>From c5328e2075b5f98311eb9c9657da79d800cf28f4 Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Tue, 15 Apr 2025 20:20:45 +0800
Subject: [PATCH] [ConstraintElim] Simplify `usub_with_overflow` when A uge B
---
.../Scalar/ConstraintElimination.cpp | 10 ++++++
.../usub-with-overflow.ll | 33 +++++++------------
2 files changed, 21 insertions(+), 22 deletions(-)
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index 6d17b36b7d9ea..e030f0fac4c0d 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -1123,6 +1123,7 @@ void State::addInfoFor(BasicBlock &BB) {
// Enqueue overflow intrinsics for simplification.
case Intrinsic::sadd_with_overflow:
case Intrinsic::ssub_with_overflow:
+ case Intrinsic::usub_with_overflow:
case Intrinsic::ucmp:
case Intrinsic::scmp:
WorkList.push_back(
@@ -1785,6 +1786,15 @@ tryToSimplifyOverflowMath(IntrinsicInst *II, ConstraintInfo &Info,
Changed = replaceSubOverflowUses(II, A, B, ToRemove);
break;
}
+ case Intrinsic::usub_with_overflow: {
+ // usub overflows iff A < B
+ // TODO: If the operation is guaranteed to overflow, we could
+ // also apply some simplifications.
+ if (DoesConditionHold(CmpInst::ICMP_UGE, A, B, Info)) {
+ Changed = replaceSubOverflowUses(II, A, B, ToRemove);
+ }
+ break;
+ }
}
return Changed;
diff --git a/llvm/test/Transforms/ConstraintElimination/usub-with-overflow.ll b/llvm/test/Transforms/ConstraintElimination/usub-with-overflow.ll
index 06bfd8269d97d..0a3c4eb00fd25 100644
--- a/llvm/test/Transforms/ConstraintElimination/usub-with-overflow.ll
+++ b/llvm/test/Transforms/ConstraintElimination/usub-with-overflow.ll
@@ -9,11 +9,9 @@ define i8 @usub_no_overflow_due_to_cmp_condition(i8 %a, i8 %b) {
; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8 [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: br i1 [[C_1]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
; CHECK: math:
-; CHECK-NEXT: [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]])
-; CHECK-NEXT: [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
-; CHECK-NEXT: br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
+; CHECK-NEXT: [[RES:%.*]] = sub i8 [[B]], [[A]]
+; CHECK-NEXT: br i1 false, label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
; CHECK: exit.ok:
-; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
; CHECK-NEXT: ret i8 [[RES]]
; CHECK: exit.fail:
; CHECK-NEXT: ret i8 0
@@ -41,11 +39,9 @@ define i8 @usub_no_overflow_due_to_cmp_condition2(i8 %a, i8 %b) {
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: br i1 [[C_1]], label [[EXIT_FAIL:%.*]], label [[MATH:%.*]]
; CHECK: math:
-; CHECK-NEXT: [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]])
-; CHECK-NEXT: [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
-; CHECK-NEXT: br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
+; CHECK-NEXT: [[RES:%.*]] = sub i8 [[B]], [[A]]
+; CHECK-NEXT: br i1 false, label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
; CHECK: exit.ok:
-; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
; CHECK-NEXT: ret i8 [[RES]]
; CHECK: exit.fail:
; CHECK-NEXT: ret i8 0
@@ -75,12 +71,11 @@ define i8 @sub_no_overflow_due_to_cmp_condition_result_used(i8 %a, i8 %b) {
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: br i1 [[C_1]], label [[EXIT_FAIL:%.*]], label [[MATH:%.*]]
; CHECK: math:
+; CHECK-NEXT: [[RES:%.*]] = sub i8 [[B]], [[A]]
; CHECK-NEXT: [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]])
; CHECK-NEXT: call void @use_res({ i8, i1 } [[OP]])
-; CHECK-NEXT: [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
-; CHECK-NEXT: br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
+; CHECK-NEXT: br i1 false, label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
; CHECK: exit.ok:
-; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
; CHECK-NEXT: ret i8 [[RES]]
; CHECK: exit.fail:
; CHECK-NEXT: ret i8 0
@@ -111,11 +106,9 @@ define i8 @usub_no_overflow_due_to_or_conds(i8 %a, i8 %b) {
; CHECK-NEXT: [[OR:%.*]] = or i1 [[C_2]], [[C_1]]
; CHECK-NEXT: br i1 [[OR]], label [[EXIT_FAIL:%.*]], label [[MATH:%.*]]
; CHECK: math:
-; CHECK-NEXT: [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]])
-; CHECK-NEXT: [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
-; CHECK-NEXT: br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
+; CHECK-NEXT: [[RES:%.*]] = sub i8 [[B]], [[A]]
+; CHECK-NEXT: br i1 false, label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
; CHECK: exit.ok:
-; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
; CHECK-NEXT: ret i8 [[RES]]
; CHECK: exit.fail:
; CHECK-NEXT: ret i8 0
@@ -147,9 +140,7 @@ define i8 @usub_no_overflow_due_to_or_conds_sub_result_not_used(i8 %a, i8 %b) {
; CHECK-NEXT: [[OR:%.*]] = or i1 [[C_2]], [[C_1]]
; CHECK-NEXT: br i1 [[OR]], label [[EXIT_FAIL:%.*]], label [[MATH:%.*]]
; CHECK: math:
-; CHECK-NEXT: [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]])
-; CHECK-NEXT: [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
-; CHECK-NEXT: br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
+; CHECK-NEXT: br i1 false, label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
; CHECK: exit.ok:
; CHECK-NEXT: ret i8 20
; CHECK: exit.fail:
@@ -181,11 +172,9 @@ define i8 @usub_no_overflow_due_to_and_conds(i8 %a, i8 %b) {
; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_1]]
; CHECK-NEXT: br i1 [[AND]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]]
; CHECK: math:
-; CHECK-NEXT: [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]])
-; CHECK-NEXT: [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1
-; CHECK-NEXT: br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
+; CHECK-NEXT: [[RES:%.*]] = sub i8 [[B]], [[A]]
+; CHECK-NEXT: br i1 false, label [[EXIT_FAIL]], label [[EXIT_OK:%.*]]
; CHECK: exit.ok:
-; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0
; CHECK-NEXT: ret i8 [[RES]]
; CHECK: exit.fail:
; CHECK-NEXT: ret i8 0
More information about the llvm-branch-commits
mailing list