[llvm-commits] [llvm] r124487 - in /llvm/trunk: include/llvm/Analysis/InstructionSimplify.h lib/Analysis/InstructionSimplify.cpp lib/Transforms/InstCombine/InstCombineMulDivRem.cpp test/Transforms/InstCombine/2008-11-20-DivMulRem.ll test/Transfor
Frits van Bommel
fvbommel at gmail.com
Fri Jan 28 10:42:07 PST 2011
SimplifyInstruction:
On Fri, Jan 28, 2011 at 5:51 PM, Duncan Sands <baldrick at free.fr> wrote:
> + // (X * Y) / Y -> X if the multiplication does not overflow.
> + Value *X = 0, *Y = 0;
> + if (match(Op0, m_Mul(m_Value(X), m_Value(Y))) && (X == Op1 || Y == Op1)) {
> + if (Y != Op1) std::swap(X, Y); // Ensure expression is (X * Y) / Y, Y = Op1
> + BinaryOperator *Mul = dyn_cast<BinaryOperator>(Op0);
This can be a regular cast<> since you just matched Op0 agains m_Mul().
> + // If the Mul knows it does not overflow, then we are good to go.
> + bool isSigned = Opcode == Instruction::SDiv;
> + if ((isSigned && Mul->hasNoSignedWrap()) ||
> + (!isSigned && Mul->hasNoUnsignedWrap()))
> + return X;
> + // If X has the form X = A / Y then X * Y cannot overflow.
> + if (BinaryOperator *Div = dyn_cast<BinaryOperator>(X))
> + if (Div->getOpcode() == Opcode && Div->getOperand(1) == Y)
> + return X;
This could also handle the "X = A / Z and Y < Z" case, especially for
constant integers Y and Z.
> + }
> +
> + return 0;
> +}
> +
> +/// SimplifySDivInst - Given operands for an SDiv, see if we can
> +/// fold the result. If not, this returns null.
> +static Value *SimplifySDivInst(Value *Op0, Value *Op1, const TargetData *TD,
> + const DominatorTree *DT, unsigned MaxRecurse) {
> + if (Value *V = SimplifyDiv(Instruction::SDiv, Op0, Op1, TD, DT, MaxRecurse))
> + return V;
> +
> + // (X rem Y) / Y -> 0
> + if (match(Op0, m_SRem(m_Value(), m_Specific(Op1))))
> + return Constant::getNullValue(Op0->getType());
Similarly, this could also handle (X rem Z) / Y where Z < Y.
> +
> + return 0;
> +}
> +
> +Value *llvm::SimplifySDivInst(Value *Op0, Value *Op1, const TargetData *TD,
> + const DominatorTree *DT) {
> + return ::SimplifySDivInst(Op0, Op1, TD, DT, RecursionLimit);
> +}
> +
> +/// SimplifyUDivInst - Given operands for a UDiv, see if we can
> +/// fold the result. If not, this returns null.
> +static Value *SimplifyUDivInst(Value *Op0, Value *Op1, const TargetData *TD,
> + const DominatorTree *DT, unsigned MaxRecurse) {
> + if (Value *V = SimplifyDiv(Instruction::UDiv, Op0, Op1, TD, DT, MaxRecurse))
> + return V;
> +
> + // (X rem Y) / Y -> 0
> + if (match(Op0, m_URem(m_Value(), m_Specific(Op1))))
> + return Constant::getNullValue(Op0->getType());
Ditto.
> +
> + return 0;
> +}
InstCombine:
> + // (X - (X rem Y)) / Y -> X / Y; usually originates as ((X / Y) * Y) / Y
> + Value *X = 0, *Z = 0;
> + if (match(Op0, m_Sub(m_Value(X), m_Value(Z)))) { // (X - Z) / Y; Y = Op1
> + bool isSigned = I.getOpcode() == Instruction::SDiv;
> + if ((isSigned && match(Z, m_SRem(m_Specific(X), m_Specific(Op1)))) ||
> + (!isSigned && match(Z, m_URem(m_Specific(X), m_Specific(Op1)))))
> + return BinaryOperator::Create(I.getOpcode(), X, Op1);
> }
This can also handle (X - (X rem Z)) / Y for Z < Y.
> @@ -516,7 +474,17 @@
> }
>
> Instruction *InstCombiner::visitFDiv(BinaryOperator &I) {
> - return commonDivTransforms(I);
> + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
> +
> + // undef / X -> undef (the undef could be a snan).
> + if (isa<UndefValue>(Op0))
> + return ReplaceInstUsesWith(I, Op0);
> +
> + // X / undef -> undef
> + if (isa<UndefValue>(Op1))
> + return ReplaceInstUsesWith(I, Op1);
> +
> + return 0;
> }
This looks like it belongs in the SimplifyInstruction infrastructure.
More information about the llvm-commits
mailing list