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

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

index 5ea25bf5c9dbb18692ccd2e88203bd626ee314ba..78f585f6f73117cee2a0ef51660a884cd1953119 100644 (file)
@@ -237,9 +237,16 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
     }
   }
 
-  if (Value *Op0v = dyn_castNegVal(Op0))     // -X * -Y = X*Y
-    if (Value *Op1v = dyn_castNegVal(Op1))
-      return BinaryOperator::CreateMul(Op0v, Op1v);
+  if (Value *Op0v = dyn_castNegVal(Op0)) {   // -X * -Y = X*Y
+    if (Value *Op1v = dyn_castNegVal(Op1)) {
+      BinaryOperator *BO = BinaryOperator::CreateMul(Op0v, Op1v);
+      if (I.hasNoSignedWrap() &&
+          match(Op0, m_NSWSub(m_Value(), m_Value())) &&
+          match(Op1, m_NSWSub(m_Value(), m_Value())))
+        BO->setHasNoSignedWrap();
+      return BO;
+    }
+  }
 
   // (X / Y) *  Y = X - (X % Y)
   // (X / Y) * -Y = (X % Y) - X
index 469ca5a0b95cc99b3b46158b97ecf9bf951aa0dc..a782cfd78d5e97b35250f8dc2df3519b6a2a62fd 100644 (file)
@@ -220,3 +220,12 @@ define i32 @test24(i32 %A) {
         ret i32 %C
 ; CHECK: mul nsw i32 %A, 6
 }
+
+define i32 @test25(i32 %A, i32 %B) {
+; CHECK-LABEL: @test25(
+        %C = sub nsw i32 0, %A
+        %D = sub nsw i32 0, %B
+        %E = mul nsw i32 %C, %D
+        ret i32 %E
+; CHECK: mul nsw i32 %A, %B
+}