InstCombine: Preserve nsw/nuw for ((X << C2)*C1) -> (X * (C1 << C2))
authorDavid Majnemer <david.majnemer@gmail.com>
Sat, 22 Nov 2014 04:52:52 +0000 (04:52 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Sat, 22 Nov 2014 04:52:52 +0000 (04:52 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222605 91177308-0d34-0410-b5e6-96231b3b80d8

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

index c96c2d62255c5a0ac3a7c79fc67efbffcb543cde..7844223746997d6f97cfce59d7d8cb32e423ecfa 100644 (file)
@@ -151,9 +151,18 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
     const APInt *IVal;
     if (match(&I, m_Mul(m_Shl(m_Value(NewOp), m_Constant(C2)),
                         m_Constant(C1))) &&
-        match(C1, m_APInt(IVal)))
-      // ((X << C1)*C2) == (X * (C2 << C1))
-      return BinaryOperator::CreateMul(NewOp, ConstantExpr::getShl(C1, C2));
+        match(C1, m_APInt(IVal))) {
+      // ((X << C2)*C1) == (X * (C1 << C2))
+      Constant *Shl = ConstantExpr::getShl(C1, C2);
+      BinaryOperator *Mul = cast<BinaryOperator>(I.getOperand(0));
+      BinaryOperator *BO = BinaryOperator::CreateMul(NewOp, Shl);
+      if (I.hasNoUnsignedWrap() && Mul->hasNoUnsignedWrap())
+        BO->setHasNoUnsignedWrap();
+      if (I.hasNoSignedWrap() && Mul->hasNoSignedWrap() &&
+          Shl->isNotMinSignedValue())
+        BO->setHasNoSignedWrap();
+      return BO;
+    }
 
     if (match(&I, m_Mul(m_Value(NewOp), m_Constant(C1)))) {
       Constant *NewCst = nullptr;
index 905c33b501f4ffae5aebac9d97ba95fede936d54..469ca5a0b95cc99b3b46158b97ecf9bf951aa0dc 100644 (file)
@@ -204,3 +204,19 @@ define i32 @test22(i32 %A) {
         ret i32 %B
 ; CHECK: sub nsw i32 0, %A
 }
+
+define i32 @test23(i32 %A) {
+; CHECK-LABEL: @test23(
+        %B = shl nuw i32 %A, 1
+        %C = mul nuw i32 %B, 3
+        ret i32 %C
+; CHECK: mul nuw i32 %A, 6
+}
+
+define i32 @test24(i32 %A) {
+; CHECK-LABEL: @test24(
+        %B = shl nsw i32 %A, 1
+        %C = mul nsw i32 %B, 3
+        ret i32 %C
+; CHECK: mul nsw i32 %A, 6
+}