[llvm-commits] [llvm] r60275 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/apint-sub.ll test/Transforms/InstCombine/sdiv-1.ll test/Transforms/InstCombine/sub.ll

Bill Wendling isanbard at gmail.com
Sat Nov 29 19:42:13 PST 2008


Author: void
Date: Sat Nov 29 21:42:12 2008
New Revision: 60275

URL: http://llvm.org/viewvc/llvm-project?rev=60275&view=rev
Log:
Instcombine was illegally transforming -X/C into X/-C when either X or C
overflowed on negation. This commit checks to make sure that neithe C nor X
overflows. This requires that the RHS of X (a subtract instruction) be a
constant integer.

Added:
    llvm/trunk/test/Transforms/InstCombine/sdiv-1.ll
Modified:
    llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
    llvm/trunk/test/Transforms/InstCombine/apint-sub.ll
    llvm/trunk/test/Transforms/InstCombine/sub.ll

Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=60275&r1=60274&r2=60275&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Sat Nov 29 21:42:12 2008
@@ -2956,9 +2956,26 @@
     if (RHS->isAllOnesValue())
       return BinaryOperator::CreateNeg(Op0);
 
-    // -X/C -> X/-C
-    if (Value *LHSNeg = dyn_castNegVal(Op0))
-      return BinaryOperator::CreateSDiv(LHSNeg, ConstantExpr::getNeg(RHS));
+    ConstantInt *RHSNeg = cast<ConstantInt>(ConstantExpr::getNeg(RHS));
+
+    // -X/C -> X/-C, if and only if negation doesn't overflow.
+    if ((RHS->getSExtValue() < 0 &&
+         RHS->getSExtValue() < RHSNeg->getSExtValue()) ||
+        (RHS->getSExtValue() > 0 &&
+         RHS->getSExtValue() > RHSNeg->getSExtValue())) {
+      if (Value *LHSNeg = dyn_castNegVal(Op0)) {
+        if (ConstantInt *CI = dyn_cast<ConstantInt>(LHSNeg)) {
+          ConstantInt *CINeg = cast<ConstantInt>(ConstantExpr::getNeg(CI));
+
+          if ((CI->getSExtValue() < 0 &&
+               CI->getSExtValue() < CINeg->getSExtValue()) ||
+              (CI->getSExtValue() > 0 &&
+               CI->getSExtValue() > CINeg->getSExtValue()))
+            return BinaryOperator::CreateSDiv(LHSNeg,
+                                              ConstantExpr::getNeg(RHS));
+        }
+      }
+    }
   }
 
   // If the sign bits of both operands are zero (i.e. we can prove they are

Modified: llvm/trunk/test/Transforms/InstCombine/apint-sub.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/apint-sub.ll?rev=60275&r1=60274&r2=60275&view=diff

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/apint-sub.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/apint-sub.ll Sat Nov 29 21:42:12 2008
@@ -3,7 +3,7 @@
 ;
 
 ; RUN: llvm-as < %s | opt -instcombine | llvm-dis | \
-; RUN:   grep -v {sub i19 %Cok, %Bok} | not grep sub
+; RUN:   grep -v {sub i19 %Cok, %Bok} | grep -v {sub i25 0, %Aok} | not grep sub
 ; END.
 
 define i23 @test1(i23 %A) {
@@ -107,8 +107,10 @@
 	ret i51 %Y
 }
 
-define i25 @test17(i25 %A) {
-	%B = sub i25 0, %A		; <i25> [#uses=1]
+; Can't fold subtract here because negation it might oveflow.
+; PR3142
+define i25 @test17(i25 %Aok) {
+	%B = sub i25 0, %Aok		; <i25> [#uses=1]
 	%C = sdiv i25 %B, 1234		; <i25> [#uses=1]
 	ret i25 %C
 }

Added: llvm/trunk/test/Transforms/InstCombine/sdiv-1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/sdiv-1.ll?rev=60275&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/sdiv-1.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/sdiv-1.ll Sat Nov 29 21:42:12 2008
@@ -0,0 +1,22 @@
+; RUN: llvm-as < %s | opt -instcombine -inline | llvm-dis | grep {715827882} | count 2
+; PR3142
+
+define i32 @a(i32 %X) nounwind readnone {
+entry:
+       %0 = sub i32 0, %X
+       %1 = sdiv i32 %0, -3
+       ret i32 %1
+}
+
+define i32 @b(i32 %X) nounwind readnone {
+entry:
+       %0 = call i32 @a(i32 -2147483648)
+       ret i32 %0
+}
+
+define i32 @c(i32 %X) nounwind readnone {
+entry:
+       %0 = sub i32 0, -2147483648
+       %1 = sdiv i32 %0, -3
+       ret i32 %1
+}

Modified: llvm/trunk/test/Transforms/InstCombine/sub.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/sub.ll?rev=60275&r1=60274&r2=60275&view=diff

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/sub.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/sub.ll Sat Nov 29 21:42:12 2008
@@ -1,7 +1,7 @@
 ; This test makes sure that these instructions are properly eliminated.
 ;
 ; RUN: llvm-as < %s | opt -instcombine | llvm-dis | \
-; RUN:   grep -v {sub i32 %Cok, %Bok} | not grep sub
+; RUN:   grep -v {sub i32 %Cok, %Bok} | grep -v {sub i32 0, %Aok} | not grep sub
 
 define i32 @test1(i32 %A) {
 	%B = sub i32 %A, %A		; <i32> [#uses=1]
@@ -104,8 +104,10 @@
 	ret i32 %Y
 }
 
-define i32 @test17(i32 %A) {
-	%B = sub i32 0, %A		; <i32> [#uses=1]
+; Can't fold subtract here because negation it might oveflow.
+; PR3142
+define i32 @test17(i32 %Aok) {
+	%B = sub i32 0, %Aok		; <i32> [#uses=1]
 	%C = sdiv i32 %B, 1234		; <i32> [#uses=1]
 	ret i32 %C
 }





More information about the llvm-commits mailing list