Mercurial > hg > CbC > CbC_gcc
diff gcc/lower-subreg.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/lower-subreg.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/lower-subreg.c Thu Oct 25 07:37:49 2018 +0900 @@ -1,5 +1,5 @@ /* Decompose multiword subregs. - Copyright (C) 2007-2017 Free Software Foundation, Inc. + Copyright (C) 2007-2018 Free Software Foundation, Inc. Contributed by Richard Henderson <rth@redhat.com> Ian Lance Taylor <iant@google.com> @@ -103,6 +103,19 @@ #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) +{ + if (!GET_MODE_SIZE (mode).is_constant (bytes)) + return false; + *words = CEIL (*bytes, UNITS_PER_WORD); + return true; +} + /* RTXes used while computing costs. */ struct cost_rtxes { /* Source and target registers. */ @@ -129,7 +142,7 @@ PUT_CODE (rtxes->shift, code); PUT_MODE (rtxes->shift, mode); PUT_MODE (rtxes->source, mode); - XEXP (rtxes->shift, 1) = GEN_INT (op1); + XEXP (rtxes->shift, 1) = gen_int_shift_amount (mode, op1); return set_src_cost (rtxes->shift, mode, speed_p); } @@ -199,10 +212,10 @@ 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 +482,10 @@ 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 @@ -484,7 +497,16 @@ were the same number and size of pieces. Hopefully this doesn't happen much. */ - if (outer_words == 1 && inner_words > 1) + if (outer_words == 1 + && inner_words > 1 + /* Don't allow to decompose floating point subregs of + multi-word pseudos if the floating point mode does + not have word size, because otherwise we'd generate + a subreg with that floating mode from a different + sized integral pseudo which is not allowed by + validate_subreg. */ + && (!FLOAT_MODE_P (GET_MODE (x)) + || outer_size == UNITS_PER_WORD)) { bitmap_set_bit (decomposable_context, regno); iter.skip_subrtxes (); @@ -507,7 +529,7 @@ } 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 +549,8 @@ 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 +590,15 @@ 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) @@ -596,28 +619,34 @@ /* Get a SUBREG of a CONCATN. */ static rtx -simplify_subreg_concatn (machine_mode outermode, rtx op, - unsigned int byte) +simplify_subreg_concatn (machine_mode outermode, rtx op, poly_uint64 orig_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; - - gcc_assert (GET_CODE (op) == CONCATN); - gcc_assert (byte % GET_MODE_SIZE (outermode) == 0); + unsigned int byte; innermode = GET_MODE (op); - gcc_assert (byte < GET_MODE_SIZE (innermode)); - if (GET_MODE_SIZE (outermode) > GET_MODE_SIZE (innermode)) + if (!interesting_mode_p (outermode, &outer_size, &outer_words) + || !interesting_mode_p (innermode, &inner_size, &inner_words)) + gcc_unreachable (); + + /* Must be constant if interesting_mode_p passes. */ + byte = orig_byte.to_constant (); + gcc_assert (GET_CODE (op) == CONCATN); + gcc_assert (byte % outer_size == 0); + + 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 @@ -648,9 +677,9 @@ { rtx op2; - if ((GET_MODE_SIZE (GET_MODE (op)) - == GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))) - && SUBREG_BYTE (op) == 0) + if (known_eq (GET_MODE_SIZE (GET_MODE (op)), + GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))) + && known_eq (SUBREG_BYTE (op), 0)) return simplify_gen_subreg_concatn (outermode, SUBREG_REG (op), GET_MODE (SUBREG_REG (op)), byte); @@ -801,9 +830,10 @@ 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 +856,15 @@ 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 (); @@ -847,9 +878,8 @@ if (GET_CODE (src) == SUBREG && resolve_reg_p (SUBREG_REG (src)) - && (SUBREG_BYTE (src) != 0 - || (GET_MODE_SIZE (orig_mode) - != GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))))) + && (maybe_ne (SUBREG_BYTE (src), 0) + || maybe_ne (orig_size, GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))))) { real_dest = dest; dest = gen_reg_rtx (orig_mode); @@ -862,9 +892,9 @@ if (GET_CODE (dest) == SUBREG && resolve_reg_p (SUBREG_REG (dest)) - && (SUBREG_BYTE (dest) != 0 - || (GET_MODE_SIZE (orig_mode) - != GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))))) + && (maybe_ne (SUBREG_BYTE (dest), 0) + || maybe_ne (orig_size, + GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))))) { rtx reg, smove; rtx_insn *minsn; @@ -964,7 +994,7 @@ { 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 +1089,7 @@ { rtx reg; machine_mode orig_mode; - unsigned int words, i; + unsigned int orig_size, words, i; int ret; reg = XEXP (pat, 0); @@ -1067,8 +1097,8 @@ 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 +1362,13 @@ 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"