compare-elim.c (struct comparison): Add not_in_a field.
authorEric Botcazou <ebotcazou@adacore.com>
Mon, 19 Nov 2018 10:25:35 +0000 (10:25 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Mon, 19 Nov 2018 10:25:35 +0000 (10:25 +0000)
* compare-elim.c (struct comparison): Add not_in_a field.
(is_not): New static function.
(strip_not): Likewise.
(conforming_compare): Handle a NOT in the first operand.
(can_eliminate_compare): Likewise.
(find_comparison_dom_walker::before_dom_children): Likewise.
(try_eliminate_compare): Likewise.
* config/visium/visium.md (negsi2_insn_set_carry): Turn into...
(neg<mode>2_insn_set_carry): ...this and add missing NEG operation.

From-SVN: r266268

gcc/ChangeLog
gcc/compare-elim.c
gcc/config/visium/visium.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/visium/overflow16.c
gcc/testsuite/gcc.target/visium/overflow32.c
gcc/testsuite/gcc.target/visium/overflow8.c

index 0b8ab0c754e4f12378ea9aea804337e62adf47e6..98038718e7d31d18789bac5830538983692ddbd0 100644 (file)
@@ -1,3 +1,15 @@
+2018-11-19  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * compare-elim.c (struct comparison): Add not_in_a field.
+       (is_not): New static function.
+       (strip_not): Likewise.
+       (conforming_compare): Handle a NOT in the first operand.
+       (can_eliminate_compare): Likewise.
+       (find_comparison_dom_walker::before_dom_children): Likewise.
+       (try_eliminate_compare): Likewise.
+       * config/visium/visium.md (negsi2_insn_set_carry): Turn into...
+       (neg<mode>2_insn_set_carry): ...this and add missing NEG operation.
+
 2018-11-19  Jonathan Wakely  <jwakely@redhat.com>
 
        * doc/extend.texi (Common Type Attributes): Fix typos.
index 8afbe76c502bdd0f3cd87c7191425f6229e6ba50..f38e57605744af9506d3e42dcbdb0ee7d67cac78 100644 (file)
@@ -123,10 +123,32 @@ struct comparison
 
   /* True if its inputs are still valid at the end of the block.  */
   bool inputs_valid;
+
+  /* Whether IN_A is wrapped in a NOT before being compared.  */
+  bool not_in_a;
 };
   
 static vec<comparison *> all_compares;
 
+/* Return whether X is a NOT unary expression.  */
+
+static bool
+is_not (rtx x)
+{
+  return GET_CODE (x) == NOT;
+}
+
+/* Strip a NOT unary expression around X, if any.  */
+
+static rtx
+strip_not (rtx x)
+{
+  if (is_not (x))
+    return XEXP (x, 0);
+
+  return x;
+}
+
 /* Look for a "conforming" comparison, as defined above.  If valid, return
    the rtx for the COMPARE itself.  */
 
@@ -147,7 +169,7 @@ conforming_compare (rtx_insn *insn)
   if (!REG_P (dest) || REGNO (dest) != targetm.flags_regnum)
     return NULL;
 
-  if (!REG_P (XEXP (src, 0)))
+  if (!REG_P (strip_not (XEXP (src, 0))))
     return NULL;
 
   if (CONSTANT_P (XEXP (src, 1)) || REG_P (XEXP (src, 1)))
@@ -278,10 +300,13 @@ can_eliminate_compare (rtx compare, rtx eh_note, struct comparison *cmp)
     return false;
 
   /* Make sure the compare is redundant with the previous.  */
-  if (!rtx_equal_p (XEXP (compare, 0), cmp->in_a)
+  if (!rtx_equal_p (strip_not (XEXP (compare, 0)), cmp->in_a)
       || !rtx_equal_p (XEXP (compare, 1), cmp->in_b))
     return false;
 
+  if (is_not (XEXP (compare, 0)) != cmp->not_in_a)
+    return false;
+
   /* New mode must be compatible with the previous compare mode.  */
   machine_mode new_mode
     = targetm.cc_modes_compatible (GET_MODE (compare), cmp->orig_mode);
@@ -365,8 +390,9 @@ find_comparison_dom_walker::before_dom_children (basic_block bb)
          last_cmp = XCNEW (struct comparison);
          last_cmp->insn = insn;
          last_cmp->prev_clobber = last_clobber;
-         last_cmp->in_a = XEXP (src, 0);
+         last_cmp->in_a = strip_not (XEXP (src, 0));
          last_cmp->in_b = XEXP (src, 1);
+         last_cmp->not_in_a = is_not (XEXP (src, 0));
          last_cmp->eh_note = eh_note;
          last_cmp->orig_mode = GET_MODE (src);
          if (last_cmp->in_b == const0_rtx
@@ -837,7 +863,9 @@ try_eliminate_compare (struct comparison *cmp)
     flags = gen_rtx_REG (cmp->orig_mode, targetm.flags_regnum);
 
   /* Generate a new comparison for installation in the setter.  */
-  rtx y = copy_rtx (cmp_a);
+  rtx y = cmp->not_in_a
+         ? gen_rtx_NOT (GET_MODE (cmp_a), copy_rtx (cmp_a))
+         : copy_rtx (cmp_a);
   y = gen_rtx_COMPARE (GET_MODE (flags), y, copy_rtx (cmp_b));
   y = gen_rtx_SET (flags, y);
 
index f94a4d4faa96b2bc400e4ba7e2936e5f9ca2ace9..c5100b7027d53e730d1a3576a41bebbb2935d9ca 100644 (file)
   "sub<s>   %0,r0,%1"
   [(set_attr "type" "arith")])
 
-(define_insn "negsi2_insn_set_carry"
+(define_insn "neg<mode>2_insn_set_carry"
   [(set (reg:CCC R_FLAGS)
-       (compare:CCC (not:SI (match_operand:SI 1 "register_operand" "r"))
+       (compare:CCC (not:I (neg:I (match_operand:I 1 "register_operand" "r")))
                     (const_int -1)))
-   (set (match_operand:SI 0 "register_operand" "=r")
-        (neg:SI (match_dup 1)))]
+   (set (match_operand:I 0 "register_operand" "=r")
+        (neg:I (match_dup 1)))]
   "reload_completed"
-  "sub.l   %0,r0,%1"
+  "sub<s>   %0,r0,%1"
   [(set_attr "type" "arith")])
 
 (define_insn "*neg<mode>2_insn_set_overflow"
index e1f0ac6b0cc6a3bfb64b8a3437d71753ba998944..271055d349a4f09a860a4215a1037a2effe1370c 100644 (file)
@@ -1,3 +1,10 @@
+2018-11-19  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc.target/visium/overflow8.c: Remove -fno-if-conversion and
+       unrelated final test.
+       * gcc.target/visium/overflow16: Likewise.
+       * gcc.target/visium/overflow32.c: Likewise.
+
 2018-11-18  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * g++.dg/template/crash91.C: Check location too.
index 223184a2d36dcda1ad16b115d3f52bc800ea753c..665b4c39be4f06876bf583d31de821c2c903b6f7 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fno-if-conversion" } */
+/* { dg-options "-O2" } */
 
 #include <stdbool.h>
 
@@ -36,4 +36,3 @@ bool my_neg_overflow (short a, short *res)
 /* { dg-final { scan-assembler-times "add.w" 2 } } */
 /* { dg-final { scan-assembler-times "sub.w" 4 } } */
 /* { dg-final { scan-assembler-not "cmp.w" } } */
-/* { dg-final { scan-assembler-not "mov.w" } } */
index e73deb707567e8d32efc7bf323778e2bfaf2e628..c9c509508ac916ee4a5a0508c7cab059c34ea47a 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fno-if-conversion" } */
+/* { dg-options "-O2" } */
 
 #include <stdbool.h>
 
@@ -36,4 +36,3 @@ bool my_neg_overflow (int a, int *res)
 /* { dg-final { scan-assembler-times "add.l" 2 } } */
 /* { dg-final { scan-assembler-times "sub.l" 4 } } */
 /* { dg-final { scan-assembler-not "cmp.l" } } */
-/* { dg-final { scan-assembler-not "mov.l" } } */
index 3aa153e92ab508ed9781c155d2deb4005c5aba60..1f96ecbeba62187ceae412a7b89b9a75f2674344 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fno-if-conversion" } */
+/* { dg-options "-O2" } */
 
 #include <stdbool.h>
 
@@ -36,4 +36,3 @@ bool my_neg_overflow (signed char a, signed char *res)
 /* { dg-final { scan-assembler-times "add.b" 2 } } */
 /* { dg-final { scan-assembler-times "sub.b" 4 } } */
 /* { dg-final { scan-assembler-not "cmp.b" } } */
-/* { dg-final { scan-assembler-not "mov.b" } } */