[llvm] r358005 - [InstCombine] prevent possible miscompile with negate+sdiv of vector op
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 9 07:09:07 PDT 2019
Author: spatel
Date: Tue Apr 9 07:09:06 2019
New Revision: 358005
URL: http://llvm.org/viewvc/llvm-project?rev=358005&view=rev
Log:
[InstCombine] prevent possible miscompile with negate+sdiv of vector op
// 0 - (X sdiv C) -> (X sdiv -C) provided the negation doesn't overflow.
This fold has been around for many years and nobody noticed the potential
vector miscompile from overflow until recently...
So it seems unlikely that there's much demand for a vector sdiv optimization
on arbitrary vector constants, so just limit the matching to splat constants
to avoid the possible bug.
Differential Revision: https://reviews.llvm.org/D60426
Modified:
llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp
llvm/trunk/test/Transforms/InstCombine/div.ll
Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp?rev=358005&r1=358004&r2=358005&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp Tue Apr 9 07:09:06 2019
@@ -1692,9 +1692,12 @@ Instruction *InstCombiner::visitSub(Bina
Builder.CreateNot(Y, Y->getName() + ".not"));
// 0 - (X sdiv C) -> (X sdiv -C) provided the negation doesn't overflow.
- if (match(Op1, m_SDiv(m_Value(X), m_Constant(C))) && match(Op0, m_Zero()) &&
- C->isNotMinSignedValue() && !C->isOneValue()) {
- auto *BO = BinaryOperator::CreateSDiv(X, ConstantExpr::getNeg(C));
+ // TODO: This could be extended to match arbitrary vector constants.
+ const APInt *DivC;
+ if (match(Op0, m_Zero()) && match(Op1, m_SDiv(m_Value(X), m_APInt(DivC))) &&
+ !DivC->isMinSignedValue() && *DivC != 1) {
+ Constant *NegDivC = ConstantInt::get(I.getType(), -(*DivC));
+ Instruction *BO = BinaryOperator::CreateSDiv(X, NegDivC);
BO->setIsExact(cast<BinaryOperator>(Op1)->isExact());
return BO;
}
Modified: llvm/trunk/test/Transforms/InstCombine/div.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/div.ll?rev=358005&r1=358004&r2=358005&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/div.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/div.ll Tue Apr 9 07:09:06 2019
@@ -772,7 +772,8 @@ define i32 @test_exact_nsw_exact(i32 %x)
define <2 x i64> @test_exact_vec(<2 x i64> %x) {
; CHECK-LABEL: @test_exact_vec(
-; CHECK-NEXT: [[NEG:%.*]] = sdiv exact <2 x i64> [[X:%.*]], <i64 -3, i64 -4>
+; CHECK-NEXT: [[DIV:%.*]] = sdiv exact <2 x i64> [[X:%.*]], <i64 3, i64 4>
+; CHECK-NEXT: [[NEG:%.*]] = sub nsw <2 x i64> zeroinitializer, [[DIV]]
; CHECK-NEXT: ret <2 x i64> [[NEG]]
;
%div = sdiv exact <2 x i64> %x, <i64 3, i64 4>
@@ -832,7 +833,8 @@ define <2 x i8> @negate_sdiv_vec_splat_s
define <2 x i8> @negate_sdiv_vec_one_element(<2 x i8> %x) {
; CHECK-LABEL: @negate_sdiv_vec_one_element(
-; CHECK-NEXT: [[NEG:%.*]] = sdiv <2 x i8> [[X:%.*]], <i8 1, i8 -1>
+; CHECK-NEXT: [[DIV:%.*]] = sdiv <2 x i8> [[X:%.*]], <i8 -1, i8 1>
+; CHECK-NEXT: [[NEG:%.*]] = sub <2 x i8> zeroinitializer, [[DIV]]
; CHECK-NEXT: ret <2 x i8> [[NEG]]
;
%div = sdiv <2 x i8> %x, <i8 -1, i8 1>
@@ -840,7 +842,7 @@ define <2 x i8> @negate_sdiv_vec_one_ele
ret <2 x i8> %neg
}
-; Division by -1 may be UB and can't negate signed-min.
+; Can't negate signed-min constant for any element of a vector.
define <2 x i8> @negate_sdiv_vec_signed_min_elt(<2 x i8> %x) {
; CHECK-LABEL: @negate_sdiv_vec_signed_min_elt(
@@ -853,7 +855,7 @@ define <2 x i8> @negate_sdiv_vec_signed_
ret <2 x i8> %neg
}
-; Can't negate signed-min constant for any element of a vector.
+; Division by -1 may be UB and can't negate signed-min.
define <2 x i8> @negate_sdiv_vec_signed_min_and_one_elt(<2 x i8> %x) {
; CHECK-LABEL: @negate_sdiv_vec_signed_min_and_one_elt(
More information about the llvm-commits
mailing list