summaryrefslogtreecommitdiff
path: root/gcc/config/cris/cris.c
diff options
context:
space:
mode:
authorHans-Peter Nilsson <hp@axis.com>2020-02-10 23:55:32 +0100
committerHans-Peter Nilsson <hp@axis.com>2020-05-09 03:51:34 +0200
commitb3e01c3d1b61ecc903b577920ca43804a2cb5497 (patch)
tree21db75d825f0d3a52c1b992d7ff2f73c0348fc2d /gcc/config/cris/cris.c
parent12bdaa7d3e94cf30f8ce1750325a245175bdbee5 (diff)
downloadgcc-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.c71
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. */