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.
}
}
- // 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: