[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/Transforms/InstSimplify/2010-12-20-Reassociate.ll

Evan Cheng evan.cheng at apple.com
Sun Jan 30 10:10:44 PST 2011


Hi Duncan,

This broke 254.gap (Darwin, clang, i386 and x86_64).  Please investigate or at least consider backing it out for now.

Thanks,

Evan

On Jan 28, 2011, at 8:51 AM, Duncan Sands wrote:

> Author: baldrick
> Date: Fri Jan 28 10:51:11 2011
> New Revision: 124487
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=124487&view=rev
> Log:
> My auto-simplifier noticed that ((X/Y)*Y)/Y occurs several times in SPEC
> benchmarks, and that it can be simplified to X/Y.  (In general you can only
> simplify (Z*Y)/Y to Z if the multiplication did not overflow; if Z has the
> form "X/Y" then this is the case).  This patch implements that transform and
> moves some Div logic out of instcombine and into InstructionSimplify.
> Unfortunately instcombine gets in the way somewhat, since it likes to change
> (X/Y)*Y into X-(X rem Y), so I had to teach instcombine about this too.
> Finally, thanks to the NSW/NUW flags, sometimes we know directly that "Z*Y"
> does not overflow, because the flag says so, so I added that logic too.  This
> eliminates a bunch of divisions and subtractions in 447.dealII, and has good
> effects on some other benchmarks too.  It seems to have quite an effect on
> tramp3d-v4 but it's hard to say if it's good or bad because inlining decisions
> changed, resulting in massive changes all over.
> 
> Modified:
>    llvm/trunk/include/llvm/Analysis/InstructionSimplify.h
>    llvm/trunk/lib/Analysis/InstructionSimplify.cpp
>    llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
>    llvm/trunk/test/Transforms/InstCombine/2008-11-20-DivMulRem.ll
>    llvm/trunk/test/Transforms/InstSimplify/2010-12-20-Reassociate.ll
> 
> Modified: llvm/trunk/include/llvm/Analysis/InstructionSimplify.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/InstructionSimplify.h?rev=124487&r1=124486&r2=124487&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Analysis/InstructionSimplify.h (original)
> +++ llvm/trunk/include/llvm/Analysis/InstructionSimplify.h Fri Jan 28 10:51:11 2011
> @@ -40,6 +40,16 @@
>   Value *SimplifyMulInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
>                          const DominatorTree *DT = 0);
> 
> +  /// SimplifySDivInst - Given operands for an SDiv, see if we can
> +  /// fold the result.  If not, this returns null.
> +  Value *SimplifySDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
> +                          const DominatorTree *DT = 0);
> +
> +  /// SimplifyUDivInst - Given operands for a UDiv, see if we can
> +  /// fold the result.  If not, this returns null.
> +  Value *SimplifyUDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
> +                         const DominatorTree *DT = 0);
> +
>   /// SimplifyShlInst - Given operands for a Shl, see if we can
>   /// fold the result.  If not, this returns null.
>   Value *SimplifyShlInst(Value *Op0, Value *Op1, const TargetData *TD = 0,
> 
> Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=124487&r1=124486&r2=124487&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
> +++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Fri Jan 28 10:51:11 2011
> @@ -747,6 +747,105 @@
>   return ::SimplifyMulInst(Op0, Op1, TD, DT, RecursionLimit);
> }
> 
> +/// SimplifyDiv - Given operands for an SDiv or UDiv, see if we can
> +/// fold the result.  If not, this returns null.
> +static Value *SimplifyDiv(unsigned Opcode, Value *Op0, Value *Op1,
> +                          const TargetData *TD, const DominatorTree *DT,
> +                          unsigned MaxRecurse) {
> +  if (Constant *C0 = dyn_cast<Constant>(Op0)) {
> +    if (Constant *C1 = dyn_cast<Constant>(Op1)) {
> +      Constant *Ops[] = { C0, C1 };
> +      return ConstantFoldInstOperands(Opcode, C0->getType(), Ops, 2, TD);
> +    }
> +  }
> +
> +  // X / undef -> undef
> +  if (isa<UndefValue>(Op1))
> +    return Op1;
> +
> +  // undef / X -> 0
> +  if (isa<UndefValue>(Op0))
> +    return Constant::getNullValue(Op0->getType());
> +
> +  // 0 / X -> 0, we don't need to preserve faults!
> +  if (match(Op0, m_Zero()))
> +    return Op0;
> +
> +  // X / 1 -> X
> +  if (match(Op1, m_One()))
> +    return Op0;
> +  // Vector case. TODO: Have m_One match vectors.
> +  if (ConstantVector *Op1V = dyn_cast<ConstantVector>(Op1)) {
> +    if (ConstantInt *X = cast_or_null<ConstantInt>(Op1V->getSplatValue()))
> +      if (X->isOne())
> +        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 = 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);
> +    // 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;
> +  }
> +
> +  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());
> +
> +  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());
> +
> +  return 0;
> +}
> +
> +Value *llvm::SimplifyUDivInst(Value *Op0, Value *Op1, const TargetData *TD,
> +                             const DominatorTree *DT) {
> +  return ::SimplifyUDivInst(Op0, Op1, TD, DT, RecursionLimit);
> +}
> +
> /// SimplifyShift - Given operands for an Shl, LShr or AShr, see if we can
> /// fold the result.  If not, this returns null.
> static Value *SimplifyShift(unsigned Opcode, Value *Op0, Value *Op1,
> @@ -1649,6 +1748,8 @@
>                                                 /* isNUW */ false, TD, DT,
>                                                 MaxRecurse);
>   case Instruction::Mul: return SimplifyMulInst(LHS, RHS, TD, DT, MaxRecurse);
> +  case Instruction::SDiv: return SimplifySDivInst(LHS, RHS, TD, DT, MaxRecurse);
> +  case Instruction::UDiv: return SimplifyUDivInst(LHS, RHS, TD, DT, MaxRecurse);
>   case Instruction::Shl: return SimplifyShlInst(LHS, RHS, TD, DT, MaxRecurse);
>   case Instruction::LShr: return SimplifyLShrInst(LHS, RHS, TD, DT, MaxRecurse);
>   case Instruction::AShr: return SimplifyAShrInst(LHS, RHS, TD, DT, MaxRecurse);
> @@ -1730,6 +1831,12 @@
>   case Instruction::Mul:
>     Result = SimplifyMulInst(I->getOperand(0), I->getOperand(1), TD, DT);
>     break;
> +  case Instruction::SDiv:
> +    Result = SimplifySDivInst(I->getOperand(0), I->getOperand(1), TD, DT);
> +    break;
> +  case Instruction::UDiv:
> +    Result = SimplifyUDivInst(I->getOperand(0), I->getOperand(1), TD, DT);
> +    break;
>   case Instruction::Shl:
>     Result = SimplifyShlInst(I->getOperand(0), I->getOperand(1), TD, DT);
>     break;
> 
> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp?rev=124487&r1=124486&r2=124487&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (original)
> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp Fri Jan 28 10:51:11 2011
> @@ -304,28 +304,6 @@
> }
> 
> 
> -/// This function implements the transforms on div instructions that work
> -/// regardless of the kind of div instruction it is (udiv, sdiv, or fdiv). It is
> -/// used by the visitors to those instructions.
> -/// @brief Transforms common to all three div instructions
> -Instruction *InstCombiner::commonDivTransforms(BinaryOperator &I) {
> -  Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
> -
> -  // undef / X -> 0        for integer.
> -  // undef / X -> undef    for FP (the undef could be a snan).
> -  if (isa<UndefValue>(Op0)) {
> -    if (Op0->getType()->isFPOrFPVectorTy())
> -      return ReplaceInstUsesWith(I, Op0);
> -    return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
> -  }
> -
> -  // X / undef -> undef
> -  if (isa<UndefValue>(Op1))
> -    return ReplaceInstUsesWith(I, Op1);
> -
> -  return 0;
> -}
> -
> /// This function implements the transforms common to both integer division
> /// instructions (udiv and sdiv). It is called by the visitors to those integer
> /// division instructions.
> @@ -333,31 +311,12 @@
> Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) {
>   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
> 
> -  // (sdiv X, X) --> 1     (udiv X, X) --> 1
> -  if (Op0 == Op1) {
> -    if (const VectorType *Ty = dyn_cast<VectorType>(I.getType())) {
> -      Constant *CI = ConstantInt::get(Ty->getElementType(), 1);
> -      std::vector<Constant*> Elts(Ty->getNumElements(), CI);
> -      return ReplaceInstUsesWith(I, ConstantVector::get(Elts));
> -    }
> -
> -    Constant *CI = ConstantInt::get(I.getType(), 1);
> -    return ReplaceInstUsesWith(I, CI);
> -  }
> -  
> -  if (Instruction *Common = commonDivTransforms(I))
> -    return Common;
> -  
>   // Handle cases involving: [su]div X, (select Cond, Y, Z)
>   // This does not apply for fdiv.
>   if (isa<SelectInst>(Op1) && SimplifyDivRemOfSelect(I))
>     return &I;
> 
>   if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
> -    // div X, 1 == X
> -    if (RHS->equalsInt(1))
> -      return ReplaceInstUsesWith(I, Op0);
> -
>     // (X / C1) / C2  -> X / (C1*C2)
>     if (Instruction *LHS = dyn_cast<Instruction>(Op0))
>       if (Instruction::BinaryOps(LHS->getOpcode()) == I.getOpcode())
> @@ -380,20 +339,13 @@
>     }
>   }
> 
> -  // 0 / X == 0, we don't need to preserve faults!
> -  if (ConstantInt *LHS = dyn_cast<ConstantInt>(Op0))
> -    if (LHS->equalsInt(0))
> -      return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
> -
> -  // It can't be division by zero, hence it must be division by one.
> -  if (I.getType()->isIntegerTy(1))
> -    return ReplaceInstUsesWith(I, Op0);
> -
> -  if (ConstantVector *Op1V = dyn_cast<ConstantVector>(Op1)) {
> -    if (ConstantInt *X = cast_or_null<ConstantInt>(Op1V->getSplatValue()))
> -      // div X, 1 == X
> -      if (X->isOne())
> -        return ReplaceInstUsesWith(I, Op0);
> +  // (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);
>   }
> 
>   return 0;
> @@ -402,6 +354,9 @@
> Instruction *InstCombiner::visitUDiv(BinaryOperator &I) {
>   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
> 
> +  if (Value *V = SimplifyUDivInst(Op0, Op1, TD))
> +    return ReplaceInstUsesWith(I, V);
> +
>   // Handle the integer div common cases
>   if (Instruction *Common = commonIDivTransforms(I))
>     return Common;
> @@ -464,6 +419,9 @@
> Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
>   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
> 
> +  if (Value *V = SimplifySDivInst(Op0, Op1, TD))
> +    return ReplaceInstUsesWith(I, V);
> +
>   // Handle the integer div common cases
>   if (Instruction *Common = commonIDivTransforms(I))
>     return Common;
> @@ -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 function implements the transforms on rem instructions that work
> 
> Modified: llvm/trunk/test/Transforms/InstCombine/2008-11-20-DivMulRem.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2008-11-20-DivMulRem.ll?rev=124487&r1=124486&r2=124487&view=diff
> ==============================================================================
> --- llvm/trunk/test/Transforms/InstCombine/2008-11-20-DivMulRem.ll (original)
> +++ llvm/trunk/test/Transforms/InstCombine/2008-11-20-DivMulRem.ll Fri Jan 28 10:51:11 2011
> @@ -1,34 +1,67 @@
> -; RUN: opt < %s -instcombine -S > %t
> -; RUN: grep urem %t | count 3
> -; RUN: grep srem %t | count 1
> -; RUN: grep sub %t | count 2
> -; RUN: grep add %t | count 1
> +; RUN: opt < %s -instcombine -S | FileCheck %s
> ; PR3103
> 
> define i8 @test1(i8 %x, i8 %y) {
> +; CHECK: @test1
>   %A = udiv i8 %x, %y
> +; CHECK-NEXT: urem
>   %B = mul i8 %A, %y
>   %C = sub i8 %x, %B
>   ret i8 %C
> +; CHECK-NEXT: ret
> }
> 
> define i8 @test2(i8 %x, i8 %y) {
> +; CHECK: @test2
>   %A = sdiv i8 %x, %y
> +; CHECK-NEXT: srem
>   %B = mul i8 %A, %y
>   %C = sub i8 %x, %B
>   ret i8 %C
> +; CHECK-NEXT: ret
> }
> 
> define i8 @test3(i8 %x, i8 %y) {
> +; CHECK: @test3
>   %A = udiv i8 %x, %y
> +; CHECK-NEXT: urem
>   %B = mul i8 %A, %y
>   %C = sub i8 %B, %x
> +; CHECK-NEXT: sub
>   ret i8 %C
> +; CHECK-NEXT: ret
> }
> 
> define i8 @test4(i8 %x) {
> +; CHECK: @test4
>   %A = udiv i8 %x, 3
> +; CHECK-NEXT: urem
>   %B = mul i8 %A, -3
> +; CHECK-NEXT: sub
>   %C = sub i8 %x, %B
> +; CHECK-NEXT: add
>   ret i8 %C
> +; CHECK-NEXT: ret
> +}
> +
> +define i32 @test5(i32 %x, i32 %y) {
> +; CHECK: @test5
> +; (((X / Y) * Y) / Y) -> X / Y
> +  %div = sdiv i32 %x, %y
> +; CHECK-NEXT: sdiv
> +  %mul = mul i32 %div, %y
> +  %r = sdiv i32 %mul, %y
> +  ret i32 %r
> +; CHECK-NEXT: ret
> +}
> +
> +define i32 @test6(i32 %x, i32 %y) {
> +; CHECK: @test6
> +; (((X / Y) * Y) / Y) -> X / Y
> +  %div = udiv i32 %x, %y
> +; CHECK-NEXT: udiv
> +  %mul = mul i32 %div, %y
> +  %r = udiv i32 %mul, %y
> +  ret i32 %r
> +; CHECK-NEXT: ret
> }
> 
> Modified: llvm/trunk/test/Transforms/InstSimplify/2010-12-20-Reassociate.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/2010-12-20-Reassociate.ll?rev=124487&r1=124486&r2=124487&view=diff
> ==============================================================================
> --- llvm/trunk/test/Transforms/InstSimplify/2010-12-20-Reassociate.ll (original)
> +++ llvm/trunk/test/Transforms/InstSimplify/2010-12-20-Reassociate.ll Fri Jan 28 10:51:11 2011
> @@ -90,3 +90,59 @@
>   ret i32 %r
> ; CHECK: ret i32 %x
> }
> +
> +define i32 @sdiv1(i32 %x, i32 %y) {
> +; CHECK: @sdiv1
> +; (no overflow X * Y) / Y -> X
> +  %mul = mul nsw i32 %x, %y
> +  %r = sdiv i32 %mul, %y
> +  ret i32 %r
> +; CHECK: ret i32 %x
> +}
> +
> +define i32 @sdiv2(i32 %x, i32 %y) {
> +; CHECK: @sdiv2
> +; (((X / Y) * Y) / Y) -> X / Y
> +  %div = sdiv i32 %x, %y
> +  %mul = mul i32 %div, %y
> +  %r = sdiv i32 %mul, %y
> +  ret i32 %r
> +; CHECK: ret i32 %div
> +}
> +
> +define i32 @sdiv3(i32 %x, i32 %y) {
> +; CHECK: @sdiv3
> +; (X rem Y) / Y -> 0
> +  %rem = srem i32 %x, %y
> +  %div = sdiv i32 %rem, %y
> +  ret i32 %div
> +; CHECK: ret i32 0
> +}
> +
> +define i32 @udiv1(i32 %x, i32 %y) {
> +; CHECK: @udiv1
> +; (no overflow X * Y) / Y -> X
> +  %mul = mul nuw i32 %x, %y
> +  %r = udiv i32 %mul, %y
> +  ret i32 %r
> +; CHECK: ret i32 %x
> +}
> +
> +define i32 @udiv2(i32 %x, i32 %y) {
> +; CHECK: @udiv2
> +; (((X / Y) * Y) / Y) -> X / Y
> +  %div = udiv i32 %x, %y
> +  %mul = mul i32 %div, %y
> +  %r = udiv i32 %mul, %y
> +  ret i32 %r
> +; CHECK: ret i32 %div
> +}
> +
> +define i32 @udiv3(i32 %x, i32 %y) {
> +; CHECK: @udiv3
> +; (X rem Y) / Y -> 0
> +  %rem = urem i32 %x, %y
> +  %div = udiv i32 %rem, %y
> +  ret i32 %div
> +; CHECK: ret i32 0
> +}
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits





More information about the llvm-commits mailing list