Skip to content

[ConstraintElim] Opimize abs based on known constraints #135754

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 4 commits into
base: users/el-ev/04-15-_constraintelim_optimize_usub.sat_intrinsic_based_on_known_constraints
Choose a base branch
from

Conversation

el-ev
Copy link
Member

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

[ConstraintElim] Opimize abs based on known constraints

update test

Copy link
Member Author

el-ev commented Apr 15, 2025

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

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 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] Opimize abs based on known constraints

update test


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

2 Files Affected:

  • (modified) llvm/lib/Transforms/Scalar/ConstraintElimination.cpp (+27-2)
  • (modified) llvm/test/Transforms/ConstraintElimination/abs.ll (+44-7)
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index 6608d65f797c5..9eedd701b5e00 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -1132,7 +1132,6 @@ void State::addInfoFor(BasicBlock &BB) {
     case Intrinsic::umax:
     case Intrinsic::smin:
     case Intrinsic::smax:
-      // TODO: handle llvm.abs as well
       WorkList.push_back(
           FactOrCheck::getCheck(DT.getNode(&BB), cast<CallInst>(&I)));
       // TODO: Check if it is possible to instead only added the min/max facts
@@ -1140,11 +1139,11 @@ void State::addInfoFor(BasicBlock &BB) {
       if (isGuaranteedNotToBePoison(&I))
         WorkList.push_back(FactOrCheck::getInstFact(DT.getNode(&BB), &I));
       break;
+    case Intrinsic::abs:
     case Intrinsic::usub_sat:
       WorkList.push_back(
           FactOrCheck::getCheck(DT.getNode(&BB), cast<CallInst>(&I)));
       [[fallthrough]];
-    case Intrinsic::abs:
     case Intrinsic::uadd_sat:
       WorkList.push_back(FactOrCheck::getInstFact(DT.getNode(&BB), &I));
       break;
@@ -1540,6 +1539,28 @@ static bool checkAndReplaceUSubSat(SaturatingInst *I, ConstraintInfo &Info,
   return false;
 }
 
+static bool checkAndReplaceAbs(IntrinsicInst *I, ConstraintInfo &Info,
+                               SmallVectorImpl<Instruction *> &ToRemove) {
+  assert(I->getIntrinsicID() == Intrinsic::abs && "Expected abs intrinsic");
+  Value *Op = I->getOperand(0);
+  if (checkCondition(ICmpInst::ICMP_SGE, Op, ConstantInt::get(Op->getType(), 0),
+                     I, Info)
+          .value_or(false)) {
+    I->replaceAllUsesWith(Op);
+    ToRemove.push_back(I);
+    return true;
+  }
+  if (checkCondition(ICmpInst::ICMP_SLT, Op, ConstantInt::get(Op->getType(), 0),
+                     I, Info)
+          .value_or(false)) {
+    IRBuilder<> Builder(I->getParent(), I->getIterator());
+    I->replaceAllUsesWith(Builder.CreateNeg(Op));
+    ToRemove.push_back(I);
+    return true;
+  }
+  return false;
+}
+
 static void
 removeEntryFromStack(const StackEntry &E, ConstraintInfo &Info,
                      Module *ReproducerModule,
@@ -1866,6 +1887,10 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
           Changed |= checkAndReplaceUSubSat(SatIntr, Info, ToRemove);
         else
           llvm_unreachable("Unexpected intrinsic.");
+      } else if (auto *II = dyn_cast<IntrinsicInst>(Inst)) {
+        if (II->getIntrinsicID() == Intrinsic::abs) {
+          Changed |= checkAndReplaceAbs(II, Info, ToRemove);
+        }
       }
       continue;
     }
diff --git a/llvm/test/Transforms/ConstraintElimination/abs.ll b/llvm/test/Transforms/ConstraintElimination/abs.ll
index 9fc68b0e72663..e09a061410f48 100644
--- a/llvm/test/Transforms/ConstraintElimination/abs.ll
+++ b/llvm/test/Transforms/ConstraintElimination/abs.ll
@@ -67,8 +67,7 @@ define i1 @abs_plus_one_unsigned_greater_or_equal_nonnegative_arg(i32 %arg) {
 ; CHECK-SAME: i32 [[ARG:%.*]]) {
 ; CHECK-NEXT:    [[CMP_ARG_NONNEGATIVE:%.*]] = icmp sge i32 [[ARG]], 0
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_ARG_NONNEGATIVE]])
-; CHECK-NEXT:    [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 true)
-; CHECK-NEXT:    [[ABS_PLUS_ONE:%.*]] = add nuw i32 [[ABS]], 1
+; CHECK-NEXT:    [[ABS_PLUS_ONE:%.*]] = add nuw i32 [[ARG]], 1
 ; CHECK-NEXT:    ret i1 true
 ;
   %cmp_arg_nonnegative = icmp sge i32 %arg, 0
@@ -95,9 +94,7 @@ define i1 @abs_plus_one_unsigned_greater_or_equal_cannot_be_simplified(i32 %arg)
 
 define i1 @abs_constant_negative_arg() {
 ; CHECK-LABEL: define i1 @abs_constant_negative_arg() {
-; CHECK-NEXT:    [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 -3, i1 false)
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[ABS]], 3
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 true
 ;
   %abs = tail call i32 @llvm.abs.i32(i32 -3, i1 false)
   %cmp = icmp sge i32 %abs, 3
@@ -106,7 +103,6 @@ define i1 @abs_constant_negative_arg() {
 
 define i1 @abs_constant_positive_arg() {
 ; CHECK-LABEL: define i1 @abs_constant_positive_arg() {
-; CHECK-NEXT:    [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 3, i1 false)
 ; CHECK-NEXT:    ret i1 true
 ;
   %abs = tail call i32 @llvm.abs.i32(i32 3, i1 false)
@@ -151,7 +147,6 @@ define i1 @abs_is_nonnegative_int_min_is_poison(i32 %arg) {
 
 define i1 @abs_is_nonnegative_constant_arg() {
 ; CHECK-LABEL: define i1 @abs_is_nonnegative_constant_arg() {
-; CHECK-NEXT:    [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 -3, i1 true)
 ; CHECK-NEXT:    ret i1 true
 ;
   %abs = tail call i32 @llvm.abs.i32(i32 -3, i1 true)
@@ -159,5 +154,47 @@ define i1 @abs_is_nonnegative_constant_arg() {
   ret i1 %cmp
 }
 
+define i64 @abs_assume_nonnegative(i64 %arg) {
+; CHECK-LABEL: define i64 @abs_assume_nonnegative(
+; CHECK-SAME: i64 [[ARG:%.*]]) {
+; CHECK-NEXT:    [[PRECOND:%.*]] = icmp sge i64 [[ARG]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[PRECOND]])
+; CHECK-NEXT:    ret i64 [[ARG]]
+;
+  %precond = icmp sge i64 %arg, 0
+  call void @llvm.assume(i1 %precond)
+  %abs = tail call i64 @llvm.abs.i64(i64 %arg, i1 false)
+  ret i64 %abs
+}
+
+define i64 @abs_assume_negative(i64 %arg) {
+; CHECK-LABEL: define i64 @abs_assume_negative(
+; CHECK-SAME: i64 [[ARG:%.*]]) {
+; CHECK-NEXT:    [[PRECOND:%.*]] = icmp slt i64 [[ARG]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[PRECOND]])
+; CHECK-NEXT:    [[ABS:%.*]] = sub i64 0, [[ARG]]
+; CHECK-NEXT:    ret i64 [[ABS]]
+;
+  %precond = icmp slt i64 %arg, 0
+  call void @llvm.assume(i1 %precond)
+  %abs = tail call i64 @llvm.abs.i64(i64 %arg, i1 false)
+  ret i64 %abs
+}
+
+; Negative test
+define i64 @abs_assume_unrelated(i64 %arg) {
+; CHECK-LABEL: define i64 @abs_assume_unrelated(
+; CHECK-SAME: i64 [[ARG:%.*]]) {
+; CHECK-NEXT:    [[PRECOND:%.*]] = icmp slt i64 [[ARG]], 3
+; CHECK-NEXT:    call void @llvm.assume(i1 [[PRECOND]])
+; CHECK-NEXT:    [[ABS:%.*]] = tail call i64 @llvm.abs.i64(i64 [[ARG]], i1 false)
+; CHECK-NEXT:    ret i64 [[ABS]]
+;
+  %precond = icmp slt i64 %arg, 3
+  call void @llvm.assume(i1 %precond)
+  %abs = tail call i64 @llvm.abs.i64(i64 %arg, i1 false)
+  ret i64 %abs
+}
+
 declare i32 @llvm.abs.i32(i32, i1 immarg)
 declare void @llvm.assume(i1)

@el-ev el-ev requested review from dtcxzyw and nikic and removed request for dtcxzyw April 15, 2025 07:21
@el-ev el-ev force-pushed the users/el-ev/04-15-_constraintelim_opimize_abs_based_on_known_constraints branch from 76b4b28 to dcd5cf9 Compare April 15, 2025 09:03
@dtcxzyw dtcxzyw requested a review from fhahn April 15, 2025 11:43
@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
@el-ev el-ev force-pushed the users/el-ev/04-15-_constraintelim_opimize_abs_based_on_known_constraints branch 2 times, most recently from 6e3bb61 to 079a353 Compare April 15, 2025 14:59
@el-ev el-ev force-pushed the users/el-ev/04-15-_constraintelim_optimize_usub.sat_intrinsic_based_on_known_constraints branch from d2dd4c4 to b705cbc Compare April 15, 2025 14:59
@el-ev el-ev force-pushed the users/el-ev/04-15-_constraintelim_opimize_abs_based_on_known_constraints branch from 079a353 to f051f42 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 b705cbc to beee270 Compare April 15, 2025 15:36
@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_opimize_abs_based_on_known_constraints branch from f051f42 to 1c0a426 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 force-pushed the users/el-ev/04-15-_constraintelim_opimize_abs_based_on_known_constraints branch from 1c0a426 to 157aa8a 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.

2 participants