https://github.com/el-ev created https://github.com/llvm/llvm-project/pull/135754
[ConstraintElim] Opimize abs based on known constraints update test >From af8e5662259fe323f403a48140443feb22e9ef63 Mon Sep 17 00:00:00 2001 From: Iris Shi <0...@owo.li> Date: Tue, 15 Apr 2025 15:00:58 +0800 Subject: [PATCH 1/2] [ConstraintElim] Opimize abs based on known constraints --- .../Scalar/ConstraintElimination.cpp | 31 +++++++++++-- .../Transforms/ConstraintElimination/abs.ll | 43 +++++++++++++++++++ 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp index 6608d65f797c5..dca55cc48d91f 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))); + 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..32f686a6fcb8f 100644 --- a/llvm/test/Transforms/ConstraintElimination/abs.ll +++ b/llvm/test/Transforms/ConstraintElimination/abs.ll @@ -159,5 +159,48 @@ 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: [[ABS:%.*]] = tail call i64 @llvm.abs.i64(i64 [[ARG]], i1 false) +; CHECK-NEXT: ret i64 [[ABS]] +; + %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:%.*]] = tail call i64 @llvm.abs.i64(i64 [[ARG]], i1 false) +; 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) >From e43776bf35377832829b53a959c377276b37c327 Mon Sep 17 00:00:00 2001 From: Iris Shi <0...@owo.li> Date: Tue, 15 Apr 2025 15:03:08 +0800 Subject: [PATCH 2/2] update test --- llvm/test/Transforms/ConstraintElimination/abs.ll | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/llvm/test/Transforms/ConstraintElimination/abs.ll b/llvm/test/Transforms/ConstraintElimination/abs.ll index 32f686a6fcb8f..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) @@ -164,8 +159,7 @@ define i64 @abs_assume_nonnegative(i64 %arg) { ; CHECK-SAME: i64 [[ARG:%.*]]) { ; CHECK-NEXT: [[PRECOND:%.*]] = icmp sge i64 [[ARG]], 0 ; 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]] +; CHECK-NEXT: ret i64 [[ARG]] ; %precond = icmp sge i64 %arg, 0 call void @llvm.assume(i1 %precond) @@ -178,7 +172,7 @@ define i64 @abs_assume_negative(i64 %arg) { ; CHECK-SAME: i64 [[ARG:%.*]]) { ; CHECK-NEXT: [[PRECOND:%.*]] = icmp slt i64 [[ARG]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[PRECOND]]) -; CHECK-NEXT: [[ABS:%.*]] = tail call i64 @llvm.abs.i64(i64 [[ARG]], i1 false) +; CHECK-NEXT: [[ABS:%.*]] = sub i64 0, [[ARG]] ; CHECK-NEXT: ret i64 [[ABS]] ; %precond = icmp slt i64 %arg, 0 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits