From 8536340f4930c47a5b444da1a2d3ad21519b5676 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Wed, 1 Nov 2017 13:51:28 +0000 Subject: [PATCH] Factor out the mode handling in lower-subreg.c This patch adds a helper routine (interesting_mode_p) to lower-subreg.c, to make the decision about whether a mode can be split and, if so, calculate the number of bytes and words in the mode. At present this function always returns true; a later patch will add cases in which it can return false. 2017-11-01 Richard Sandiford Alan Hayward David Sherwood gcc/ * lower-subreg.c (interesting_mode_p): New function. (compute_costs, find_decomposable_subregs, decompose_register) (simplify_subreg_concatn, can_decompose_p, resolve_simple_move) (resolve_clobber, dump_choices): Use it. Co-Authored-By: Alan Hayward Co-Authored-By: David Sherwood From-SVN: r254308 --- gcc/ChangeLog | 9 ++++++ gcc/lower-subreg.c | 78 +++++++++++++++++++++++++++++----------------- 2 files changed, 58 insertions(+), 29 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2d390a01e04..d997cac3b20 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2017-11-01 Richard Sandiford + Alan Hayward + David Sherwood + + * lower-subreg.c (interesting_mode_p): New function. + (compute_costs, find_decomposable_subregs, decompose_register) + (simplify_subreg_concatn, can_decompose_p, resolve_simple_move) + (resolve_clobber, dump_choices): Use it. + 2017-11-01 Richard Sandiford Alan Hayward David Sherwood diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c index e34746b3fe4..466b4bfd93d 100644 --- a/gcc/lower-subreg.c +++ b/gcc/lower-subreg.c @@ -103,6 +103,18 @@ struct target_lower_subreg *this_target_lower_subreg #define choices \ this_target_lower_subreg->x_choices +/* Return true if MODE is a mode we know how to lower. When returning true, + store its byte size in *BYTES and its word size in *WORDS. */ + +static inline bool +interesting_mode_p (machine_mode mode, unsigned int *bytes, + unsigned int *words) +{ + *bytes = GET_MODE_SIZE (mode); + *words = CEIL (*bytes, UNITS_PER_WORD); + return true; +} + /* RTXes used while computing costs. */ struct cost_rtxes { /* Source and target registers. */ @@ -199,10 +211,10 @@ compute_costs (bool speed_p, struct cost_rtxes *rtxes) for (i = 0; i < MAX_MACHINE_MODE; i++) { machine_mode mode = (machine_mode) i; - int factor = GET_MODE_SIZE (mode) / UNITS_PER_WORD; - if (factor > 1) + unsigned int size, factor; + if (interesting_mode_p (mode, &size, &factor) && factor > 1) { - int mode_move_cost; + unsigned int mode_move_cost; PUT_MODE (rtxes->target, mode); PUT_MODE (rtxes->source, mode); @@ -469,10 +481,10 @@ find_decomposable_subregs (rtx *loc, enum classify_move_insn *pcmi) continue; } - outer_size = GET_MODE_SIZE (GET_MODE (x)); - inner_size = GET_MODE_SIZE (GET_MODE (inner)); - outer_words = (outer_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; - inner_words = (inner_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; + if (!interesting_mode_p (GET_MODE (x), &outer_size, &outer_words) + || !interesting_mode_p (GET_MODE (inner), &inner_size, + &inner_words)) + continue; /* We only try to decompose single word subregs of multi-word registers. When we find one, we return -1 to avoid iterating @@ -507,7 +519,7 @@ find_decomposable_subregs (rtx *loc, enum classify_move_insn *pcmi) } else if (REG_P (x)) { - unsigned int regno; + unsigned int regno, size, words; /* We will see an outer SUBREG before we see the inner REG, so when we see a plain REG here it means a direct reference to @@ -527,7 +539,8 @@ find_decomposable_subregs (rtx *loc, enum classify_move_insn *pcmi) regno = REGNO (x); if (!HARD_REGISTER_NUM_P (regno) - && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD) + && interesting_mode_p (GET_MODE (x), &size, &words) + && words > 1) { switch (*pcmi) { @@ -567,15 +580,15 @@ static void decompose_register (unsigned int regno) { rtx reg; - unsigned int words, i; + unsigned int size, words, i; rtvec v; reg = regno_reg_rtx[regno]; regno_reg_rtx[regno] = NULL_RTX; - words = GET_MODE_SIZE (GET_MODE (reg)); - words = (words + UNITS_PER_WORD - 1) / UNITS_PER_WORD; + if (!interesting_mode_p (GET_MODE (reg), &size, &words)) + gcc_unreachable (); v = rtvec_alloc (words); for (i = 0; i < words; ++i) @@ -599,25 +612,29 @@ static rtx simplify_subreg_concatn (machine_mode outermode, rtx op, unsigned int byte) { - unsigned int inner_size; + unsigned int outer_size, outer_words, inner_size, inner_words; machine_mode innermode, partmode; rtx part; unsigned int final_offset; + innermode = GET_MODE (op); + if (!interesting_mode_p (outermode, &outer_size, &outer_words) + || !interesting_mode_p (innermode, &inner_size, &inner_words)) + gcc_unreachable (); + gcc_assert (GET_CODE (op) == CONCATN); - gcc_assert (byte % GET_MODE_SIZE (outermode) == 0); + gcc_assert (byte % outer_size == 0); - innermode = GET_MODE (op); - gcc_assert (byte < GET_MODE_SIZE (innermode)); - if (GET_MODE_SIZE (outermode) > GET_MODE_SIZE (innermode)) + gcc_assert (byte < inner_size); + if (outer_size > inner_size) return NULL_RTX; - inner_size = GET_MODE_SIZE (innermode) / XVECLEN (op, 0); + inner_size /= XVECLEN (op, 0); part = XVECEXP (op, 0, byte / inner_size); partmode = GET_MODE (part); final_offset = byte % inner_size; - if (final_offset + GET_MODE_SIZE (outermode) > inner_size) + if (final_offset + outer_size > inner_size) return NULL_RTX; /* VECTOR_CSTs in debug expressions are expanded into CONCATN instead of @@ -801,9 +818,10 @@ can_decompose_p (rtx x) if (HARD_REGISTER_NUM_P (regno)) { - unsigned int byte, num_bytes; + unsigned int byte, num_bytes, num_words; - num_bytes = GET_MODE_SIZE (GET_MODE (x)); + if (!interesting_mode_p (GET_MODE (x), &num_bytes, &num_words)) + return false; for (byte = 0; byte < num_bytes; byte += UNITS_PER_WORD) if (simplify_subreg_regno (regno, GET_MODE (x), byte, word_mode) < 0) return false; @@ -826,14 +844,15 @@ resolve_simple_move (rtx set, rtx_insn *insn) rtx src, dest, real_dest; rtx_insn *insns; machine_mode orig_mode, dest_mode; - unsigned int words; + unsigned int orig_size, words; bool pushing; src = SET_SRC (set); dest = SET_DEST (set); orig_mode = GET_MODE (dest); - words = (GET_MODE_SIZE (orig_mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; + if (!interesting_mode_p (orig_mode, &orig_size, &words)) + gcc_unreachable (); gcc_assert (words > 1); start_sequence (); @@ -964,7 +983,7 @@ resolve_simple_move (rtx set, rtx_insn *insn) { unsigned int i, j, jinc; - gcc_assert (GET_MODE_SIZE (orig_mode) % UNITS_PER_WORD == 0); + gcc_assert (orig_size % UNITS_PER_WORD == 0); gcc_assert (GET_CODE (XEXP (dest, 0)) != PRE_MODIFY); gcc_assert (GET_CODE (XEXP (dest, 0)) != POST_MODIFY); @@ -1059,7 +1078,7 @@ resolve_clobber (rtx pat, rtx_insn *insn) { rtx reg; machine_mode orig_mode; - unsigned int words, i; + unsigned int orig_size, words, i; int ret; reg = XEXP (pat, 0); @@ -1067,8 +1086,8 @@ resolve_clobber (rtx pat, rtx_insn *insn) return false; orig_mode = GET_MODE (reg); - words = GET_MODE_SIZE (orig_mode); - words = (words + UNITS_PER_WORD - 1) / UNITS_PER_WORD; + if (!interesting_mode_p (orig_mode, &orig_size, &words)) + gcc_unreachable (); ret = validate_change (NULL_RTX, &XEXP (pat, 0), simplify_gen_subreg_concatn (word_mode, reg, @@ -1332,12 +1351,13 @@ dump_shift_choices (enum rtx_code code, bool *splitting) static void dump_choices (bool speed_p, const char *description) { - unsigned int i; + unsigned int size, factor, i; fprintf (dump_file, "Choices when optimizing for %s:\n", description); for (i = 0; i < MAX_MACHINE_MODE; i++) - if (GET_MODE_SIZE ((machine_mode) i) > UNITS_PER_WORD) + if (interesting_mode_p ((machine_mode) i, &size, &factor) + && factor > 1) fprintf (dump_file, " %s mode %s for copy lowering.\n", choices[speed_p].move_modes_to_split[i] ? "Splitting" -- 2.30.2