[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