summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2014-11-22 07:25:19 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2014-11-22 07:25:19 +0000
commit082eff658ef184d7ec9b7c932680e64b192bb58b (patch)
tree6fa2628a62fda1618d82c2dcf58b8bf71f0e80fd
parent7eca618dfc363f98085cef732b61c7c48c519582 (diff)
InstCombine: Propagate NSW for -X * -Y -> X * Y
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222612 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/InstCombine/InstCombineMulDivRem.cpp13
-rw-r--r--test/Transforms/InstCombine/mul.ll9
2 files changed, 19 insertions, 3 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 5ea25bf5c9d..78f585f6f73 100644
--- a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -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
diff --git a/test/Transforms/InstCombine/mul.ll b/test/Transforms/InstCombine/mul.ll
index 469ca5a0b95..a782cfd78d5 100644
--- a/test/Transforms/InstCombine/mul.ll
+++ b/test/Transforms/InstCombine/mul.ll
@@ -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
+}