Skip to content

[ConstraintElim] Optimize usub.sat intrinsic based on known constraints #135744

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

el-ev
Copy link
Member

@el-ev el-ev commented Apr 15, 2025

[ConstraintElim] Optimize usub.sat intrinsic based on known constraints

pre-commit test

update test

Copy link
Member Author

el-ev commented Apr 15, 2025

@el-ev el-ev marked this pull request as ready for review April 15, 2025 07:16
@llvmbot
Copy link
Member

llvmbot commented Apr 15, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Iris (el-ev)

Changes

[ConstraintElim] Optimize usub.sat intrinsic based on known constraints

pre-commit test

update test


Full diff: https://github.com/llvm/llvm-project/pull/135744.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/Scalar/ConstraintElimination.cpp (+29-3)
  • (modified) llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll (+37)
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index ad41ea735f0fd..6608d65f797c5 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -1137,12 +1137,15 @@ void State::addInfoFor(BasicBlock &BB) {
           FactOrCheck::getCheck(DT.getNode(&BB), cast<CallInst>(&I)));
       // TODO: Check if it is possible to instead only added the min/max facts
       // when simplifying uses of the min/max intrinsics.
-      if (!isGuaranteedNotToBePoison(&I))
-        break;
+      if (isGuaranteedNotToBePoison(&I))
+        WorkList.push_back(FactOrCheck::getInstFact(DT.getNode(&BB), &I));
+      break;
+    case Intrinsic::usub_sat:
+      WorkList.push_back(
+          FactOrCheck::getCheck(DT.getNode(&BB), cast<CallInst>(&I)));
       [[fallthrough]];
     case Intrinsic::abs:
     case Intrinsic::uadd_sat:
-    case Intrinsic::usub_sat:
       WorkList.push_back(FactOrCheck::getInstFact(DT.getNode(&BB), &I));
       break;
     }
@@ -1519,6 +1522,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 +1861,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;
     }
diff --git a/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll b/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll
index b0db89dcfdab8..ea0d0d42eb081 100644
--- a/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll
+++ b/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll
@@ -29,6 +29,33 @@ define i1 @usub_sat_ule_lhs(i64 %a, i64 %b) {
   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:%.*]] = sub i64 [[A]], [[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:    ret i64 0
+;
+  %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 +68,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
+}

@el-ev el-ev force-pushed the users/el-ev/04-15-_constraintelim_optimize_usub.sat_intrinsic_based_on_known_constraints branch from aac90e1 to d2dd4c4 Compare April 15, 2025 14:56
Copy link

github-actions bot commented Apr 15, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@el-ev el-ev force-pushed the users/el-ev/04-15-_constraintelim_optimize_usub.sat_intrinsic_based_on_known_constraints branch 2 times, most recently from b705cbc to beee270 Compare April 15, 2025 15:35
@el-ev el-ev force-pushed the users/el-ev/04-15-_constraintelim_optimize_usub.sat_intrinsic_based_on_known_constraints branch from beee270 to 33ba7e5 Compare April 18, 2025 10:03
@el-ev el-ev force-pushed the users/el-ev/04-15-_constraintelim_optimize_usub.sat_intrinsic_based_on_known_constraints branch from 33ba7e5 to 9b486eb Compare April 18, 2025 10:26
@el-ev el-ev marked this pull request as draft April 20, 2025 02:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants