From 9596eccb9c64faa13750692b46dd0779aac0d57c Mon Sep 17 00:00:00 2001 From: Hans-Peter Nilsson Date: Mon, 6 Jul 2020 01:10:54 +0200 Subject: [PATCH] cris: update recent patterns. Simplify cris_select_cc_mode. 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. ("*qihi"): Rename from "*extopqihi". Use code iterator constructs instead of match_operator constructs. ("*si"): Similar from "*extopsi". ("*addqihi_swap"): Similar from "*addxqihi_swap". ("*si_swap"): Similar from "*extopsi_swap". gcc/testsuite: * gcc.target/cris/pr93372-39.c: New test. --- gcc/config/cris/cris-modes.def | 17 ++-- gcc/config/cris/cris.c | 16 +--- gcc/config/cris/cris.md | 105 +++++++++++---------- gcc/testsuite/gcc.target/cris/pr93372-39.c | 19 ++++ 4 files changed, 90 insertions(+), 67 deletions(-) create mode 100644 gcc/testsuite/gcc.target/cris/pr93372-39.c diff --git a/gcc/config/cris/cris-modes.def b/gcc/config/cris/cris-modes.def index 1aaf12a0f5b..874e4c19657 100644 --- a/gcc/config/cris/cris-modes.def +++ b/gcc/config/cris/cris-modes.def @@ -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 diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c index 2bad9393c6e..b26b9f2e883 100644 --- a/gcc/config/cris/cris.c +++ b/gcc/config/cris/cris.c @@ -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 (and the - anonymization prefix 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); diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md index e700819d510..ae6a27f5f2c 100644 --- a/gcc/config/cris/cris.md +++ b/gcc/config/cris/cris.md @@ -183,6 +183,25 @@ (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]) @@ -1113,42 +1132,37 @@ ;; QImode to HImode ;; FIXME: GCC should widen. -(define_insn "*extopqihi" +(define_insn "*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 || != PLUS)" "@ - %x3%E4.%m4 %2,%0 - %x3%E4.%m4 %2,%0 - %x3%E4.%m4 %2,%0 - %x3%E4.%m4 %2,%1,%0" + .b %2,%0 + .b %2,%0 + .b %2,%0 + .b %2,%1,%0" [(set_attr "slottable" "yes,yes,no,no") (set_attr "cc" "clobber")]) -(define_insn "*extopsi" +;; FIXME: bound is actually also , but is so rarely used in this +;; form that it's not worthwhile to make that distinction. +(define_insn "*si" [(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))] + "( != UMIN || == ZERO_EXTEND) + && (operands[1] != frame_pointer_rtx || != PLUS)" "@ - %x3%E4 %2,%0 - %x3%E4 %2,%0 - %x3%E4 %2,%0 - %x3%E4 %2,%1,%0" + %2,%0 + %2,%0 + %2,%0 + %2,%1,%0" [(set_attr "slottable" "yes,yes,no,no")]) ;; We may have swapped operands for add or bound. @@ -1156,39 +1170,34 @@ ;; QImode to HImode -(define_insn "*addxqihi_swap" +(define_insn "*addqihi_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.b %2,%0 + add.b %2,%0 + add.b %2,%0 + add.b %2,%1,%0" [(set_attr "slottable" "yes,yes,no,no") (set_attr "cc" "clobber")]) -(define_insn "*extopsi_swap" +(define_insn "*si_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))] + "( != UMIN || == ZERO_EXTEND) && operands[1] != frame_pointer_rtx" "@ - %x4%E3 %2,%0 - %x4%E3 %2,%0 - %x4%E3 %2,%0 - %x4%E3 %2,%1,%0" + %2,%0 + %2,%0 + %2,%0 + %2,%1,%0" [(set_attr "slottable" "yes,yes,no,no")]) ;; 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 index 00000000000..6cc387fd794 --- /dev/null +++ b/gcc/testsuite/gcc.target/cris/pr93372-39.c @@ -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; +} -- 2.30.2