Skip to content

Commit d117ee2

Browse files
committed
[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".
1 parent bc032c7 commit d117ee2

File tree

1 file changed

+37
-20
lines changed

1 file changed

+37
-20
lines changed

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,41 @@ static bool isMultiple(const APInt &C1, const APInt &C2, APInt &Quotient,
816816
return Remainder.isMinValue();
817817
}
818818

819+
static Instruction *foldIDivShl(BinaryOperator &I,
820+
InstCombiner::BuilderTy &Builder) {
821+
assert((I.getOpcode() == Instruction::SDiv ||
822+
I.getOpcode() == Instruction::UDiv) &&
823+
"Expected integer divide");
824+
825+
bool IsSigned = I.getOpcode() == Instruction::SDiv;
826+
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
827+
Type *Ty = I.getType();
828+
829+
// With appropriate no-wrap constraints, remove a common factor in the
830+
// dividend and divisor that is disguised as a left-shift.
831+
Value *X, *Y, *Z;
832+
if (match(Op1, m_Shl(m_Value(X), m_Value(Z))) &&
833+
match(Op0, m_c_Mul(m_Specific(X), m_Value(Y)))) {
834+
// Both operands must have the matching no-wrap for this kind of division.
835+
auto *Mul = cast<OverflowingBinaryOperator>(Op0);
836+
auto *Shl = cast<OverflowingBinaryOperator>(Op1);
837+
bool HasNUW = Mul->hasNoUnsignedWrap() && Shl->hasNoUnsignedWrap();
838+
bool HasNSW = Mul->hasNoSignedWrap() && Shl->hasNoSignedWrap();
839+
840+
// (X * Y) u/ (X << Z) --> Y u>> Z
841+
if (!IsSigned && HasNUW)
842+
return BinaryOperator::CreateLShr(Y, Z);
843+
844+
// (X * Y) s/ (X << Z) --> Y s/ (1 << Z)
845+
if (IsSigned && HasNSW && (Op0->hasOneUse() || Op1->hasOneUse())) {
846+
Value *Shl = Builder.CreateShl(ConstantInt::get(Ty, 1), Z);
847+
return BinaryOperator::CreateSDiv(Y, Shl);
848+
}
849+
}
850+
851+
return nullptr;
852+
}
853+
819854
/// This function implements the transforms common to both integer division
820855
/// instructions (udiv and sdiv). It is called by the visitors to those integer
821856
/// division instructions.
@@ -962,26 +997,8 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
962997
}
963998
}
964999

965-
// With appropriate no-wrap constraints, remove a common factor in the
966-
// dividend and divisor that is disguised as a left-shift.
967-
if (match(Op1, m_Shl(m_Value(X), m_Value(Z))) &&
968-
match(Op0, m_c_Mul(m_Specific(X), m_Value(Y)))) {
969-
// Both operands must have the matching no-wrap for this kind of division.
970-
auto *OBO0 = cast<OverflowingBinaryOperator>(Op0);
971-
auto *OBO1 = cast<OverflowingBinaryOperator>(Op1);
972-
bool HasNUW = OBO0->hasNoUnsignedWrap() && OBO1->hasNoUnsignedWrap();
973-
bool HasNSW = OBO0->hasNoSignedWrap() && OBO1->hasNoSignedWrap();
974-
975-
// (X * Y) u/ (X << Z) --> Y u>> Z
976-
if (!IsSigned && HasNUW)
977-
return BinaryOperator::CreateLShr(Y, Z);
978-
979-
// (X * Y) s/ (X << Z) --> Y s/ (1 << Z)
980-
if (IsSigned && HasNSW && (Op0->hasOneUse() || Op1->hasOneUse())) {
981-
Value *Shl = Builder.CreateShl(ConstantInt::get(Ty, 1), Z);
982-
return BinaryOperator::CreateSDiv(Y, Shl);
983-
}
984-
}
1000+
if (Instruction *R = foldIDivShl(I, Builder))
1001+
return R;
9851002

9861003
// With the appropriate no-wrap constraint, remove a multiply by the divisor
9871004
// after peeking through another divide:

0 commit comments

Comments
 (0)