InstCombine: Propagate NSW/NUW for X*(1<<Y) -> X<<Y
authorDavid Majnemer <david.majnemer@gmail.com>
Sat, 22 Nov 2014 08:57:02 +0000 (08:57 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Sat, 22 Nov 2014 08:57:02 +0000 (08:57 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222613 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
test/Transforms/InstCombine/mul.ll

index 78f585f6f73117cee2a0ef51660a884cd1953119..010625a715716e7debf88df3245ab98db442315e 100644 (file)
@@ -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
index a782cfd78d5e97b35250f8dc2df3519b6a2a62fd..934448290e01f017d2b004ed2a08d1dc1d1d7eaf 100644 (file)
@@ -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
+}