Patchwork [i386] : Fix PR 58779, wrong MINUS overflow checks

login
register
mail settings
Submitter Uros Bizjak
Date Oct. 22, 2013, 6:31 p.m.
Message ID <CAFULd4YjgQ9KtsAQT8eM=r6NE1iy6JSf55djjLsnAQCNkRvEug@mail.gmail.com>
Download mbox | patch
Permalink /patch/285480/
State New
Headers show

Comments

Uros Bizjak - Oct. 22, 2013, 6:31 p.m.
Hello!

As explained in the PR [1], the pattern that implements MINUS overflow
checks is wrong. The combine pass is able to create
*subsi3_cconly_overflow pattern, but since the functionality of the
pattern depends on inverted conditions in put_condition_mode, the
final jump in the combined sequence gets the inverted condition.

The attached patch removes wrong definitions.

2013-10-22  Uros Bizjak  <ubizjak@gmail.com>

    PR target/58779
    * config/i386/i386.c (put_condition_code) <case GTU, case LEU>:
    Remove CCCmode handling.
    <case LTU>: Return 'c' suffix for CCCmode.
    <case GEU>: Return 'nc' suffix for CCCmode.
    (ix86_cc_mode) <case GTU, case LEU>: Do not generate overflow checks.
    * config/i386/i386.md (*sub<mode>3_cconly_overflow): Remove.
    (*sub<mode>3_cc_overflow): Ditto.
    (*subsi3_zext_cc_overflow): Ditto.

testsuite/ChangeLog:

2013-10-22  Uros Bizjak  <ubizjak@gmail.com>

    PR target/58779
    * gcc.target/i386/pr30315.c: Remove MINUSCC, DECCC, MINUSCCONLY
    and MINUSCCZEXT defines. Update scan-assembler dg directive.
    * gcc.dg/torture/pr58779.c: New test.

Patch was bootstrapped and regression tested on x86_64-pc-linux-gnu
{,-m32} for all default languages plus obj-c++ and go.

Patch was committed to mainline SVN and will be committed to release
branches in a couple of days.

[1] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58779#c5

Uros.

Patch

Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 203860)
+++ config/i386/i386.c	(working copy)
@@ -14103,8 +14103,6 @@  put_condition_code (enum rtx_code code, enum machi
 	 Those same assemblers have the same but opposite lossage on cmov.  */
       if (mode == CCmode)
 	suffix = fp ? "nbe" : "a";
-      else if (mode == CCCmode)
-	suffix = "b";
       else
 	gcc_unreachable ();
       break;
@@ -14126,8 +14124,12 @@  put_condition_code (enum rtx_code code, enum machi
 	}
       break;
     case LTU:
-      gcc_assert (mode == CCmode || mode == CCCmode);
-      suffix = "b";
+      if (mode == CCmode)
+	suffix = "b";
+      else if (mode == CCCmode)
+	suffix = "c";
+      else
+	gcc_unreachable ();
       break;
     case GE:
       switch (mode)
@@ -14147,20 +14149,20 @@  put_condition_code (enum rtx_code code, enum machi
 	}
       break;
     case GEU:
-      /* ??? As above.  */
-      gcc_assert (mode == CCmode || mode == CCCmode);
-      suffix = fp ? "nb" : "ae";
+      if (mode == CCmode)
+	suffix = fp ? "nb" : "ae";
+      else if (mode == CCCmode)
+	suffix = "nc";
+      else
+	gcc_unreachable ();
       break;
     case LE:
       gcc_assert (mode == CCmode || mode == CCGCmode || mode == CCNOmode);
       suffix = "le";
       break;
     case LEU:
-      /* ??? As above.  */
       if (mode == CCmode)
 	suffix = "be";
-      else if (mode == CCCmode)
-	suffix = fp ? "nb" : "ae";
       else
 	gcc_unreachable ();
       break;
@@ -18862,12 +18864,7 @@  ix86_cc_mode (enum rtx_code code, rtx op0, rtx op1
 	return CCmode;
     case GTU:			/* CF=0 & ZF=0 */
     case LEU:			/* CF=1 | ZF=1 */
-      /* Detect overflow checks.  They need just the carry flag.  */
-      if (GET_CODE (op0) == MINUS
-	  && rtx_equal_p (op1, XEXP (op0, 0)))
-	return CCCmode;
-      else
-	return CCmode;
+      return CCmode;
       /* Codes possibly doable only with sign flag when
          comparing against zero.  */
     case GE:			/* SF=OF   or   SF=0 */
Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md	(revision 203860)
+++ config/i386/i386.md	(working copy)
@@ -6486,7 +6486,7 @@ 
    (set_attr "use_carry" "1")
    (set_attr "mode" "<MODE>")])
 
-;; Overflow setting add and subtract instructions
+;; Overflow setting add instructions
 
 (define_insn "*add<mode>3_cconly_overflow"
   [(set (reg:CCC FLAGS_REG)
@@ -6501,43 +6501,31 @@ 
   [(set_attr "type" "alu")
    (set_attr "mode" "<MODE>")])
 
-(define_insn "*sub<mode>3_cconly_overflow"
+(define_insn "*add<mode>3_cc_overflow"
   [(set (reg:CCC FLAGS_REG)
 	(compare:CCC
-	  (minus:SWI
-	    (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>")
-	    (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m"))
-	  (match_dup 0)))]
-  ""
-  "cmp{<imodesuffix>}\t{%1, %0|%0, %1}"
-  [(set_attr "type" "icmp")
-   (set_attr "mode" "<MODE>")])
-
-(define_insn "*<plusminus_insn><mode>3_cc_overflow"
-  [(set (reg:CCC FLAGS_REG)
-	(compare:CCC
-	    (plusminus:SWI
-		(match_operand:SWI 1 "nonimmediate_operand" "<comm>0,0")
+	    (plus:SWI
+		(match_operand:SWI 1 "nonimmediate_operand" "%0,0")
 		(match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m"))
 	    (match_dup 1)))
    (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
-	(plusminus:SWI (match_dup 1) (match_dup 2)))]
-  "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
-  "<plusminus_mnemonic>{<imodesuffix>}\t{%2, %0|%0, %2}"
+	(plus:SWI (match_dup 1) (match_dup 2)))]
+  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
+  "add{<imodesuffix>}\t{%2, %0|%0, %2}"
   [(set_attr "type" "alu")
    (set_attr "mode" "<MODE>")])
 
-(define_insn "*<plusminus_insn>si3_zext_cc_overflow"
+(define_insn "*addsi3_zext_cc_overflow"
   [(set (reg:CCC FLAGS_REG)
 	(compare:CCC
-	  (plusminus:SI
-	    (match_operand:SI 1 "nonimmediate_operand" "<comm>0")
+	  (plus:SI
+	    (match_operand:SI 1 "nonimmediate_operand" "%0")
 	    (match_operand:SI 2 "x86_64_general_operand" "rme"))
 	  (match_dup 1)))
    (set (match_operand:DI 0 "register_operand" "=r")
-	(zero_extend:DI (plusminus:SI (match_dup 1) (match_dup 2))))]
-  "TARGET_64BIT && ix86_binary_operator_ok (<CODE>, SImode, operands)"
-  "<plusminus_mnemonic>{l}\t{%2, %k0|%k0, %2}"
+	(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
+  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
+  "add{l}\t{%2, %k0|%k0, %2}"
   [(set_attr "type" "alu")
    (set_attr "mode" "SI")])
 
Index: testsuite/gcc.dg/torture/pr58779.c
===================================================================
--- testsuite/gcc.dg/torture/pr58779.c	(revision 0)
+++ testsuite/gcc.dg/torture/pr58779.c	(working copy)
@@ -0,0 +1,12 @@ 
+/* { dg-do run } */
+
+int a, c;
+
+int main ()
+{
+  int e = -1;
+  short d = (c <= 0) ^ e;
+  if ((unsigned int) a - (a || d) <= (unsigned int) a)
+    __builtin_abort ();
+  return 0;
+}
Index: testsuite/gcc.target/i386/pr30315.c
===================================================================
--- testsuite/gcc.target/i386/pr30315.c	(revision 203860)
+++ testsuite/gcc.target/i386/pr30315.c	(working copy)
@@ -1,6 +1,6 @@ 
 /* { dg-do compile } */
 /* { dg-options "-O2" } */
-/* { dg-final { scan-assembler-times "cmp" 4 } } */
+/* { dg-final { scan-assembler-not "cmp" } } */
 
 extern void abort (void);
 int c;
@@ -34,39 +34,10 @@  void pluscconly##t##C (T a, T b)	\
 }
 #define PLUSCCONLY(T, t) PLUSCCONLY1(T, t, a) PLUSCCONLY1(T, t, b)
 
-#define MINUSCC(T, t)	\
-T minuscc##t (T a, T b)	\
-{	\
-  T difference = a - b;	\
-  if (difference > a)	\
-    abort ();		\
-  return difference;	\
-}
-
-#define DECCC(T, t)	\
-T deccc##t (T a, T b)	\
-{	\
-  T difference = a - b;	\
-  if (difference > a)	\
-    c --;		\
-  return difference;	\
-}
-
-#define MINUSCCONLY(T, t)	\
-void minuscconly##t (T a, T b)	\
-{	\
-  T difference = a - b;	\
-  if (difference > a)	\
-    abort ();		\
-}
-
 #define TEST(T, t)	\
   PLUSCC(T, t)		\
   PLUSCCONLY(T, t)	\
-  INCCC(T, t)		\
-  MINUSCC(T, t)		\
-  MINUSCCONLY(T, t)	\
-  DECCC(T, t)
+  INCCC(T, t)
 
 TEST (unsigned long,  l)
 TEST (unsigned int,   i)
@@ -84,14 +55,3 @@  unsigned long pluscczext##C (unsigned int a, unsig
 
 PLUSCCZEXT(a)
 PLUSCCZEXT(b)
-
-#define MINUSCCZEXT	\
-unsigned long minuscczext (unsigned int a, unsigned int b)	\
-{	\
-  unsigned int difference = a - b;	\
-  if (difference > a)		\
-    abort ();			\
-  return difference;		\
-}
-
-MINUSCCZEXT