diff options
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 21 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/mul.ll | 16 |
2 files changed, 33 insertions, 4 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 78f585f6f73..010625a7157 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -295,10 +295,23 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) { // (1 << Y)*X --> X << Y { Value *Y; - if (match(Op0, m_Shl(m_One(), m_Value(Y)))) - return BinaryOperator::CreateShl(Op1, Y); - if (match(Op1, m_Shl(m_One(), m_Value(Y)))) - return BinaryOperator::CreateShl(Op0, Y); + BinaryOperator *BO = nullptr; + bool ShlNSW = false; + if (match(Op0, m_Shl(m_One(), m_Value(Y)))) { + BO = BinaryOperator::CreateShl(Op1, Y); + ShlNSW = cast<BinaryOperator>(Op0)->hasNoSignedWrap(); + } + if (match(Op1, m_Shl(m_One(), m_Value(Y)))) { + BO = BinaryOperator::CreateShl(Op0, Y); + ShlNSW = cast<BinaryOperator>(Op1)->hasNoSignedWrap(); + } + if (BO) { + if (I.hasNoUnsignedWrap()) + BO->setHasNoUnsignedWrap(); + if (I.hasNoSignedWrap() && ShlNSW) + BO->setHasNoSignedWrap(); + return BO; + } } // If one of the operands of the multiply is a cast from a boolean value, then diff --git a/llvm/test/Transforms/InstCombine/mul.ll b/llvm/test/Transforms/InstCombine/mul.ll index a782cfd78d5..934448290e0 100644 --- a/llvm/test/Transforms/InstCombine/mul.ll +++ b/llvm/test/Transforms/InstCombine/mul.ll @@ -229,3 +229,19 @@ define i32 @test25(i32 %A, i32 %B) { ret i32 %E ; CHECK: mul nsw i32 %A, %B } + +define i32 @test26(i32 %A, i32 %B) { +; CHECK-LABEL: @test26( + %C = shl nsw i32 1, %B + %D = mul nsw i32 %A, %C + ret i32 %D +; CHECK: shl nsw i32 %A, %B +} + +define i32 @test27(i32 %A, i32 %B) { +; CHECK-LABEL: @test27( + %C = shl i32 1, %B + %D = mul nuw i32 %A, %C + ret i32 %D +; CHECK: shl nuw i32 %A, %B +} |

