[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