diff options
author | Hans-Peter Nilsson <hp@axis.com> | 2020-02-10 23:55:32 +0100 |
---|---|---|
committer | Hans-Peter Nilsson <hp@axis.com> | 2020-05-09 03:51:34 +0200 |
commit | b3e01c3d1b61ecc903b577920ca43804a2cb5497 (patch) | |
tree | 21db75d825f0d3a52c1b992d7ff2f73c0348fc2d /gcc/config/cris/cris.c | |
parent | 12bdaa7d3e94cf30f8ce1750325a245175bdbee5 (diff) | |
download | gcc-b3e01c3d1b61ecc903b577920ca43804a2cb5497.tar.gz |
cris: Introduce CC_NZVCmode and CC_NZmode.
This is just the framework bits of splitting CCmode into classes
where the cc-setter can merge mode (CCmode), classes where the
cc-setter must set V and C "usefully" (as well as N and Z flags)
and classes where the cc-setter is something like an arithmetic
instruction, where N and Z are valid but C and V reflect the
operation rather than a compare of the result with zero. This
should yield identical or near-identical code.
The old split of conditions into the ncond and ocond sets took
into account the transformations done by final.c:alter_cond from
cc_status.flags & CC_NO_OVERFLOW, and wasn't a reflection of the
hardware description of the conditions (i.e. whether V mattered
or not).
gcc:
Prepare for cmpelim pass to eliminate redundant compare insns.
* config/cris/cris-modes.def: New file.
* config/cris/cris-protos.h (cris_select_cc_mode): Declare.
(cris_notice_update_cc): Remove left-over declaration.
* config/cris/cris.c (TARGET_CC_MODES_COMPATIBLE): Define.
(cris_select_cc_mode, cris_cc_modes_compatible): New functions.
* config/cris/cris.h (SELECT_CC_MODE): Define.
* config/cris/cris.md (NZSET, NZUSE, NZVCSET, NZVCUSE): New
mode_iterators.
(cond): New code_iterator.
(nzcond): Replacement for incorrect ncond. All callers changed.
(nzvccond): Replacement for ocond. All callers changed.
(rnzcond): Replacement for rcond. All callers changed.
(xCC): New code_attr.
(cmp_op1c, cmp_op0c): Renumber from cmp_op1c and cmp_op2c. All
users changed.
("*cmpdi<NZVCSET:mode>"): Rename from "*cmpdi". Replace
CCmode with iteration over NZVCSET.
("*cmp_ext<BW:mode><NZVCSET:mode>"): Similarly; rename from
"*cmp_ext<mode>".
("*cmpsi<NZVCSET:mode>"): Similarly, from "*cmpsi".
("*cmp<BW:mode><NZVCSET:mode>"): Similarly from "*cmp<mode>".
("*btst<mode>"): Similarly, from "*btst".
("*cbranch<mode><code>4"): Rename from "*cbranch<mode>4",
iterating over cond instead of matching the comparison with
ordered_comparison_operator.
("*cbranch<mode>4_btstq<CC>"): Correct label operand number.
("b<zcond:code><mode>"): Rename from "b<ncond:code>", iterating
over NZUSE.
("b<nzvccond:code><mode>"): Similarly from "b<ocond:code>", over
NZVCUSE. Remove FIXME.
("*b<nzcond:code>_reversed<mode>"): Similarly from
"*b<ncond:code>_reversed", over NZUSE.
("*b<nzvccond:code>_reversed<mode>"): Similarly from
"*b<ocond:code>_reversed", over NZVCUSE. Remove FIXME.
("b<rnzcond:code><mode>"): Similarly from "b<rcond:code>",
over NZUSE. Reinstate "b<oCC>" vs. "b<CC>" mnemonic choice,
depending on CC_NZmode vs. CCmode. Remove FIXME.
("*b<rnzcond:code>_reversed<mode>"): Similarly from
"*b<rcond:code>_reversed", over NZUSE.
("*cstore<mode><code>4"): Rename from "*cstore<mode>4",
iterating over cond instead of matching the comparison with
ordered_comparison_operator.
("*s<nzcond:code><mode>"): Rename from "*s<ncond:code>",
iterating over NZUSE.
("*s<rnzcond:code><mode>"): Similar from "*s<rcond:code>", over
NZUSE. Reinstate "b<oCC>" vs. "b<CC>" mnemonic choice,
depending on CC_NZmode vs. CCmode.
("*s<nzvccond:code><mode>"): Simlar from "*s<ocond:code>", over
NZVCUSE. Remove FIXME.
Diffstat (limited to 'gcc/config/cris/cris.c')
-rw-r--r-- | gcc/config/cris/cris.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c index eecda83845c..04c80c314a3 100644 --- a/gcc/config/cris/cris.c +++ b/gcc/config/cris/cris.c @@ -133,6 +133,7 @@ static reg_class_t cris_preferred_reload_class (rtx, reg_class_t); static int cris_register_move_cost (machine_mode, reg_class_t, reg_class_t); static int cris_memory_move_cost (machine_mode, reg_class_t, bool); +static machine_mode cris_cc_modes_compatible (machine_mode, machine_mode); static bool cris_rtx_costs (rtx, machine_mode, int, int, int *, bool); static int cris_address_cost (rtx, machine_mode, addr_space_t, bool); static bool cris_pass_by_reference (cumulative_args_t, @@ -226,6 +227,9 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION; nothing. Beware of changes to its usage; it may make sense to enable "later". */ +#undef TARGET_CC_MODES_COMPATIBLE +#define TARGET_CC_MODES_COMPATIBLE cris_cc_modes_compatible + #undef TARGET_FLAGS_REGNUM #define TARGET_FLAGS_REGNUM CRIS_CC0_REGNUM @@ -1509,6 +1513,73 @@ cris_memory_move_cost (machine_mode mode, return 6; } +/* Worker function for SELECT_CC_MODE. */ + +machine_mode +cris_select_cc_mode (enum rtx_code op, rtx x, rtx y) +{ + /* We have different sets of patterns before and after + reload_completed, and everything before reload_completed is CCmode. + At the time of this writing, this function isn't called before that + time, so let's just gcc_assert on that assumption rather than doing + "if (!reload_completed) return CCmode;". */ + gcc_assert (reload_completed); + + /* For float mode or comparisons with something other than 0, we + always go with CCmode. */ + 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 looks like a binary 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 (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 + ? CC_NZmode : CCmode; + } + + /* We should only get here for comparison operators. */ + gcc_assert (op == GEU || op == LTU || op == GT || op == LE); + + return CC_NZVCmode; +} + +/* Worker function for TARGET_CC_MODES_COMPATIBLE. + We start with CCmode for most comparisons, which merges and yields to + CC_NZmode or CC_NZVCmode. The exceptions have CC_NZVCmode and can't do with + another mode. */ + +static machine_mode +cris_cc_modes_compatible (machine_mode m1, machine_mode m2) +{ + if (m1 == CC_NZVCmode) + { + if (m2 == CC_NZVCmode || m2 == CCmode) + return CC_NZVCmode; + return VOIDmode; + } + + if (m2 == CC_NZVCmode) + { + if (m1 == CC_NZVCmode || m1 == CCmode) + return CC_NZVCmode; + return VOIDmode; + } + + if (m1 != m2) + return CC_NZmode; + + return m1; +} + /* Return != 0 if the return sequence for the current function is short, like "ret" or "jump [sp+]". Prior to reloading, we can't tell if registers must be saved, so return 0 then. */ |