https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/135754
>From 13861a0e36e5b658f6073532e6d7ed25b8f9198f 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/4] [ConstraintElim] Opimize abs based on known constraints --- .../Scalar/ConstraintElimination.cpp | 28 +++++++++++- .../Transforms/ConstraintElimination/abs.ll | 43 +++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp index 8a05d0c1ddf5a..9930b3ea106d9 100644 --- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp +++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp @@ -1128,6 +1128,7 @@ void State::addInfoFor(BasicBlock &BB) { FactOrCheck::getCheck(DT.getNode(&BB), cast<CallInst>(&I))); break; // Enqueue the intrinsics to add extra info. + case Intrinsic::abs: case Intrinsic::umin: case Intrinsic::umax: case Intrinsic::smin: @@ -1139,7 +1140,6 @@ void State::addInfoFor(BasicBlock &BB) { // TODO: Check if it is possible to instead only added the min/max facts // when simplifying uses of the min/max intrinsics. [[fallthrough]]; - case Intrinsic::abs: case Intrinsic::uadd_sat: if (!isGuaranteedNotToBePoison(&I)) break; @@ -1537,6 +1537,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, @@ -1863,6 +1885,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 356c0cf985a662ddbafd75fd6cd9b3af4888a498 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/4] 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 >From 68418b42002286d5c9b61fb9bb2c61cb31bd6c77 Mon Sep 17 00:00:00 2001 From: Iris Shi <0...@owo.li> Date: Tue, 15 Apr 2025 16:58:39 +0800 Subject: [PATCH 3/4] match abs only --- llvm/lib/Transforms/Scalar/ConstraintElimination.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp index 9930b3ea106d9..ed46e125e1f68 100644 --- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp +++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp @@ -1880,15 +1880,14 @@ 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 (match(Inst, m_Intrinsic<Intrinsic::abs>(m_Value()))) { + Changed |= + checkAndReplaceAbs(dyn_cast<IntrinsicInst>(Inst), 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."); - } else if (auto *II = dyn_cast<IntrinsicInst>(Inst)) { - if (II->getIntrinsicID() == Intrinsic::abs) { - Changed |= checkAndReplaceAbs(II, Info, ToRemove); - } } continue; } >From 1c0a42611203e0ad1d9cb42a747b5047c3be2862 Mon Sep 17 00:00:00 2001 From: Iris Shi <0...@owo.li> Date: Tue, 15 Apr 2025 21:29:43 +0800 Subject: [PATCH 4/4] add nopoison back --- .../Scalar/ConstraintElimination.cpp | 1 - .../Transforms/ConstraintElimination/abs.ll | 18 ++++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp index ed46e125e1f68..d62fae410ce21 100644 --- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp +++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp @@ -1134,7 +1134,6 @@ void State::addInfoFor(BasicBlock &BB) { 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))); // TODO: Check if it is possible to instead only added the min/max facts diff --git a/llvm/test/Transforms/ConstraintElimination/abs.ll b/llvm/test/Transforms/ConstraintElimination/abs.ll index e09a061410f48..a49b4643ab92c 100644 --- a/llvm/test/Transforms/ConstraintElimination/abs.ll +++ b/llvm/test/Transforms/ConstraintElimination/abs.ll @@ -5,7 +5,8 @@ define i1 @abs_int_min_is_not_poison(i32 %arg) { ; CHECK-LABEL: define i1 @abs_int_min_is_not_poison( ; CHECK-SAME: i32 [[ARG:%.*]]) { ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 false) -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[ABS]], [[ARG]] +; CHECK-NEXT: ret i1 [[CMP]] ; %abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 false) %cmp = icmp sge i32 %abs, %arg @@ -16,7 +17,8 @@ define i1 @abs_int_min_is_poison(i32 %arg) { ; CHECK-LABEL: define i1 @abs_int_min_is_poison( ; CHECK-SAME: i32 [[ARG:%.*]]) { ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 true) -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[ABS]], [[ARG]] +; CHECK-NEXT: ret i1 [[CMP]] ; %abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 true) %cmp = icmp sge i32 %abs, %arg @@ -28,7 +30,8 @@ define i1 @abs_plus_one(i32 %arg) { ; CHECK-SAME: i32 [[ARG:%.*]]) { ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 true) ; CHECK-NEXT: [[ABS_PLUS_ONE:%.*]] = add nsw i32 [[ABS]], 1 -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[ABS_PLUS_ONE]], [[ARG]] +; CHECK-NEXT: ret i1 [[CMP]] ; %abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 true) %abs_plus_one = add nsw i32 %abs, 1 @@ -41,7 +44,8 @@ define i1 @arg_minus_one_strict_less(i32 %arg) { ; CHECK-SAME: i32 [[ARG:%.*]]) { ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 true) ; CHECK-NEXT: [[ARG_MINUS_ONE:%.*]] = add nsw i32 [[ARG]], -1 -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[ARG_MINUS_ONE]], [[ABS]] +; CHECK-NEXT: ret i1 [[CMP]] ; %abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 true) %arg_minus_one = add nsw i32 %arg, -1 @@ -54,7 +58,8 @@ define i1 @arg_minus_one_strict_greater(i32 %arg) { ; CHECK-SAME: i32 [[ARG:%.*]]) { ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 true) ; CHECK-NEXT: [[ARG_MINUS_ONE:%.*]] = add nsw i32 [[ARG]], -1 -; CHECK-NEXT: ret i1 false +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ARG_MINUS_ONE]], [[ABS]] +; CHECK-NEXT: ret i1 [[CMP]] ; %abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 true) %arg_minus_one = add nsw i32 %arg, -1 @@ -138,7 +143,8 @@ define i1 @abs_is_nonnegative_int_min_is_poison(i32 %arg) { ; CHECK-LABEL: define i1 @abs_is_nonnegative_int_min_is_poison( ; CHECK-SAME: i32 [[ARG:%.*]]) { ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[ARG]], i1 true) -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[ABS]], 0 +; CHECK-NEXT: ret i1 [[CMP]] ; %abs = tail call i32 @llvm.abs.i32(i32 %arg, i1 true) %cmp = icmp sge i32 %abs, 0 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits