cris: update recent patterns. Simplify cris_select_cc_mode.
authorHans-Peter Nilsson <hp@axis.com>
Sun, 5 Jul 2020 23:10:54 +0000 (01:10 +0200)
committerHans-Peter Nilsson <hp@axis.com>
Sun, 5 Jul 2020 23:17:54 +0000 (01:17 +0200)
The code in cris_select_cc_mode for selecting CC_NZmode was
partly inconsistent with the comment and partly seemed
ambiguous.  I couldn't find a reason why I qualified selection
of CC_NZmode on the setting operation once a matching user was
spotted, so I just removed that.  The cris.c update was due to
observing the new test-case failing; the CC_NZmode compare
wasn't eliminated.

The recently re-instated adds/addu/subs/subu/bound patterns are
rewritten to replace the use of match_operator with iterators.

gcc:
* config/cris/cris.c (cris_select_cc_mode): Always return
CC_NZmode for matching comparisons.  Clarify comments.
* config/cris/cris-modes.def: Clarify mode comment.
* config/cris/cris.md (plusminus, plusminusumin, plusumin): New
code iterators.
(addsub, addsubbo, nd): New code iterator attributes.
("*<addsub><su>qihi"): Rename from "*extopqihi".  Use code
iterator constructs instead of match_operator constructs.
("*<addsubbo><su><nd><mode>si<setnz>"): Similar from
"*extop<mode>si<setnz>".
("*add<su>qihi_swap"): Similar from "*addxqihi_swap".
("*<addsubbo><su><nd><mode>si<setnz>_swap"): Similar from
"*extop<mode>si<setnz>_swap".

gcc/testsuite:
* gcc.target/cris/pr93372-39.c: New test.

gcc/config/cris/cris-modes.def
gcc/config/cris/cris.c
gcc/config/cris/cris.md
gcc/testsuite/gcc.target/cris/pr93372-39.c [new file with mode: 0644]

index 1aaf12a0f5ba04d6eed718aab6772c8157234651..874e4c19657e87db4e0d869b34c3cf06d3b741c9 100644 (file)
@@ -25,9 +25,10 @@ along with GCC; see the file COPYING3.  If not see
    have ordinary compares and incidental condition-code settings from
    preceding instructions, setting a subset of N, Z, V and C to usable
    values, from the perspective of comparing the result against zero
-   (fpcraz).  The two subsets meaningful to gcc are all of N, Z, V, C
-   versus just N, Z; some CC-users care only about N and/or Z and some
-   that care about at least one of those flags together with V and/or C.
+   (referred to below as "fpcraz").  The two subsets meaningful to gcc are
+   all of N, Z, V, C versus just N, Z; some CC-users care only about N
+   and/or Z and some that care about at least one of those flags together
+   with V and/or C.
 
    The plain "CC_MODE (CC)" (which is always present in gcc), is used to
    reflect the "unoptimized" state, where the CC-setter is a compare
@@ -37,9 +38,13 @@ along with GCC; see the file COPYING3.  If not see
    or if optimization of CC-setter and CC-users, when CCmode setters can
    be changed or replaced by either CC_NZmode or CC_NZVCmode.  To wit, all
    users that require CC_NZVCmode must match only that mode at any time.
-   All other users must match all CCmodes.  All setters that set only
-   CC_NZmode must set only that mode.  All other setters must match
-   setting all CCmodes.  */
+   All other users must match all of CCmode, CC_NZmode, and CC_NZVCmode.
+   All setters that set only CC_NZmode must match setting only that mode.
+   All other setters must match setting all of CCmode, CC_NZmode, and
+   CC_NZVCmode.
+
+   There's also other modes (i.e. CC_ZnNmode) with a separate set of
+   setters and users not matched by the others. */
 
 /* Z and N flags only.  For a condition-code setter: only the Z and N
    flags are set to usable values, fpcraz.  For a condition-code user: the
index 2bad9393c6ed8863756627b1c67b49152364213e..b26b9f2e883338c1157c5f0d0905c1c43177f6a6 100644 (file)
@@ -1530,21 +1530,11 @@ cris_select_cc_mode (enum rtx_code op, rtx x, rtx y)
   if (GET_MODE_CLASS (GET_MODE (x)) != MODE_INT || y != const0_rtx)
     return CCmode;
 
-  /* If we have a comparison that doesn't have to look at V or C, check
-     operand x; if it's a valid operator, return CC_NZmode, else CCmode,
-     so we only use CC_NZmode for the cases where we don't actually have
-     both V and C valid.  */
+  /* If we have a comparison that doesn't have to look at V or C, return
+     CC_NZmode.  */
   if (op == EQ || op ==  NE || op ==  GTU || op ==  LEU
       || op ==  LT || op ==  GE)
-    {
-      enum rtx_code e = GET_CODE (x);
-
-    /* Mentioning the rtx_code here is required but not sufficient: the
-       insn also needs to be decorated with <setnz> (and the
-       anonymization prefix <anz> for a named pattern).  */
-      return e == PLUS || e == MINUS || e == MULT || e == NOT || e == NEG
-       ? CC_NZmode : CCmode;
-    }
+    return CC_NZmode;
 
   /* We should only get here for comparison operators.  */
   gcc_assert (op ==  GEU || op ==  LTU || op ==  GT || op ==  LE);
index e700819d510f528a2b10f0190608af63b571bec5..ae6a27f5f2cb8f6659266b8e4e3d423ba834be07 100644 (file)
 (define_code_attr u [(sign_extend "") (zero_extend "u")])
 (define_code_attr su [(sign_extend "s") (zero_extend "u")])
 
+;; For extended-operand variants.
+(define_code_iterator plusminus [plus minus])
+(define_code_attr addsub [(plus "add") (minus "sub")])
+
+;; Similar, other cases also matching bound/umin.
+(define_code_iterator plusminusumin [plus minus umin])
+
+;; Ditto, commutative operators (i.e. not minus).
+(define_code_iterator plusumin [plus umin])
+
+;; The addsubbo and nd code-attributes form a hack.  We need to output
+;; "addu.b", "subu.b" but "bound.b" (no "u"-suffix) which means we'd
+;; need to refer to one iterator from the next.  But, that can't be
+;; done.  Instead output the "u" for unsigned as the "u" in "bound",
+;; i.e. the mnemonic as three parts including the extend-letter, and
+;; with an empty third part for "add" and "sub".
+(define_code_attr addsubbo [(plus "add") (minus "sub") (umin "bo")])
+(define_code_attr nd [(plus "") (minus "") (umin "nd")])
+
 ;; For the shift variants.
 (define_code_iterator shift [ashiftrt lshiftrt ashift])
 (define_code_iterator shiftrt [ashiftrt lshiftrt])
 ;; QImode to HImode
 ;; FIXME: GCC should widen.
 
-(define_insn "*extopqihi"
+(define_insn "*<addsub><su>qihi"
   [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
-       (match_operator:HI
-        3 "cris_additive_operand_extend_operator"
-        [(match_operand:HI 1 "register_operand" "0,0,0,r")
-         (match_operator:HI
-          4 "cris_extend_operator"
-          [(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")])]))
+       (plusminus:HI
+        (match_operand:HI 1 "register_operand" "0,0,0,r")
+        (szext:HI (match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To"))))
    (clobber (reg:CC CRIS_CC0_REGNUM))]
   "GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
-   && (operands[1] != frame_pointer_rtx || GET_CODE (operands[3]) != PLUS)"
+   && (operands[1] != frame_pointer_rtx || <plusminus:CODE> != PLUS)"
   "@
-   %x3%E4.%m4 %2,%0
-   %x3%E4.%m4 %2,%0
-   %x3%E4.%m4 %2,%0
-   %x3%E4.%m4 %2,%1,%0"
+   <addsub><su>.b %2,%0
+   <addsub><su>.b %2,%0
+   <addsub><su>.b %2,%0
+   <addsub><su>.b %2,%1,%0"
   [(set_attr "slottable" "yes,yes,no,no")
    (set_attr "cc" "clobber")])
 
-(define_insn "*extop<mode>si<setnz>"
+;; FIXME: bound is actually also <setnzvc>, but is so rarely used in this
+;; form that it's not worthwhile to make that distinction.
+(define_insn "*<addsubbo><su><nd><mode>si<setnz>"
   [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
-       (match_operator:SI
-        3 "cris_operand_extend_operator"
-        [(match_operand:SI 1 "register_operand" "0,0,0,r")
-         (match_operator:SI
-          4 "cris_extend_operator"
-          [(match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")])]))
-   (clobber (reg:CC CRIS_CC0_REGNUM))]
-  "(GET_CODE (operands[3]) != UMIN || GET_CODE (operands[4]) == ZERO_EXTEND)
-   && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
-   && (operands[1] != frame_pointer_rtx || GET_CODE (operands[3]) != PLUS)"
+       (plusminusumin:SI
+        (match_operand:SI 1 "register_operand" "0,0,0,r")
+        (szext:SI (match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To"))))
+   (clobber (reg:CC CRIS_CC0_REGNUM))]
+  "(<plusminusumin:CODE> != UMIN || <szext:CODE> == ZERO_EXTEND)
+   && (operands[1] != frame_pointer_rtx || <plusminusumin:CODE> != PLUS)"
   "@
-   %x3%E4<m> %2,%0
-   %x3%E4<m> %2,%0
-   %x3%E4<m> %2,%0
-   %x3%E4<m> %2,%1,%0"
+   <addsubbo><su><nd><m> %2,%0
+   <addsubbo><su><nd><m> %2,%0
+   <addsubbo><su><nd><m> %2,%0
+   <addsubbo><su><nd><m> %2,%1,%0"
   [(set_attr "slottable" "yes,yes,no,no")])
 \f
 ;; We may have swapped operands for add or bound.
 
 ;; QImode to HImode
 
-(define_insn "*addxqihi_swap"
+(define_insn "*add<su>qihi_swap"
   [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
        (plus:HI
-        (match_operator:HI
-         3 "cris_extend_operator"
-         [(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")])
+        (szext:HI (match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To"))
         (match_operand:HI 1 "register_operand" "0,0,0,r")))
    (clobber (reg:CC CRIS_CC0_REGNUM))]
   "operands[1] != frame_pointer_rtx"
   "@
-   add%e3.b %2,%0
-   add%e3.b %2,%0
-   add%e3.b %2,%0
-   add%e3.b %2,%1,%0"
+   add<su>.b %2,%0
+   add<su>.b %2,%0
+   add<su>.b %2,%0
+   add<su>.b %2,%1,%0"
   [(set_attr "slottable" "yes,yes,no,no")
    (set_attr "cc" "clobber")])
 
-(define_insn "*extop<mode>si<setnz>_swap"
+(define_insn "*<addsubbo><su><nd><mode>si<setnz>_swap"
   [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
-       (match_operator:SI
-        4 "cris_plus_or_bound_operator"
-        [(match_operator:SI
-          3 "cris_extend_operator"
-          [(match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")])
-         (match_operand:SI 1 "register_operand" "0,0,0,r")]))
-   (clobber (reg:CC CRIS_CC0_REGNUM))]
-  "(GET_CODE (operands[4]) != UMIN || GET_CODE (operands[3]) == ZERO_EXTEND)
+       (plusumin:SI
+        (szext:SI (match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To"))
+        (match_operand:SI 1 "register_operand" "0,0,0,r")))
+   (clobber (reg:CC CRIS_CC0_REGNUM))]
+  "(<plusumin:CODE> != UMIN || <szext:CODE> == ZERO_EXTEND)
    && operands[1] != frame_pointer_rtx"
   "@
-   %x4%E3<m> %2,%0
-   %x4%E3<m> %2,%0
-   %x4%E3<m> %2,%0
-   %x4%E3<m> %2,%1,%0"
+   <addsubbo><su><nd><m> %2,%0
+   <addsubbo><su><nd><m> %2,%0
+   <addsubbo><su><nd><m> %2,%0
+   <addsubbo><su><nd><m> %2,%1,%0"
   [(set_attr "slottable" "yes,yes,no,no")])
 \f
 ;; This is the special case when we use what corresponds to the
diff --git a/gcc/testsuite/gcc.target/cris/pr93372-39.c b/gcc/testsuite/gcc.target/cris/pr93372-39.c
new file mode 100644 (file)
index 0000000..6cc387f
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not {\tcmp|\ttest|\tmovu|\tmovs} } } */
+/* { dg-final { scan-assembler-times "\tbound.b" 1 } } */
+/* { dg-final { scan-assembler-times "\tbound.w" 1 } } */
+
+unsigned int ub (unsigned int a, unsigned char *b, int *c)
+{
+  unsigned int d = a < *b ? a : *b;
+  *c = d == 0;
+  return d;
+}
+
+unsigned int us (unsigned int a, unsigned short *b, int *c)
+{
+  unsigned int d = a < *b ? a : *b;
+  *c = d == 0;
+  return d;
+}