[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
Duncan Sands
baldrick at free.fr
Sun Jan 30 10:20:39 PST 2011
Hi Evan,
> This broke 254.gap (Darwin, clang, i386 and x86_64). Please investigate or at least consider backing it out for now.
this may be related to PR9088. I will speculatively disable this part of the
transform.
Ciao, Duncan.
>
> 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