[InstSimplify] refactor related div/rem folds; NFCI

llvm-svn: 297052
This commit is contained in:
Sanjay Patel 2017-03-06 19:08:35 +00:00
parent 95b6d5f2b1
commit 0cb2ee9287
1 changed files with 45 additions and 55 deletions

View File

@ -1009,6 +1009,46 @@ Value *llvm::SimplifyMulInst(Value *Op0, Value *Op1, const DataLayout &DL,
RecursionLimit);
}
/// Check for common or similar folds of integer division or integer remainder.
static Value *simplifyDivRem(Value *Op0, Value *Op1, bool IsDiv) {
Type *Ty = Op0->getType();
// X / undef -> undef
// X % undef -> undef
if (match(Op1, m_Undef()))
return Op1;
// X / 0 -> undef
// X % 0 -> undef
// We don't need to preserve faults!
if (match(Op1, m_Zero()))
return UndefValue::get(Ty);
// undef / X -> 0
// undef % X -> 0
if (match(Op0, m_Undef()))
return Constant::getNullValue(Ty);
// 0 / X -> 0
// 0 % X -> 0
if (match(Op0, m_Zero()))
return Op0;
// X / X -> 1
// X % X -> 0
if (Op0 == Op1)
return IsDiv ? ConstantInt::get(Ty, 1) : Constant::getNullValue(Ty);
// X / 1 -> X
// X % 1 -> 0
// If this is a boolean op (single-bit type), we can't have division-by-zero
// or remainder-by-zero, so assume the divisor is 1.
if (match(Op1, m_One()) || Ty->isIntegerTy(1))
return IsDiv ? Op0 : Constant::getNullValue(Ty);
return nullptr;
}
/// Given operands for an SDiv or UDiv, see if we can fold the result.
/// If not, this returns null.
static Value *SimplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
@ -1017,36 +1057,11 @@ static Value *SimplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
if (Constant *C1 = dyn_cast<Constant>(Op1))
return ConstantFoldBinaryOpOperands(Opcode, C0, C1, Q.DL);
if (Value *V = simplifyDivRem(Op0, Op1, true))
return V;
bool isSigned = Opcode == Instruction::SDiv;
// X / undef -> undef
if (match(Op1, m_Undef()))
return Op1;
// X / 0 -> undef, we don't need to preserve faults!
if (match(Op1, m_Zero()))
return UndefValue::get(Op1->getType());
// undef / X -> 0
if (match(Op0, m_Undef()))
return Constant::getNullValue(Op0->getType());
// 0 / X -> 0
if (match(Op0, m_Zero()))
return Op0;
// X / 1 -> X
if (match(Op1, m_One()))
return Op0;
if (Op0->getType()->isIntegerTy(1))
// It can't be division by zero, hence it must be division by one.
return Op0;
// X / X -> 1
if (Op0 == Op1)
return ConstantInt::get(Op0->getType(), 1);
// (X * Y) / Y -> X if the multiplication does not overflow.
Value *X = nullptr, *Y = nullptr;
if (match(Op0, m_Mul(m_Value(X), m_Value(Y))) && (X == Op1 || Y == Op1)) {
@ -1193,33 +1208,8 @@ static Value *SimplifyRem(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
if (Constant *C1 = dyn_cast<Constant>(Op1))
return ConstantFoldBinaryOpOperands(Opcode, C0, C1, Q.DL);
// X % undef -> undef
if (match(Op1, m_Undef()))
return Op1;
// undef % X -> 0
if (match(Op0, m_Undef()))
return Constant::getNullValue(Op0->getType());
// 0 % X -> 0
if (match(Op0, m_Zero()))
return Op0;
// X % 0 -> undef, we don't need to preserve faults!
if (match(Op1, m_Zero()))
return UndefValue::get(Op0->getType());
// X % 1 -> 0
if (match(Op1, m_One()))
return Constant::getNullValue(Op0->getType());
if (Op0->getType()->isIntegerTy(1))
// It can't be remainder by zero, hence it must be remainder by one.
return Constant::getNullValue(Op0->getType());
// X % X -> 0
if (Op0 == Op1)
return Constant::getNullValue(Op0->getType());
if (Value *V = simplifyDivRem(Op0, Op1, false))
return V;
// (X % Y) % Y -> X % Y
if ((Opcode == Instruction::SRem &&