Skip to content

Commit cca8f78

Browse files
committedSep 14, 2017
[InstSimplify] clean up div/rem handling; NFCI
The idea to make an 'isDivZero' helper was suggested for the signed case in D37713: https://reviews.llvm.org/D37713 This clean-up makes it clear that D37713 is just filling the gap for signed div/rem, removes unnecessary code, and allows us to remove a bit of duplicated code from the planned improvement in D37713. llvm-svn: 313261
1 parent 3d712c4 commit cca8f78

File tree

1 file changed

+44
-54
lines changed

1 file changed

+44
-54
lines changed
 

‎llvm/lib/Analysis/InstructionSimplify.cpp

+44-54
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,34 @@ static Value *simplifyDivRem(Value *Op0, Value *Op1, bool IsDiv) {
905905
return nullptr;
906906
}
907907

908+
/// Given a predicate and two operands, return true if the comparison is true.
909+
/// This is a helper for div/rem simplification where we return some other value
910+
/// when we can prove a relationship between the operands.
911+
static bool isICmpTrue(ICmpInst::Predicate Pred, Value *LHS, Value *RHS,
912+
const SimplifyQuery &Q, unsigned MaxRecurse) {
913+
Value *V = SimplifyICmpInst(Pred, LHS, RHS, Q, MaxRecurse);
914+
Constant *C = dyn_cast_or_null<Constant>(V);
915+
return (C && C->isAllOnesValue());
916+
}
917+
918+
/// Return true if we can simplify X / Y to 0. Remainder can adapt that answer
919+
/// to simplify X % Y to X.
920+
static bool isDivZero(Value *Op0, Value *Op1, const SimplifyQuery &Q,
921+
unsigned MaxRecurse, bool IsSigned) {
922+
// Recursion is always used, so bail out at once if we already hit the limit.
923+
if (!MaxRecurse--)
924+
return false;
925+
926+
if (IsSigned) {
927+
// TODO: Handle signed.
928+
return false;
929+
}
930+
931+
// IsSigned == false.
932+
// Is the quotient unsigned less than the divisor?
933+
return isICmpTrue(ICmpInst::ICMP_ULT, Op0, Op1, Q, MaxRecurse);
934+
}
935+
908936
/// These are simplifications common to SDiv and UDiv.
909937
static Value *simplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
910938
const SimplifyQuery &Q, unsigned MaxRecurse) {
@@ -914,16 +942,16 @@ static Value *simplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
914942
if (Value *V = simplifyDivRem(Op0, Op1, true))
915943
return V;
916944

917-
bool isSigned = Opcode == Instruction::SDiv;
945+
bool IsSigned = Opcode == Instruction::SDiv;
918946

919947
// (X * Y) / Y -> X if the multiplication does not overflow.
920948
Value *X = nullptr, *Y = nullptr;
921949
if (match(Op0, m_Mul(m_Value(X), m_Value(Y))) && (X == Op1 || Y == Op1)) {
922950
if (Y != Op1) std::swap(X, Y); // Ensure expression is (X * Y) / Y, Y = Op1
923951
OverflowingBinaryOperator *Mul = cast<OverflowingBinaryOperator>(Op0);
924952
// If the Mul knows it does not overflow, then we are good to go.
925-
if ((isSigned && Mul->hasNoSignedWrap()) ||
926-
(!isSigned && Mul->hasNoUnsignedWrap()))
953+
if ((IsSigned && Mul->hasNoSignedWrap()) ||
954+
(!IsSigned && Mul->hasNoUnsignedWrap()))
927955
return X;
928956
// If X has the form X = A / Y then X * Y cannot overflow.
929957
if (BinaryOperator *Div = dyn_cast<BinaryOperator>(X))
@@ -932,13 +960,13 @@ static Value *simplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
932960
}
933961

934962
// (X rem Y) / Y -> 0
935-
if ((isSigned && match(Op0, m_SRem(m_Value(), m_Specific(Op1)))) ||
936-
(!isSigned && match(Op0, m_URem(m_Value(), m_Specific(Op1)))))
963+
if ((IsSigned && match(Op0, m_SRem(m_Value(), m_Specific(Op1)))) ||
964+
(!IsSigned && match(Op0, m_URem(m_Value(), m_Specific(Op1)))))
937965
return Constant::getNullValue(Op0->getType());
938966

939967
// (X /u C1) /u C2 -> 0 if C1 * C2 overflow
940968
ConstantInt *C1, *C2;
941-
if (!isSigned && match(Op0, m_UDiv(m_Value(X), m_ConstantInt(C1))) &&
969+
if (!IsSigned && match(Op0, m_UDiv(m_Value(X), m_ConstantInt(C1))) &&
942970
match(Op1, m_ConstantInt(C2))) {
943971
bool Overflow;
944972
(void)C1->getValue().umul_ov(C2->getValue(), Overflow);
@@ -958,6 +986,9 @@ static Value *simplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
958986
if (Value *V = ThreadBinOpOverPHI(Opcode, Op0, Op1, Q, MaxRecurse))
959987
return V;
960988

989+
if (isDivZero(Op0, Op1, Q, MaxRecurse, IsSigned))
990+
return Constant::getNullValue(Op0->getType());
991+
961992
return nullptr;
962993
}
963994

@@ -989,32 +1020,9 @@ static Value *simplifyRem(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
9891020
if (Value *V = ThreadBinOpOverPHI(Opcode, Op0, Op1, Q, MaxRecurse))
9901021
return V;
9911022

992-
return nullptr;
993-
}
994-
995-
/// Given a predicate and two operands, return true if the comparison is true.
996-
/// This is a helper for div/rem simplification where we return some other value
997-
/// when we can prove a relationship between the operands.
998-
static bool isICmpTrue(ICmpInst::Predicate Pred, Value *LHS, Value *RHS,
999-
const SimplifyQuery &Q, unsigned MaxRecurse) {
1000-
Value *V = SimplifyICmpInst(Pred, LHS, RHS, Q, MaxRecurse);
1001-
Constant *C = dyn_cast_or_null<Constant>(V);
1002-
return (C && C->isAllOnesValue());
1003-
}
1004-
1005-
static Value *simplifyUnsignedDivRem(Value *Op0, Value *Op1,
1006-
const SimplifyQuery &Q,
1007-
unsigned MaxRecurse, bool IsDiv) {
1008-
// Recursion is always used, so bail out at once if we already hit the limit.
1009-
if (!MaxRecurse--)
1010-
return nullptr;
1011-
1012-
// If we can prove that the quotient is unsigned less than the divisor, then
1013-
// we know the answer:
1014-
// X / Y --> 0
1015-
// X % Y --> X
1016-
if (isICmpTrue(ICmpInst::ICMP_ULT, Op0, Op1, Q, MaxRecurse))
1017-
return IsDiv ? Constant::getNullValue(Op0->getType()) : Op0;
1023+
// If X / Y == 0, then X % Y == X.
1024+
if (isDivZero(Op0, Op1, Q, MaxRecurse, Opcode == Instruction::SRem))
1025+
return Op0;
10181026

10191027
return nullptr;
10201028
}
@@ -1023,10 +1031,7 @@ static Value *simplifyUnsignedDivRem(Value *Op0, Value *Op1,
10231031
/// If not, this returns null.
10241032
static Value *SimplifySDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
10251033
unsigned MaxRecurse) {
1026-
if (Value *V = simplifyDiv(Instruction::SDiv, Op0, Op1, Q, MaxRecurse))
1027-
return V;
1028-
1029-
return nullptr;
1034+
return simplifyDiv(Instruction::SDiv, Op0, Op1, Q, MaxRecurse);
10301035
}
10311036

10321037
Value *llvm::SimplifySDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {
@@ -1037,13 +1042,7 @@ Value *llvm::SimplifySDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {
10371042
/// If not, this returns null.
10381043
static Value *SimplifyUDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
10391044
unsigned MaxRecurse) {
1040-
if (Value *V = simplifyDiv(Instruction::UDiv, Op0, Op1, Q, MaxRecurse))
1041-
return V;
1042-
1043-
if (Value *V = simplifyUnsignedDivRem(Op0, Op1, Q, MaxRecurse, true))
1044-
return V;
1045-
1046-
return nullptr;
1045+
return simplifyDiv(Instruction::UDiv, Op0, Op1, Q, MaxRecurse);
10471046
}
10481047

10491048
Value *llvm::SimplifyUDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {
@@ -1054,10 +1053,7 @@ Value *llvm::SimplifyUDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {
10541053
/// If not, this returns null.
10551054
static Value *SimplifySRemInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
10561055
unsigned MaxRecurse) {
1057-
if (Value *V = simplifyRem(Instruction::SRem, Op0, Op1, Q, MaxRecurse))
1058-
return V;
1059-
1060-
return nullptr;
1056+
return simplifyRem(Instruction::SRem, Op0, Op1, Q, MaxRecurse);
10611057
}
10621058

10631059
Value *llvm::SimplifySRemInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {
@@ -1068,13 +1064,7 @@ Value *llvm::SimplifySRemInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {
10681064
/// If not, this returns null.
10691065
static Value *SimplifyURemInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
10701066
unsigned MaxRecurse) {
1071-
if (Value *V = simplifyRem(Instruction::URem, Op0, Op1, Q, MaxRecurse))
1072-
return V;
1073-
1074-
if (Value *V = simplifyUnsignedDivRem(Op0, Op1, Q, MaxRecurse, false))
1075-
return V;
1076-
1077-
return nullptr;
1067+
return simplifyRem(Instruction::URem, Op0, Op1, Q, MaxRecurse);
10781068
}
10791069

10801070
Value *llvm::SimplifyURemInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {

0 commit comments

Comments
 (0)
Please sign in to comment.