summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2019-04-09 15:13:03 +0000
committerSanjay Patel <spatel@rotateright.com>2019-04-09 15:13:03 +0000
commit49d9d17a77cb0bab1b7fb7b141af272a62856550 (patch)
treedce38e4e37b7e30ea931a6e648be76b1213696ff
parent9b22c469ca2f50325cbec067f2faf2bd92ce444f (diff)
downloadbcm5719-llvm-49d9d17a77cb0bab1b7fb7b141af272a62856550.tar.gz
bcm5719-llvm-49d9d17a77cb0bab1b7fb7b141af272a62856550.zip
[InstCombine] prevent possible miscompile with sdiv+negate of vector op
Similar to: rL358005 Forego folding arbitrary vector constants to fix a possible miscompile bug. We can enhance the transform if we do want to handle the more complicated vector case. llvm-svn: 358013
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp21
-rw-r--r--llvm/test/Transforms/InstCombine/div.ll11
2 files changed, 18 insertions, 14 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 6be2efdcc53..cb8708446b2 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1015,6 +1015,10 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
(match(Op1, m_SExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1)))
return BinaryOperator::CreateNeg(Op0);
+ // X / INT_MIN --> X == INT_MIN
+ if (match(Op1, m_SignMask()))
+ return new ZExtInst(Builder.CreateICmpEQ(Op0, Op1), I.getType());
+
const APInt *Op1C;
if (match(Op1, m_APInt(Op1C))) {
// sdiv exact X, C --> ashr exact X, log2(C)
@@ -1039,17 +1043,14 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
Value *NarrowOp = Builder.CreateSDiv(Op0Src, NarrowDivisor);
return new SExtInst(NarrowOp, Op0->getType());
}
- }
- if (Constant *RHS = dyn_cast<Constant>(Op1)) {
- // X/INT_MIN -> X == INT_MIN
- if (RHS->isMinSignedValue())
- return new ZExtInst(Builder.CreateICmpEQ(Op0, Op1), I.getType());
-
- // -X/C --> X/-C provided the negation doesn't overflow.
- Value *X;
- if (match(Op0, m_NSWSub(m_Zero(), m_Value(X)))) {
- auto *BO = BinaryOperator::CreateSDiv(X, ConstantExpr::getNeg(RHS));
+ // -X / C --> X / -C (if the negation doesn't overflow).
+ // TODO: This could be enhanced to handle arbitrary vector constants by
+ // checking if all elements are not the min-signed-val.
+ if (!Op1C->isMinSignedValue() &&
+ match(Op0, m_NSWSub(m_Zero(), m_Value(X)))) {
+ Constant *NegC = ConstantInt::get(I.getType(), -(*Op1C));
+ Instruction *BO = BinaryOperator::CreateSDiv(X, NegC);
BO->setIsExact(I.isExact());
return BO;
}
diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll
index c9d56dc9efd..6b373328016 100644
--- a/llvm/test/Transforms/InstCombine/div.ll
+++ b/llvm/test/Transforms/InstCombine/div.ll
@@ -522,7 +522,8 @@ define <2 x i8> @sdiv_negated_dividend_constant_divisor_vec_undef(<2 x i8> %x) {
define <2 x i64> @sdiv_negated_dividend_constant_divisor_vec(<2 x i64> %x) {
; CHECK-LABEL: @sdiv_negated_dividend_constant_divisor_vec(
-; CHECK-NEXT: [[DIV:%.*]] = sdiv <2 x i64> [[X:%.*]], <i64 -3, i64 -4>
+; CHECK-NEXT: [[NEG:%.*]] = sub nsw <2 x i64> zeroinitializer, [[X:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = sdiv <2 x i64> [[NEG]], <i64 3, i64 4>
; CHECK-NEXT: ret <2 x i64> [[DIV]]
;
%neg = sub nsw <2 x i64> zeroinitializer, %x
@@ -532,7 +533,8 @@ define <2 x i64> @sdiv_negated_dividend_constant_divisor_vec(<2 x i64> %x) {
define <2 x i64> @sdiv_exact_negated_dividend_constant_divisor_vec(<2 x i64> %x) {
; CHECK-LABEL: @sdiv_exact_negated_dividend_constant_divisor_vec(
-; CHECK-NEXT: [[DIV:%.*]] = sdiv exact <2 x i64> [[X:%.*]], <i64 -3, i64 -4>
+; CHECK-NEXT: [[NEG:%.*]] = sub nsw <2 x i64> zeroinitializer, [[X:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = sdiv exact <2 x i64> [[NEG]], <i64 3, i64 4>
; CHECK-NEXT: ret <2 x i64> [[DIV]]
;
%neg = sub nsw <2 x i64> zeroinitializer, %x
@@ -540,11 +542,12 @@ define <2 x i64> @sdiv_exact_negated_dividend_constant_divisor_vec(<2 x i64> %x)
ret <2 x i64> %div
}
-; FIXME: Can't negate signed min vector element.
+; Can't negate signed min vector element.
define <2 x i8> @sdiv_exact_negated_dividend_constant_divisor_vec_overflow(<2 x i8> %x) {
; CHECK-LABEL: @sdiv_exact_negated_dividend_constant_divisor_vec_overflow(
-; CHECK-NEXT: [[DIV:%.*]] = sdiv exact <2 x i8> [[X:%.*]], <i8 -128, i8 -42>
+; CHECK-NEXT: [[NEG:%.*]] = sub nsw <2 x i8> zeroinitializer, [[X:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = sdiv exact <2 x i8> [[NEG]], <i8 -128, i8 42>
; CHECK-NEXT: ret <2 x i8> [[DIV]]
;
%neg = sub nsw <2 x i8> zeroinitializer, %x
OpenPOWER on IntegriCloud