[InstSimplify] refactor related div/rem folds; NFCI
llvm-svn: 297052
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index f9c5a46..369cf1d 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1009,6 +1009,46 @@
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 @@
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 @@
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 &&