From 50af16a97b3983c224a48ae4369d7e9facf8174e Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 13 Nov 2004 19:50:12 +0000 Subject: [PATCH] Simplify handling of shifts to be the same as we do for adds. Add support for (X * C1) + (X * C2) (where * can be mul or shl), allowing us to fold: Y+Y+Y+Y+Y+Y+Y+Y into %tmp.8 = shl long %Y, ubyte 3 ; [#uses=1] instead of %tmp.4 = shl long %Y, ubyte 2 ; [#uses=1] %tmp.12 = shl long %Y, ubyte 2 ; [#uses=1] %tmp.8 = add long %tmp.4, %tmp.12 ; [#uses=1] This implements add.ll:test25 Also add support for (X*C1)-(X*C2) -> X*(C1-C2), implementing sub.ll:test18 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@17704 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/InstructionCombining.cpp | 85 +++++++++---------- 1 file changed, 40 insertions(+), 45 deletions(-) diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 3f746a59ee3..5af9aee165d 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -317,14 +317,23 @@ static inline Value *dyn_castNotVal(Value *V) { // dyn_castFoldableMul - If this value is a multiply that can be folded into // other computations (because it has a constant operand), return the -// non-constant operand of the multiply. +// non-constant operand of the multiply, and set CST to point to the multiplier. +// Otherwise, return null. // -static inline Value *dyn_castFoldableMul(Value *V) { +static inline Value *dyn_castFoldableMul(Value *V, ConstantInt *&CST) { if (V->hasOneUse() && V->getType()->isInteger()) - if (Instruction *I = dyn_cast(V)) + if (Instruction *I = dyn_cast(V)) { if (I->getOpcode() == Instruction::Mul) - if (isa(I->getOperand(1))) + if (CST = dyn_cast(I->getOperand(1))) return I->getOperand(0); + if (I->getOpcode() == Instruction::Shl) + if (CST = dyn_cast(I->getOperand(1))) { + // The multiplier is really 1 << CST. + Constant *One = ConstantInt::get(V->getType(), 1); + CST = cast(ConstantExpr::getShl(One, CST)); + return I->getOperand(0); + } + } return 0; } @@ -595,42 +604,26 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { if (Value *V = dyn_castNegVal(RHS)) return BinaryOperator::createSub(LHS, V); - // X*C + X --> X * (C+1) - if (dyn_castFoldableMul(LHS) == RHS) { - Constant *CP1 = - ConstantExpr::getAdd( - cast(cast(LHS)->getOperand(1)), - ConstantInt::get(I.getType(), 1)); - return BinaryOperator::createMul(RHS, CP1); + ConstantInt *C2; + if (Value *X = dyn_castFoldableMul(LHS, C2)) { + if (X == RHS) // X*C + X --> X * (C+1) + return BinaryOperator::createMul(RHS, AddOne(C2)); + + // X*C1 + X*C2 --> X * (C1+C2) + ConstantInt *C1; + if (X == dyn_castFoldableMul(RHS, C1)) + return BinaryOperator::createMul(X, ConstantExpr::getAdd(C1, C2)); } // X + X*C --> X * (C+1) - if (dyn_castFoldableMul(RHS) == LHS) { - Constant *CP1 = - ConstantExpr::getAdd( - cast(cast(RHS)->getOperand(1)), - ConstantInt::get(I.getType(), 1)); - return BinaryOperator::createMul(LHS, CP1); - } + if (dyn_castFoldableMul(RHS, C2) == LHS) + return BinaryOperator::createMul(LHS, AddOne(C2)); + // (A & C1)+(B & C2) --> (A & C1)|(B & C2) iff C1&C2 == 0 - ConstantInt *C2; if (match(RHS, m_And(m_Value(), m_ConstantInt(C2)))) if (Instruction *R = AssociativeOpt(I, AddMaskingAnd(C2))) return R; - // (X + (X << C2)) --> X * ((1 << C2) + 1) - // ((X << C2) + X) --> X * ((1 << C2) + 1) - Value *Tmp; - if ((RHS->hasOneUse() && match(RHS, m_Shl(m_Value(Tmp), - m_ConstantInt(C2))) && LHS == Tmp)|| - (LHS->hasOneUse() && match(LHS, m_Shl(m_Value(Tmp), - m_ConstantInt(C2))) && RHS == Tmp)){ - ConstantInt *One = ConstantInt::get(LHS->getType(), 1); - Constant *NewRHS = - ConstantExpr::getAdd(ConstantExpr::getShl(One, C2), One); - return BinaryOperator::createMul(Tmp, NewRHS); - } - if (ConstantInt *CRHS = dyn_cast(RHS)) { Value *X; if (match(LHS, m_Not(m_Value(X)))) { // ~X + C --> (C-1) - X @@ -800,24 +793,26 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { ConstantExpr::getNeg(DivRHS)); // X - X*C --> X * (1-C) - if (dyn_castFoldableMul(Op1I) == Op0) { - Constant *CP1 = - ConstantExpr::getSub(ConstantInt::get(I.getType(), 1), - cast(cast(Op1)->getOperand(1))); - assert(CP1 && "Couldn't constant fold 1-C?"); + ConstantInt *C2; + if (dyn_castFoldableMul(Op1I, C2) == Op0) { + Constant *CP1 = + ConstantExpr::getSub(ConstantInt::get(I.getType(), 1), C2); return BinaryOperator::createMul(Op0, CP1); } } - // X*C - X --> X * (C-1) - if (dyn_castFoldableMul(Op0) == Op1) { - Constant *CP1 = - ConstantExpr::getSub(cast(cast(Op0)->getOperand(1)), - ConstantInt::get(I.getType(), 1)); - assert(CP1 && "Couldn't constant fold C - 1?"); - return BinaryOperator::createMul(Op1, CP1); - } + + ConstantInt *C1; + if (Value *X = dyn_castFoldableMul(Op0, C1)) { + if (X == Op1) { // X*C - X --> X * (C-1) + Constant *CP1 = ConstantExpr::getSub(C1, ConstantInt::get(I.getType(),1)); + return BinaryOperator::createMul(Op1, CP1); + } + ConstantInt *C2; // X*C1 - X*C2 -> X * (C1-C2) + if (X == dyn_castFoldableMul(Op1, C2)) + return BinaryOperator::createMul(Op1, ConstantExpr::getSub(C1, C2)); + } return 0; }