diff options
| author | Sanjay Patel <spatel@rotateright.com> | 2019-04-09 15:13:03 +0000 |
|---|---|---|
| committer | Sanjay Patel <spatel@rotateright.com> | 2019-04-09 15:13:03 +0000 |
| commit | 49d9d17a77cb0bab1b7fb7b141af272a62856550 (patch) | |
| tree | dce38e4e37b7e30ea931a6e648be76b1213696ff | |
| parent | 9b22c469ca2f50325cbec067f2faf2bd92ce444f (diff) | |
| download | bcm5719-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.cpp | 21 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/div.ll | 11 |
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 |

