mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-19 02:25:01 +00:00
[InstCombine] Don't eagerly propagate nsw for A*B+A*C => A*(B+C)
InstCombine transforms A *nsw B +nsw A *nsw C to A *nsw (B + C). This is incorrect -- e.g. if A = -1, B = 1, C = INT_SMAX. Then nothing in the LHS overflows, but the multiplication in RHS overflows. We need to first make sure that we won't multiple by INT_SMAX + 1. Test case `add_of_mul` contributed by Sanjoy Das. This fixes PR23635. Differential Revision: http://reviews.llvm.org/D9629 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238066 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -452,6 +452,7 @@ static Value *tryFactorization(InstCombiner::BuilderTy *Builder,
|
||||
if (!A || !C || !B || !D)
|
||||
return nullptr;
|
||||
|
||||
Value *V = nullptr;
|
||||
Value *SimplifiedInst = nullptr;
|
||||
Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
|
||||
Instruction::BinaryOps TopLevelOpcode = I.getOpcode();
|
||||
@@ -468,7 +469,7 @@ static Value *tryFactorization(InstCombiner::BuilderTy *Builder,
|
||||
std::swap(C, D);
|
||||
// Consider forming "A op' (B op D)".
|
||||
// If "B op D" simplifies then it can be formed with no cost.
|
||||
Value *V = SimplifyBinOp(TopLevelOpcode, B, D, DL);
|
||||
V = SimplifyBinOp(TopLevelOpcode, B, D, DL);
|
||||
// If "B op D" doesn't simplify then only go on if both of the existing
|
||||
// operations "A op' B" and "C op' D" will be zapped as no longer used.
|
||||
if (!V && LHS->hasOneUse() && RHS->hasOneUse())
|
||||
@@ -487,7 +488,7 @@ static Value *tryFactorization(InstCombiner::BuilderTy *Builder,
|
||||
std::swap(C, D);
|
||||
// Consider forming "(A op C) op' B".
|
||||
// If "A op C" simplifies then it can be formed with no cost.
|
||||
Value *V = SimplifyBinOp(TopLevelOpcode, A, C, DL);
|
||||
V = SimplifyBinOp(TopLevelOpcode, A, C, DL);
|
||||
|
||||
// If "A op C" doesn't simplify then only go on if both of the existing
|
||||
// operations "A op' B" and "C op' D" will be zapped as no longer used.
|
||||
@@ -517,7 +518,19 @@ static Value *tryFactorization(InstCombiner::BuilderTy *Builder,
|
||||
if (BinaryOperator *Op1 = dyn_cast<BinaryOperator>(RHS))
|
||||
if (isa<OverflowingBinaryOperator>(Op1))
|
||||
HasNSW &= Op1->hasNoSignedWrap();
|
||||
BO->setHasNoSignedWrap(HasNSW);
|
||||
|
||||
// We can propogate 'nsw' if we know that
|
||||
// %Y = mul nsw i16 %X, C
|
||||
// %Z = add nsw i16 %Y, %X
|
||||
// =>
|
||||
// %Z = mul nsw i16 %X, C+1
|
||||
//
|
||||
// iff C+1 isn't INT_MIN
|
||||
const APInt *CInt;
|
||||
if (TopLevelOpcode == Instruction::Add &&
|
||||
InnerOpcode == Instruction::Mul)
|
||||
if (match(V, m_APInt(CInt)) && !CInt->isMinSignedValue())
|
||||
BO->setHasNoSignedWrap(HasNSW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user