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  <ubiz...@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  <ubiz...@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.
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

Reply via email to