Index: lib/Transforms/Scalar/Reassociate.cpp =================================================================== --- lib/Transforms/Scalar/Reassociate.cpp +++ lib/Transforms/Scalar/Reassociate.cpp @@ -355,6 +355,32 @@ } } +/// If this is a shift of a reassociable multiply or is used by one, change +/// this into a multiply by a constant to assist with further reassociation. +static BinaryOperator *ConvertShiftToMul(Instruction *Shl) { + Constant *MulCst = ConstantInt::get(Shl->getType(), 1); + MulCst = ConstantExpr::getShl(MulCst, cast(Shl->getOperand(1))); + + BinaryOperator *Mul = + BinaryOperator::CreateMul(Shl->getOperand(0), MulCst, "", Shl); + Shl->setOperand(0, UndefValue::get(Shl->getType())); // Drop use of op. + Mul->takeName(Shl); + + // Everyone now refers to the mul instruction. + Shl->replaceAllUsesWith(Mul); + Mul->setDebugLoc(Shl->getDebugLoc()); + + // We can safely preserve the nuw flag in all cases. It's also safe to turn a + // nuw nsw shl into a nuw nsw mul. However, nsw in isolation requires special + // handling. + bool NSW = cast(Shl)->hasNoSignedWrap(); + bool NUW = cast(Shl)->hasNoUnsignedWrap(); + if (NSW && NUW) + Mul->setHasNoSignedWrap(true); + Mul->setHasNoUnsignedWrap(NUW); + return Mul; +} + typedef std::pair RepeatedValue; /// Given an associative binary expression, return the leaf @@ -556,9 +582,9 @@ "Should have been handled above!"); assert(Op->hasOneUse() && "Has uses outside the expression tree!"); - // If this is a multiply expression, turn any internal negations into - // multiplies by -1 so they can be reassociated. - if (BinaryOperator *BO = dyn_cast(Op)) + if (BinaryOperator *BO = dyn_cast(Op)) { + // If this is a multiply expression, turn any internal negations into + // multiplies by -1 so they can be reassociated. if ((Opcode == Instruction::Mul && BinaryOperator::isNeg(BO)) || (Opcode == Instruction::FMul && BinaryOperator::isFNeg(BO))) { DEBUG(dbgs() << "MORPH LEAF: " << *Op << " (" << Weight << ") TO "); @@ -568,7 +594,18 @@ Changed = true; continue; } - + // If this is a multiply expression, convert any left shift by a + // constant into a multiply so they can be reassociated. + if (Opcode == Instruction::Mul && BO->getOpcode() == Instruction::Shl && + isa(BO->getOperand(1))) { + DEBUG(dbgs() << "MORPH LEAF: " << *Op << " (" << Weight << ") TO "); + BO = ConvertShiftToMul(BO); + DEBUG(dbgs() << *BO << '\n'); + Worklist.push_back(std::make_pair(BO, Weight)); + Changed = true; + continue; + } + } // Failed to morph into an expression of the right type. This really is // a leaf. DEBUG(dbgs() << "ADD LEAF: " << *Op << " (" << Weight << ")\n"); @@ -926,32 +963,6 @@ return New; } -/// If this is a shift of a reassociable multiply or is used by one, change -/// this into a multiply by a constant to assist with further reassociation. -static BinaryOperator *ConvertShiftToMul(Instruction *Shl) { - Constant *MulCst = ConstantInt::get(Shl->getType(), 1); - MulCst = ConstantExpr::getShl(MulCst, cast(Shl->getOperand(1))); - - BinaryOperator *Mul = - BinaryOperator::CreateMul(Shl->getOperand(0), MulCst, "", Shl); - Shl->setOperand(0, UndefValue::get(Shl->getType())); // Drop use of op. - Mul->takeName(Shl); - - // Everyone now refers to the mul instruction. - Shl->replaceAllUsesWith(Mul); - Mul->setDebugLoc(Shl->getDebugLoc()); - - // We can safely preserve the nuw flag in all cases. It's also safe to turn a - // nuw nsw shl into a nuw nsw mul. However, nsw in isolation requires special - // handling. - bool NSW = cast(Shl)->hasNoSignedWrap(); - bool NUW = cast(Shl)->hasNoUnsignedWrap(); - if (NSW && NUW) - Mul->setHasNoSignedWrap(true); - Mul->setHasNoUnsignedWrap(NUW); - return Mul; -} - /// Scan backwards and forwards among values with the same rank as element i /// to see if X exists. If X does not exist, return i. This is useful when /// scanning for 'x' when we see '-x' because they both get the same rank. Index: test/Transforms/Reassociate/basictest.ll =================================================================== --- test/Transforms/Reassociate/basictest.ll +++ test/Transforms/Reassociate/basictest.ll @@ -222,3 +222,19 @@ ; CHECK-LABEL: @test15 ; CHECK: and i1 %A, %B } + + +; -(a << 1)*2 + b --> -4a + b +define i32 @test16(i1 %cmp, i32 %a, i32 %b) { +entry: + %shl = shl i32 %a, 1 + %shl.neg = sub i32 0, %shl + %add1 = mul i32 %shl.neg, 2 + %add2 = add i32 %add1, %b + ret i32 %add2 + +; CHECK-LABEL: @test16 +; CHECK: %[[MUL:.*]] = mul i32 %a, -4 +; CHECK: %[[ADD:.*]] = add i64 %[[MUL]], %b +; CHECK: ret i32 %[[ADD]] +}