[llvm] [InstCombine] Simplify fractions when there is no overflow (PR #92949)
via llvm-commits
llvm-commits at lists.llvm.org
Tue May 21 11:36:35 PDT 2024
https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/92949
>From 63d8028db5d75a2aa72e290dce47bd7f5f4b8dae Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Tue, 21 May 2024 14:09:05 -0400
Subject: [PATCH] [InstCombine] Simplify fractions when there is no overlap
---
.../InstCombine/InstCombineMulDivRem.cpp | 60 +++++++++++++++++--
1 file changed, 55 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index ca1b1921404d8..34fb266ca27fd 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1057,7 +1057,8 @@ static Value *foldIDivShl(BinaryOperator &I, InstCombiner::BuilderTy &Builder) {
// (X * Y) s/ (X << Z) --> Y s/ (1 << Z)
if (IsSigned && HasNSW && (Op0->hasOneUse() || Op1->hasOneUse())) {
- Value *Shl = Builder.CreateShl(ConstantInt::get(Ty, 1), Z);
+ Value *Shl =
+ Builder.CreateShl(ConstantInt::get(Ty, 1), Z, "", HasNUW, true);
return Builder.CreateSDiv(Y, Shl, "", I.isExact());
}
}
@@ -1169,13 +1170,52 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
// (X * C1) / C2 -> X * (C1 / C2) if C1 is a multiple of C2.
if (isMultiple(*C1, *C2, Quotient, IsSigned)) {
+ assert(!C1.isOne() && !C2.isOne() && !C1.isZero() && !C2.isZero() &&
+ "InstSimplify should have removed constants of 1!");
auto *Mul = BinaryOperator::Create(Instruction::Mul, X,
ConstantInt::get(Ty, Quotient));
auto *OBO = cast<OverflowingBinaryOperator>(Op0);
- Mul->setHasNoUnsignedWrap(!IsSigned && OBO->hasNoUnsignedWrap());
- Mul->setHasNoSignedWrap(OBO->hasNoSignedWrap());
+ Mul->setHasNoUnsignedWrap(OBO->hasNoUnsignedWrap());
+ Mul->setHasNoSignedWrap(true);
return Mul;
}
+
+ // We can reduce expressions of things like * 150 / 100 to * 3 / 2
+ if (Op0->hasOneUse() && !C2->isZero() &&
+ !(IsSigned && C1->isMinSignedValue() && C2->isAllOnes())) {
+ APInt GCD = APIntOps::GreatestCommonDivisor(C1->abs(), C2->abs());
+ if (!GCD.isOne() && !GCD.isZero()) {
+ APInt NewC1;
+ APInt NewC2;
+ if (IsSigned && C1->isNegative() && C2->isNegative()) {
+ NewC1 = C1->abs().udiv(GCD);
+ NewC2 = C2->abs().udiv(GCD);
+ } else if (IsSigned) {
+ NewC1 = C1->sdiv(GCD);
+ NewC2 = C2->sdiv(GCD);
+ } else {
+ NewC1 = C1->udiv(GCD);
+ NewC2 = C2->udiv(GCD);
+ }
+
+ auto *NewMul = Builder.CreateMul(
+ X, ConstantInt::get(Ty, NewC1), "",
+ /*NUW*/ cast<OverflowingBinaryOperator>(Op0)->hasNoUnsignedWrap(),
+ /*NSW*/ true);
+
+ if (IsSigned) {
+ auto *NewDiv =
+ BinaryOperator::CreateSDiv(NewMul, ConstantInt::get(Ty, NewC2));
+ NewDiv->setIsExact(I.isExact());
+ return NewDiv;
+ }
+
+ auto *NewDiv =
+ BinaryOperator::CreateUDiv(NewMul, ConstantInt::get(Ty, NewC2));
+ NewDiv->setIsExact(I.isExact());
+ return NewDiv;
+ }
+ }
}
if ((IsSigned && match(Op0, m_NSWShl(m_Value(X), m_APInt(C1))) &&
@@ -1198,7 +1238,7 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
auto *Mul = BinaryOperator::Create(Instruction::Mul, X,
ConstantInt::get(Ty, Quotient));
auto *OBO = cast<OverflowingBinaryOperator>(Op0);
- Mul->setHasNoUnsignedWrap(!IsSigned && OBO->hasNoUnsignedWrap());
+ Mul->setHasNoUnsignedWrap(OBO->hasNoUnsignedWrap());
Mul->setHasNoSignedWrap(OBO->hasNoSignedWrap());
return Mul;
}
@@ -1273,7 +1313,6 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
}
// (X << Z) / (X * Y) -> (1 << Z) / Y
- // TODO: Handle sdiv.
if (!IsSigned && Op1->hasOneUse() &&
match(Op0, m_NUWShl(m_Value(X), m_Value(Z))) &&
match(Op1, m_c_Mul(m_Specific(X), m_Value(Y))))
@@ -1284,6 +1323,17 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
return NewDiv;
}
+ // (X << Z) / (X * Y) -> (1 << Z) / Y
+ if (IsSigned && Op1->hasOneUse() &&
+ match(Op0, m_NSWShl(m_Value(X), m_Value(Z))) &&
+ match(Op1, m_c_Mul(m_Specific(X), m_Value(Y))))
+ if (cast<OverflowingBinaryOperator>(Op1)->hasNoSignedWrap()) {
+ Instruction *NewDiv = BinaryOperator::CreateSDiv(
+ Builder.CreateShl(ConstantInt::get(Ty, 1), Z, "", /*NSW*/ true), Y);
+ NewDiv->setIsExact(I.isExact());
+ return NewDiv;
+ }
+
if (Value *R = foldIDivShl(I, Builder))
return replaceInstUsesWith(I, R);
More information about the llvm-commits
mailing list