[llvm-commits] [llvm] r122399 - in /llvm/trunk: lib/Transforms/InstCombine/InstCombine.h lib/Transforms/InstCombine/InstCombineAddSub.cpp lib/Transforms/InstCombine/InstCombineAndOrXor.cpp lib/Transforms/InstCombine/InstCombineMulDivRem.cpp lib/Transforms/InstCombine/InstructionCombining.cpp test/Transforms/InstCombine/2010-11-23-Distributed.ll
Chris Lattner
clattner at apple.com
Sat Dec 25 12:48:44 PST 2010
On Dec 22, 2010, at 5:36 AM, Duncan Sands wrote:
> Author: baldrick
> Date: Wed Dec 22 07:36:08 2010
> New Revision: 122399
>
> URL: http://llvm.org/viewvc/llvm-project?rev=122399&view=rev
> Log:
> Add a generic expansion transform: A op (B op' C) -> (A op B) op' (A op C)
> if both A op B and A op C simplify. This fires fairly often but doesn't
> make that much difference. On gcc-as-one-file it removes two "and"s and
> turns one branch into a select.
Hi Duncan,
I'm a bit concerned about the compile time cost of this. If this isn't kicking in much, is it really worth it? Have you looked to see if this causes a compile time hit?
-Chris
>
> Modified:
> llvm/trunk/lib/Transforms/InstCombine/InstCombine.h
> llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp
> llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
> llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
> llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
> llvm/trunk/test/Transforms/InstCombine/2010-11-23-Distributed.ll
>
> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombine.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombine.h?rev=122399&r1=122398&r2=122399&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/InstCombine/InstCombine.h (original)
> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombine.h Wed Dec 22 07:36:08 2010
> @@ -290,11 +290,12 @@
> /// operators which are associative or commutative.
> bool SimplifyAssociativeOrCommutative(BinaryOperator &I);
>
> - /// SimplifyByFactorizing - This tries to simplify binary operations which
> - /// some other binary operation distributes over by factorizing out a common
> - /// term (eg "(A*B)+(A*C)" -> "A*(B+C)"). Returns the simplified value, or
> - /// null if no simplification was performed.
> - Instruction *SimplifyByFactorizing(BinaryOperator &I);
> + /// SimplifyUsingDistributiveLaws - This tries to simplify binary operations
> + /// which some other binary operation distributes over either by factorizing
> + /// out common terms (eg "(A*B)+(A*C)" -> "A*(B+C)") or expanding out if this
> + /// results in simplifications (eg: "A & (B | C) -> (A&B) | (A&C)" if this is
> + /// a win). Returns the simplified value, or null if it didn't simplify.
> + Value *SimplifyUsingDistributiveLaws(BinaryOperator &I);
>
> /// SimplifyDemandedUseBits - Attempts to replace V with a simpler value
> /// based on the demanded bits.
>
> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp?rev=122399&r1=122398&r2=122399&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp (original)
> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp Wed Dec 22 07:36:08 2010
> @@ -91,9 +91,10 @@
> I.hasNoUnsignedWrap(), TD))
> return ReplaceInstUsesWith(I, V);
>
> - if (Instruction *NV = SimplifyByFactorizing(I)) // (A*B)+(A*C) -> A*(B+C)
> - return NV;
> -
> + // (A*B)+(A*C) -> A*(B+C) etc
> + if (Value *V = SimplifyUsingDistributiveLaws(I))
> + return ReplaceInstUsesWith(I, V);
> +
> if (Constant *RHSC = dyn_cast<Constant>(RHS)) {
> if (ConstantInt *CI = dyn_cast<ConstantInt>(RHSC)) {
> // X + (signbit) --> X ^ signbit
> @@ -535,9 +536,10 @@
> I.hasNoUnsignedWrap(), TD))
> return ReplaceInstUsesWith(I, V);
>
> - if (Instruction *NV = SimplifyByFactorizing(I)) // (A*B)-(A*C) -> A*(B-C)
> - return NV;
> -
> + // (A*B)-(A*C) -> A*(B-C) etc
> + if (Value *V = SimplifyUsingDistributiveLaws(I))
> + return ReplaceInstUsesWith(I, V);
> +
> // If this is a 'B = x-(-A)', change to B = x+A. This preserves NSW/NUW.
> if (Value *V = dyn_castNegVal(Op1)) {
> BinaryOperator *Res = BinaryOperator::CreateAdd(Op0, V);
>
> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp?rev=122399&r1=122398&r2=122399&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (original)
> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp Wed Dec 22 07:36:08 2010
> @@ -984,8 +984,9 @@
> if (Value *V = SimplifyAndInst(Op0, Op1, TD))
> return ReplaceInstUsesWith(I, V);
>
> - if (Instruction *NV = SimplifyByFactorizing(I)) // (A|B)&(A|C) -> A|(B&C)
> - return NV;
> + // (A|B)&(A|C) -> A|(B&C) etc
> + if (Value *V = SimplifyUsingDistributiveLaws(I))
> + return ReplaceInstUsesWith(I, V);
>
> // See if we can simplify any instructions used by the instruction whose sole
> // purpose is to compute bits we don't care about.
> @@ -1702,8 +1703,9 @@
> if (Value *V = SimplifyOrInst(Op0, Op1, TD))
> return ReplaceInstUsesWith(I, V);
>
> - if (Instruction *NV = SimplifyByFactorizing(I)) // (A&B)|(A&C) -> A&(B|C)
> - return NV;
> + // (A&B)|(A&C) -> A&(B|C) etc
> + if (Value *V = SimplifyUsingDistributiveLaws(I))
> + return ReplaceInstUsesWith(I, V);
>
> // See if we can simplify any instructions used by the instruction whose sole
> // purpose is to compute bits we don't care about.
> @@ -1973,8 +1975,9 @@
> if (Value *V = SimplifyXorInst(Op0, Op1, TD))
> return ReplaceInstUsesWith(I, V);
>
> - if (Instruction *NV = SimplifyByFactorizing(I)) // (A&B)^(A&C) -> A&(B^C)
> - return NV;
> + // (A&B)^(A&C) -> A&(B^C) etc
> + if (Value *V = SimplifyUsingDistributiveLaws(I))
> + return ReplaceInstUsesWith(I, V);
>
> // See if we can simplify any instructions used by the instruction whose sole
> // purpose is to compute bits we don't care about.
>
> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp?rev=122399&r1=122398&r2=122399&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (original)
> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp Wed Dec 22 07:36:08 2010
> @@ -54,6 +54,9 @@
> if (Value *V = SimplifyMulInst(Op0, Op1, TD))
> return ReplaceInstUsesWith(I, V);
>
> + if (Value *V = SimplifyUsingDistributiveLaws(I))
> + return ReplaceInstUsesWith(I, V);
> +
> // Simplify mul instructions with a constant RHS.
> if (Constant *Op1C = dyn_cast<Constant>(Op1)) {
> if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1C)) {
>
> Modified: llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp?rev=122399&r1=122398&r2=122399&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp (original)
> +++ llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp Wed Dec 22 07:36:08 2010
> @@ -58,6 +58,7 @@
> STATISTIC(NumConstProp, "Number of constant folds");
> STATISTIC(NumDeadInst , "Number of dead inst eliminated");
> STATISTIC(NumSunkInst , "Number of instructions sunk");
> +STATISTIC(NumExpand, "Number of expansions");
> STATISTIC(NumFactor , "Number of factorizations");
> STATISTIC(NumReassoc , "Number of reassociations");
>
> @@ -294,64 +295,123 @@
> return false;
> }
>
> -/// SimplifyByFactorizing - This tries to simplify binary operations which
> -/// some other binary operation distributes over by factorizing out a common
> -/// term (eg "(A*B)+(A*C)" -> "A*(B+C)"). Returns the simplified value, or
> -/// null if no simplification was performed.
> -Instruction *InstCombiner::SimplifyByFactorizing(BinaryOperator &I) {
> - BinaryOperator *Op0 = dyn_cast<BinaryOperator>(I.getOperand(0));
> - BinaryOperator *Op1 = dyn_cast<BinaryOperator>(I.getOperand(1));
> - if (!Op0 || !Op1 || Op0->getOpcode() != Op1->getOpcode())
> - return 0;
> +/// SimplifyUsingDistributiveLaws - This tries to simplify binary operations
> +/// which some other binary operation distributes over either by factorizing
> +/// out common terms (eg "(A*B)+(A*C)" -> "A*(B+C)") or expanding out if this
> +/// results in simplifications (eg: "A & (B | C) -> (A&B) | (A&C)" if this is
> +/// a win). Returns the simplified value, or null if it didn't simplify.
> +Value *InstCombiner::SimplifyUsingDistributiveLaws(BinaryOperator &I) {
> + Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
> + BinaryOperator *Op0 = dyn_cast<BinaryOperator>(LHS);
> + BinaryOperator *Op1 = dyn_cast<BinaryOperator>(RHS);
> + Instruction::BinaryOps TopLevelOpcode = I.getOpcode(); // op
> +
> + // Factorization.
> + if (Op0 && Op1 && Op0->getOpcode() == Op1->getOpcode()) {
> + // The instruction has the form "(A op' B) op (C op' D)". Try to factorize
> + // a common term.
> + Value *A = Op0->getOperand(0), *B = Op0->getOperand(1);
> + Value *C = Op1->getOperand(0), *D = Op1->getOperand(1);
> + Instruction::BinaryOps InnerOpcode = Op0->getOpcode(); // op'
> +
> + // Does "X op' Y" always equal "Y op' X"?
> + bool InnerCommutative = Instruction::isCommutative(InnerOpcode);
> +
> + // Does "X op' (Y op Z)" always equal "(X op' Y) op (X op' Z)"?
> + if (LeftDistributesOverRight(InnerOpcode, TopLevelOpcode))
> + // Does the instruction have the form "(A op' B) op (A op' D)" or, in the
> + // commutative case, "(A op' B) op (C op' A)"?
> + if (A == C || (InnerCommutative && A == D)) {
> + if (A != C)
> + 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, TD);
> + // 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 && Op0->hasOneUse() && Op1->hasOneUse())
> + V = Builder->CreateBinOp(TopLevelOpcode, B, D, Op1->getName());
> + if (V) {
> + ++NumFactor;
> + V = Builder->CreateBinOp(InnerOpcode, A, V);
> + V->takeName(&I);
> + return V;
> + }
> + }
>
> - // The instruction has the form "(A op' B) op (C op' D)".
> - Value *A = Op0->getOperand(0); Value *B = Op0->getOperand(1);
> - Value *C = Op1->getOperand(0); Value *D = Op1->getOperand(1);
> - Instruction::BinaryOps OuterOpcode = I.getOpcode(); // op
> - Instruction::BinaryOps InnerOpcode = Op0->getOpcode(); // op'
> -
> - // Does "X op' Y" always equal "Y op' X"?
> - bool InnerCommutative = Instruction::isCommutative(InnerOpcode);
> -
> - // Does "X op' (Y op Z)" always equal "(X op' Y) op (X op' Z)"?
> - if (LeftDistributesOverRight(InnerOpcode, OuterOpcode))
> - // Does the instruction have the form "(A op' B) op (A op' D)" or, in the
> - // commutative case, "(A op' B) op (C op' A)"?
> - if (A == C || (InnerCommutative && A == D)) {
> - if (A != C)
> - 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 *RHS = SimplifyBinOp(OuterOpcode, B, D, TD);
> - // If "B op D" doesn't simplify then only proceed if both of the existing
> - // operations "A op' B" and "C op' D" will be zapped since no longer used.
> - if (!RHS && Op0->hasOneUse() && Op1->hasOneUse())
> - RHS = Builder->CreateBinOp(OuterOpcode, B, D, Op1->getName());
> - if (RHS) {
> - ++NumFactor;
> - return BinaryOperator::Create(InnerOpcode, A, RHS);
> + // Does "(X op Y) op' Z" always equal "(X op' Z) op (Y op' Z)"?
> + if (RightDistributesOverLeft(TopLevelOpcode, InnerOpcode))
> + // Does the instruction have the form "(A op' B) op (C op' B)" or, in the
> + // commutative case, "(A op' B) op (B op' D)"?
> + if (B == D || (InnerCommutative && B == C)) {
> + if (B != D)
> + 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, TD);
> + // 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.
> + if (!V && Op0->hasOneUse() && Op1->hasOneUse())
> + V = Builder->CreateBinOp(TopLevelOpcode, A, C, Op0->getName());
> + if (V) {
> + ++NumFactor;
> + V = Builder->CreateBinOp(InnerOpcode, V, B);
> + V->takeName(&I);
> + return V;
> + }
> }
> - }
> + }
>
> - // Does "(X op Y) op' Z" always equal "(X op' Z) op (Y op' Z)"?
> - if (RightDistributesOverLeft(OuterOpcode, InnerOpcode))
> - // Does the instruction have the form "(A op' B) op (C op' B)" or, in the
> - // commutative case, "(A op' B) op (B op' D)"?
> - if (B == D || (InnerCommutative && B == C)) {
> - if (B != D)
> - 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 *LHS = SimplifyBinOp(OuterOpcode, A, C, TD);
> - // If "A op C" doesn't simplify then only proceed if both of the existing
> - // operations "A op' B" and "C op' D" will be zapped since no longer used.
> - if (!LHS && Op0->hasOneUse() && Op1->hasOneUse())
> - LHS = Builder->CreateBinOp(OuterOpcode, A, C, Op0->getName());
> - if (LHS) {
> - ++NumFactor;
> - return BinaryOperator::Create(InnerOpcode, LHS, B);
> + // Expansion.
> + if (Op0 && RightDistributesOverLeft(Op0->getOpcode(), TopLevelOpcode)) {
> + // The instruction has the form "(A op' B) op C". See if expanding it out
> + // to "(A op C) op' (B op C)" results in simplifications.
> + Value *A = Op0->getOperand(0), *B = Op0->getOperand(1), *C = RHS;
> + Instruction::BinaryOps InnerOpcode = Op0->getOpcode(); // op'
> +
> + // Do "A op C" and "B op C" both simplify?
> + if (Value *L = SimplifyBinOp(TopLevelOpcode, A, C, TD))
> + if (Value *R = SimplifyBinOp(TopLevelOpcode, B, C, TD)) {
> + // They do! Return "L op' R".
> + ++NumExpand;
> + // If "L op' R" equals "A op' B" then "L op' R" is just the LHS.
> + if ((L == A && R == B) ||
> + (Instruction::isCommutative(InnerOpcode) && L == B && R == A))
> + return Op0;
> + // Otherwise return "L op' R" if it simplifies.
> + if (Value *V = SimplifyBinOp(InnerOpcode, L, R, TD))
> + return V;
> + // Otherwise, create a new instruction.
> + C = Builder->CreateBinOp(InnerOpcode, L, R);
> + C->takeName(&I);
> + return C;
> }
> - }
> + }
> +
> + if (Op1 && LeftDistributesOverRight(TopLevelOpcode, Op1->getOpcode())) {
> + // The instruction has the form "A op (B op' C)". See if expanding it out
> + // to "(A op B) op' (A op C)" results in simplifications.
> + Value *A = LHS, *B = Op1->getOperand(0), *C = Op1->getOperand(1);
> + Instruction::BinaryOps InnerOpcode = Op1->getOpcode(); // op'
> +
> + // Do "A op B" and "A op C" both simplify?
> + if (Value *L = SimplifyBinOp(TopLevelOpcode, A, B, TD))
> + if (Value *R = SimplifyBinOp(TopLevelOpcode, A, C, TD)) {
> + // They do! Return "L op' R".
> + ++NumExpand;
> + // If "L op' R" equals "B op' C" then "L op' R" is just the RHS.
> + if ((L == B && R == C) ||
> + (Instruction::isCommutative(InnerOpcode) && L == C && R == B))
> + return Op1;
> + // Otherwise return "L op' R" if it simplifies.
> + if (Value *V = SimplifyBinOp(InnerOpcode, L, R, TD))
> + return V;
> + // Otherwise, create a new instruction.
> + A = Builder->CreateBinOp(InnerOpcode, L, R);
> + A->takeName(&I);
> + return A;
> + }
> + }
>
> return 0;
> }
>
> Modified: llvm/trunk/test/Transforms/InstCombine/2010-11-23-Distributed.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2010-11-23-Distributed.ll?rev=122399&r1=122398&r2=122399&view=diff
> ==============================================================================
> --- llvm/trunk/test/Transforms/InstCombine/2010-11-23-Distributed.ll (original)
> +++ llvm/trunk/test/Transforms/InstCombine/2010-11-23-Distributed.ll Wed Dec 22 07:36:08 2010
> @@ -5,7 +5,19 @@
> %mul = mul nsw i32 %add, %y
> %square = mul nsw i32 %y, %y
> %res = sub i32 %mul, %square
> -; CHECK: %res = mul i32 %x, %y
> ret i32 %res
> -; CHECK: ret i32 %res
> +; CHECK-NEXT: mul i32 %x, %y
> +; CHECK-NEXT: ret i32
> +}
> +
> +define i1 @bar(i64 %x, i64 %y) {
> +; CHECK: @bar
> + %a = and i64 %y, %x
> +; CHECK: and
> +; CHECK-NOT: and
> + %not = xor i64 %a, -1
> + %b = and i64 %y, %not
> + %r = icmp eq i64 %b, 0
> + ret i1 %r
> +; CHECK: ret i1
> }
>
>
> _______________________________________________
> 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