summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2014-10-11 10:20:01 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2014-10-11 10:20:01 +0000
commitcb9d59665531cb2a894ac8af7e7cf476fba40600 (patch)
treeab0f8a8ced3fe61c01f5cbd807dabda731b62411
parent3cac85e07120f0cfcbc8e78a975f68ae99fcebbb (diff)
downloadbcm5719-llvm-cb9d59665531cb2a894ac8af7e7cf476fba40600.tar.gz
bcm5719-llvm-cb9d59665531cb2a894ac8af7e7cf476fba40600.zip
InstCombine, InstSimplify: (%X /s C1) /s C2 isn't always 0 when C1 * C2 overflow
consider: C1 = INT_MIN C2 = -1 C1 * C2 overflows without a doubt but consider the following: %x = i32 INT_MIN This means that (%X /s C1) is 1 and (%X /s C1) /s C2 is -1. N. B. Move the unsigned version of this transform to InstSimplify, it doesn't create any new instructions. This fixes PR21243. llvm-svn: 219567
-rw-r--r--llvm/lib/Analysis/InstructionSimplify.cpp10
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp9
-rw-r--r--llvm/test/Transforms/InstCombine/2008-02-16-SDivOverflow.ll14
-rw-r--r--llvm/test/Transforms/InstSimplify/exact-nsw-nuw.ll16
4 files changed, 30 insertions, 19 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index f2f67067d15..a01bac2077f 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1057,6 +1057,16 @@ static Value *SimplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
(!isSigned && match(Op0, m_URem(m_Value(), m_Specific(Op1)))))
return Constant::getNullValue(Op0->getType());
+ // (X /u C1) /u C2 -> 0 if C1 * C2 overflow
+ ConstantInt *C1, *C2;
+ if (!isSigned && match(Op0, m_UDiv(m_Value(X), m_ConstantInt(C1))) &&
+ match(Op1, m_ConstantInt(C2))) {
+ bool Overflow;
+ C1->getValue().umul_ov(C2->getValue(), Overflow);
+ if (Overflow)
+ return Constant::getNullValue(Op0->getType());
+ }
+
// If the operation is with the result of a select instruction, check whether
// operating on either branch of the select always yields the same value.
if (isa<SelectInst>(Op0) || isa<SelectInst>(Op1))
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 249456fa6ea..8d004f2a0a2 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -727,11 +727,10 @@ Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) {
// (X / C1) / C2 -> X / (C1*C2)
if (Instruction::BinaryOps(LHS->getOpcode()) == I.getOpcode())
if (ConstantInt *LHSRHS = dyn_cast<ConstantInt>(LHS->getOperand(1))) {
- if (MultiplyOverflows(RHS, LHSRHS,
- I.getOpcode() == Instruction::SDiv))
- return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
- return BinaryOperator::Create(I.getOpcode(), LHS->getOperand(0),
- ConstantExpr::getMul(RHS, LHSRHS));
+ if (!MultiplyOverflows(RHS, LHSRHS,
+ I.getOpcode() == Instruction::SDiv))
+ return BinaryOperator::Create(I.getOpcode(), LHS->getOperand(0),
+ ConstantExpr::getMul(RHS, LHSRHS));
}
Value *X;
diff --git a/llvm/test/Transforms/InstCombine/2008-02-16-SDivOverflow.ll b/llvm/test/Transforms/InstCombine/2008-02-16-SDivOverflow.ll
deleted file mode 100644
index 917d3d9436b..00000000000
--- a/llvm/test/Transforms/InstCombine/2008-02-16-SDivOverflow.ll
+++ /dev/null
@@ -1,14 +0,0 @@
-; RUN: opt < %s -instcombine -S | grep "ret i.* 0" | count 2
-; PR2048
-
-define i32 @i(i32 %a) {
- %tmp1 = sdiv i32 %a, -1431655765
- %tmp2 = sdiv i32 %tmp1, 3
- ret i32 %tmp2
-}
-
-define i8 @j(i8 %a) {
- %tmp1 = sdiv i8 %a, 64
- %tmp2 = sdiv i8 %tmp1, 3
- ret i8 %tmp2
-}
diff --git a/llvm/test/Transforms/InstSimplify/exact-nsw-nuw.ll b/llvm/test/Transforms/InstSimplify/exact-nsw-nuw.ll
index a0e326b13c0..5ccc8083e64 100644
--- a/llvm/test/Transforms/InstSimplify/exact-nsw-nuw.ll
+++ b/llvm/test/Transforms/InstSimplify/exact-nsw-nuw.ll
@@ -42,3 +42,19 @@ define i32 @shift5(i32 %A, i32 %B) {
%D = ashr i32 %C, %B
ret i32 %D
}
+
+; CHECK-LABEL: @div1(
+; CHECK: ret i32 0
+define i32 @div1(i32 %V) {
+ %A = udiv i32 %V, -2147483648
+ %B = udiv i32 %A, -2147483648
+ ret i32 %B
+}
+
+; CHECK-LABEL: @div2(
+; CHECK-NOT: ret i32 0
+define i32 @div2(i32 %V) {
+ %A = sdiv i32 %V, -1
+ %B = sdiv i32 %A, -2147483648
+ ret i32 %B
+}
OpenPOWER on IntegriCloud