[llvm] d117ee2 - [InstCombine] add helper function for div+shl folds; NFC
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 12 06:26:42 PDT 2022
Author: Sanjay Patel
Date: 2022-10-12T09:25:04-04:00
New Revision: d117ee25b8d19dd63deecaed4759be032708dd90
URL: https://github.com/llvm/llvm-project/commit/d117ee25b8d19dd63deecaed4759be032708dd90
DIFF: https://github.com/llvm/llvm-project/commit/d117ee25b8d19dd63deecaed4759be032708dd90.diff
LOG: [InstCombine] add helper function for div+shl folds; NFC
There are at least 2 similar patterns that could be added here,
and the existing fold can be improved because it fails to
propagate "exact".
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 1f34d6f6fb80e..c7a7be1886d9b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -816,6 +816,41 @@ static bool isMultiple(const APInt &C1, const APInt &C2, APInt &Quotient,
return Remainder.isMinValue();
}
+static Instruction *foldIDivShl(BinaryOperator &I,
+ InstCombiner::BuilderTy &Builder) {
+ assert((I.getOpcode() == Instruction::SDiv ||
+ I.getOpcode() == Instruction::UDiv) &&
+ "Expected integer divide");
+
+ bool IsSigned = I.getOpcode() == Instruction::SDiv;
+ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+ Type *Ty = I.getType();
+
+ // With appropriate no-wrap constraints, remove a common factor in the
+ // dividend and divisor that is disguised as a left-shift.
+ Value *X, *Y, *Z;
+ if (match(Op1, m_Shl(m_Value(X), m_Value(Z))) &&
+ match(Op0, m_c_Mul(m_Specific(X), m_Value(Y)))) {
+ // Both operands must have the matching no-wrap for this kind of division.
+ auto *Mul = cast<OverflowingBinaryOperator>(Op0);
+ auto *Shl = cast<OverflowingBinaryOperator>(Op1);
+ bool HasNUW = Mul->hasNoUnsignedWrap() && Shl->hasNoUnsignedWrap();
+ bool HasNSW = Mul->hasNoSignedWrap() && Shl->hasNoSignedWrap();
+
+ // (X * Y) u/ (X << Z) --> Y u>> Z
+ if (!IsSigned && HasNUW)
+ return BinaryOperator::CreateLShr(Y, Z);
+
+ // (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);
+ return BinaryOperator::CreateSDiv(Y, Shl);
+ }
+ }
+
+ return nullptr;
+}
+
/// This function implements the transforms common to both integer division
/// instructions (udiv and sdiv). It is called by the visitors to those integer
/// division instructions.
@@ -962,26 +997,8 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
}
}
- // With appropriate no-wrap constraints, remove a common factor in the
- // dividend and divisor that is disguised as a left-shift.
- if (match(Op1, m_Shl(m_Value(X), m_Value(Z))) &&
- match(Op0, m_c_Mul(m_Specific(X), m_Value(Y)))) {
- // Both operands must have the matching no-wrap for this kind of division.
- auto *OBO0 = cast<OverflowingBinaryOperator>(Op0);
- auto *OBO1 = cast<OverflowingBinaryOperator>(Op1);
- bool HasNUW = OBO0->hasNoUnsignedWrap() && OBO1->hasNoUnsignedWrap();
- bool HasNSW = OBO0->hasNoSignedWrap() && OBO1->hasNoSignedWrap();
-
- // (X * Y) u/ (X << Z) --> Y u>> Z
- if (!IsSigned && HasNUW)
- return BinaryOperator::CreateLShr(Y, Z);
-
- // (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);
- return BinaryOperator::CreateSDiv(Y, Shl);
- }
- }
+ if (Instruction *R = foldIDivShl(I, Builder))
+ return R;
// With the appropriate no-wrap constraint, remove a multiply by the divisor
// after peeking through another divide:
More information about the llvm-commits
mailing list