[llvm] [ConstraintElim] Optimize usub.sat intrinsic based on known constraints (PR #135744)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 14 21:46:17 PDT 2025
https://github.com/el-ev created https://github.com/llvm/llvm-project/pull/135744
[ConstraintElim] Optimize usub.sat intrinsic based on known constraints
pre-commit test
update test
>From e26f7a78aaa34d0283c5a2d793faa474774c6233 Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Tue, 15 Apr 2025 12:22:59 +0800
Subject: [PATCH 1/3] [ConstraintElim] Optimize usub.sat intrinsic based on
known constraints
---
.../Scalar/ConstraintElimination.cpp | 25 ++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index ad41ea735f0fd..c7259723addd7 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -1132,6 +1132,7 @@ void State::addInfoFor(BasicBlock &BB) {
case Intrinsic::umax:
case Intrinsic::smin:
case Intrinsic::smax:
+ case Intrinsic::usub_sat:
// TODO: handle llvm.abs as well
WorkList.push_back(
FactOrCheck::getCheck(DT.getNode(&BB), cast<CallInst>(&I)));
@@ -1142,7 +1143,6 @@ void State::addInfoFor(BasicBlock &BB) {
[[fallthrough]];
case Intrinsic::abs:
case Intrinsic::uadd_sat:
- case Intrinsic::usub_sat:
WorkList.push_back(FactOrCheck::getInstFact(DT.getNode(&BB), &I));
break;
}
@@ -1519,6 +1519,24 @@ static bool checkAndReplaceCmp(CmpIntrinsic *I, ConstraintInfo &Info,
return false;
}
+static bool checkAndReplaceUSubSat(SaturatingInst *I, ConstraintInfo &Info,
+ SmallVectorImpl<Instruction *> &ToRemove) {
+ Value *LHS = I->getOperand(0);
+ Value *RHS = I->getOperand(1);
+ if (checkCondition(ICmpInst::ICMP_UGT, LHS, RHS, I, Info).value_or(false)) {
+ IRBuilder<> Builder(I->getParent(), I->getIterator());
+ I->replaceAllUsesWith(Builder.CreateSub(LHS, RHS));
+ ToRemove.push_back(I);
+ return true;
+ }
+ if (checkCondition(ICmpInst::ICMP_ULE, LHS, RHS, I, Info).value_or(false)) {
+ I->replaceAllUsesWith(ConstantInt::get(I->getType(), 0));
+ ToRemove.push_back(I);
+ return true;
+ }
+ return false;
+}
+
static void
removeEntryFromStack(const StackEntry &E, ConstraintInfo &Info,
Module *ReproducerModule,
@@ -1840,6 +1858,11 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
Changed |= checkAndReplaceMinMax(MinMax, Info, ToRemove);
} else if (auto *CmpIntr = dyn_cast<CmpIntrinsic>(Inst)) {
Changed |= checkAndReplaceCmp(CmpIntr, Info, ToRemove);
+ } else if (auto *SatIntr = dyn_cast<SaturatingInst>(Inst)) {
+ if (SatIntr->getIntrinsicID() == Intrinsic::usub_sat)
+ Changed |= checkAndReplaceUSubSat(SatIntr, Info, ToRemove);
+ else
+ llvm_unreachable("Unexpected intrinsic.");
}
continue;
}
>From c527814f189367dc3502893083a28dc7991c49d6 Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Tue, 15 Apr 2025 12:23:41 +0800
Subject: [PATCH 2/3] pre-commit test
---
.../ConstraintElimination/uadd-usub-sat.ll | 45 ++++++++++++++++++-
1 file changed, 43 insertions(+), 2 deletions(-)
diff --git a/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll b/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll
index b0db89dcfdab8..0ef17d40a07a7 100644
--- a/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll
+++ b/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll
@@ -8,7 +8,9 @@ define i1 @uadd_sat_uge(i64 %a, i64 %b) {
; CHECK-LABEL: define i1 @uadd_sat_uge(
; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) {
; CHECK-NEXT: [[ADD_SAT:%.*]] = call i64 @llvm.uadd.sat.i64(i64 [[A]], i64 [[B]])
-; CHECK-NEXT: [[CMP:%.*]] = and i1 true, true
+; CHECK-NEXT: [[CMP1:%.*]] = icmp uge i64 [[ADD_SAT]], [[A]]
+; CHECK-NEXT: [[CMP2:%.*]] = icmp uge i64 [[ADD_SAT]], [[B]]
+; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP1]], [[CMP2]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add.sat = call i64 @llvm.uadd.sat.i64(i64 %a, i64 %b)
@@ -22,13 +24,42 @@ define i1 @usub_sat_ule_lhs(i64 %a, i64 %b) {
; CHECK-LABEL: define i1 @usub_sat_ule_lhs(
; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) {
; CHECK-NEXT: [[SUB_SAT:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
-; CHECK-NEXT: ret i1 true
+; CHECK-NEXT: [[CMP:%.*]] = icmp ule i64 [[SUB_SAT]], [[A]]
+; CHECK-NEXT: ret i1 [[CMP]]
;
%sub.sat = call i64 @llvm.usub.sat.i64(i64 %a, i64 %b)
%cmp = icmp ule i64 %sub.sat, %a
ret i1 %cmp
}
+define i64 @usub_sat_when_lhs_ugt_rhs(i64 %a, i64 %b) {
+; CHECK-LABEL: define i64 @usub_sat_when_lhs_ugt_rhs(
+; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) {
+; CHECK-NEXT: [[PRECOND:%.*]] = icmp ugt i64 [[A]], [[B]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[PRECOND]])
+; CHECK-NEXT: [[SUB_SAT:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
+; CHECK-NEXT: ret i64 [[SUB_SAT]]
+;
+ %precond = icmp ugt i64 %a, %b
+ call void @llvm.assume(i1 %precond)
+ %sub.sat = call i64 @llvm.usub.sat.i64(i64 %a, i64 %b)
+ ret i64 %sub.sat
+}
+
+define i64 @usub_sat_when_lhs_ule_rhs(i64 %a, i64 %b) {
+; CHECK-LABEL: define i64 @usub_sat_when_lhs_ule_rhs(
+; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) {
+; CHECK-NEXT: [[PRECOND:%.*]] = icmp ule i64 [[A]], [[B]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[PRECOND]])
+; CHECK-NEXT: [[SUB_SAT:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
+; CHECK-NEXT: ret i64 [[SUB_SAT]]
+;
+ %precond = icmp ule i64 %a, %b
+ call void @llvm.assume(i1 %precond)
+ %sub.sat = call i64 @llvm.usub.sat.i64(i64 %a, i64 %b)
+ ret i64 %sub.sat
+}
+
; Negative test
define i1 @usub_sat_not_ule_rhs(i64 %a, i64 %b) {
; CHECK-LABEL: define i1 @usub_sat_not_ule_rhs(
@@ -41,3 +72,13 @@ define i1 @usub_sat_not_ule_rhs(i64 %a, i64 %b) {
%cmp = icmp ule i64 %sub.sat, %b
ret i1 %cmp
}
+
+define i64 @usub_sat_without_precond(i64 %a, i64 %b) {
+; CHECK-LABEL: define i64 @usub_sat_without_precond(
+; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) {
+; CHECK-NEXT: [[SUB_SAT:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
+; CHECK-NEXT: ret i64 [[SUB_SAT]]
+;
+ %sub.sat = call i64 @llvm.usub.sat.i64(i64 %a, i64 %b)
+ ret i64 %sub.sat
+}
>From eb43a70a9ea83768ed0ead5d01462d83fc0c0357 Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Tue, 15 Apr 2025 12:24:37 +0800
Subject: [PATCH 3/3] update test
---
.../Transforms/ConstraintElimination/uadd-usub-sat.ll | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll b/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll
index 0ef17d40a07a7..567b5ce6c3a3f 100644
--- a/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll
+++ b/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll
@@ -8,9 +8,7 @@ define i1 @uadd_sat_uge(i64 %a, i64 %b) {
; CHECK-LABEL: define i1 @uadd_sat_uge(
; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) {
; CHECK-NEXT: [[ADD_SAT:%.*]] = call i64 @llvm.uadd.sat.i64(i64 [[A]], i64 [[B]])
-; CHECK-NEXT: [[CMP1:%.*]] = icmp uge i64 [[ADD_SAT]], [[A]]
-; CHECK-NEXT: [[CMP2:%.*]] = icmp uge i64 [[ADD_SAT]], [[B]]
-; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT: [[CMP:%.*]] = and i1 true, true
; CHECK-NEXT: ret i1 [[CMP]]
;
%add.sat = call i64 @llvm.uadd.sat.i64(i64 %a, i64 %b)
@@ -37,7 +35,7 @@ define i64 @usub_sat_when_lhs_ugt_rhs(i64 %a, i64 %b) {
; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) {
; CHECK-NEXT: [[PRECOND:%.*]] = icmp ugt i64 [[A]], [[B]]
; CHECK-NEXT: call void @llvm.assume(i1 [[PRECOND]])
-; CHECK-NEXT: [[SUB_SAT:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
+; CHECK-NEXT: [[SUB_SAT:%.*]] = sub i64 [[A]], [[B]]
; CHECK-NEXT: ret i64 [[SUB_SAT]]
;
%precond = icmp ugt i64 %a, %b
@@ -51,8 +49,7 @@ define i64 @usub_sat_when_lhs_ule_rhs(i64 %a, i64 %b) {
; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) {
; CHECK-NEXT: [[PRECOND:%.*]] = icmp ule i64 [[A]], [[B]]
; CHECK-NEXT: call void @llvm.assume(i1 [[PRECOND]])
-; CHECK-NEXT: [[SUB_SAT:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
-; CHECK-NEXT: ret i64 [[SUB_SAT]]
+; CHECK-NEXT: ret i64 0
;
%precond = icmp ule i64 %a, %b
call void @llvm.assume(i1 %precond)
More information about the llvm-commits
mailing list