diff options
author | Oleg Endo <olegendo@gcc.gnu.org> | 2014-05-03 09:42:52 +0000 |
---|---|---|
committer | Oleg Endo <olegendo@gcc.gnu.org> | 2014-05-03 09:42:52 +0000 |
commit | f6982a08ca633c0168be0b7700884a3ae7f161a3 (patch) | |
tree | 1b456e93876262373707f1e2e15e67d7197477cf | |
parent | 3c922bcd25f3876ada4160e5109e27923f3828a2 (diff) | |
download | gcc-f6982a08ca633c0168be0b7700884a3ae7f161a3.zip gcc-f6982a08ca633c0168be0b7700884a3ae7f161a3.tar.gz gcc-f6982a08ca633c0168be0b7700884a3ae7f161a3.tar.bz2 |
sh.h (ROUND_ADVANCE): Delete macro.
* config/sh/sh.h (ROUND_ADVANCE): Delete macro.
(ROUND_REG, PASS_IN_REG_P): Move and rename macros to ...
* config/sh/sh.c (sh_round_reg, sh_pass_in_reg_p): ... these new
functions.
(sh_arg_partial_bytes, sh_function_arg, sh_function_arg_advance,
sh_setup_incoming_varargs): Replace usage of PASS_IN_REG_P with
sh_pass_in_reg_p.
Replace usage of ROUND_REG with sh_round_reg.
Use CEIL instead of ROUND_ADVANCE.
From-SVN: r210032
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 86 | ||||
-rw-r--r-- | gcc/config/sh/sh.h | 39 |
3 files changed, 79 insertions, 58 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 92812c5..6464565 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,17 @@ 2014-05-03 Oleg Endo <olegendo@gcc.gnu.org> + * config/sh/sh.h (ROUND_ADVANCE): Delete macro. + (ROUND_REG, PASS_IN_REG_P): Move and rename macros to ... + * config/sh/sh.c (sh_round_reg, sh_pass_in_reg_p): ... these new + functions. + (sh_arg_partial_bytes, sh_function_arg, sh_function_arg_advance, + sh_setup_incoming_varargs): Replace usage of PASS_IN_REG_P with + sh_pass_in_reg_p. + Replace usage of ROUND_REG with sh_round_reg. + Use CEIL instead of ROUND_ADVANCE. + +2014-05-03 Oleg Endo <olegendo@gcc.gnu.org> + PR target/61026 * config/sh/sh.c: Include stdlib headers before everything else. diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 12724a2..26a5d79 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -8809,6 +8809,54 @@ sh_callee_copies (cumulative_args_t cum, enum machine_mode mode, % SH_MIN_ALIGN_FOR_CALLEE_COPY == 0)); } +/* Round a register number up to a proper boundary for an arg of mode + MODE. + The SH doesn't care about double alignment, so we only + round doubles to even regs when asked to explicitly. */ +static int +sh_round_reg (const CUMULATIVE_ARGS& cum, machine_mode mode) +{ + /* FIXME: This used to be a macro and has been copy pasted into this + function as is. Make this more readable. */ + return + (((TARGET_ALIGN_DOUBLE + || ((TARGET_SH4 || TARGET_SH2A_DOUBLE) + && (mode == DFmode || mode == DCmode) + && cum.arg_count[(int) SH_ARG_FLOAT] < NPARM_REGS (mode))) + && GET_MODE_UNIT_SIZE (mode) > UNITS_PER_WORD) + ? (cum.arg_count[(int) GET_SH_ARG_CLASS (mode)] + + (cum.arg_count[(int) GET_SH_ARG_CLASS (mode)] & 1)) + : cum.arg_count[(int) GET_SH_ARG_CLASS (mode)]); +} + +/* Return true if arg of the specified mode should be be passed in a register + or false otherwise. */ +static bool +sh_pass_in_reg_p (const CUMULATIVE_ARGS& cum, machine_mode mode, + const_tree type) +{ + /* FIXME: This used to be a macro and has been copy pasted into this + function as is. Make this more readable. */ + return + ((type == 0 + || (! TREE_ADDRESSABLE (type) + && (! (TARGET_HITACHI || cum.renesas_abi) + || ! (AGGREGATE_TYPE_P (type) + || (!TARGET_FPU_ANY + && (GET_MODE_CLASS (mode) == MODE_FLOAT + && GET_MODE_SIZE (mode) > GET_MODE_SIZE (SFmode))))))) + && ! cum.force_mem + && (TARGET_SH2E + ? ((mode) == BLKmode + ? ((cum.arg_count[(int) SH_ARG_INT] * UNITS_PER_WORD + + int_size_in_bytes (type)) + <= NPARM_REGS (SImode) * UNITS_PER_WORD) + : ((sh_round_reg (cum, mode) + + HARD_REGNO_NREGS (BASE_ARG_REG (mode), mode)) + <= NPARM_REGS (mode))) + : sh_round_reg (cum, mode) < NPARM_REGS (mode))); +} + static int sh_arg_partial_bytes (cumulative_args_t cum_v, enum machine_mode mode, tree type, bool named ATTRIBUTE_UNUSED) @@ -8817,14 +8865,14 @@ sh_arg_partial_bytes (cumulative_args_t cum_v, enum machine_mode mode, int words = 0; if (!TARGET_SH5 - && PASS_IN_REG_P (*cum, mode, type) + && sh_pass_in_reg_p (*cum, mode, type) && !(TARGET_SH4 || TARGET_SH2A_DOUBLE) - && (ROUND_REG (*cum, mode) + && (sh_round_reg (*cum, mode) + (mode != BLKmode - ? ROUND_ADVANCE (GET_MODE_SIZE (mode)) - : ROUND_ADVANCE (int_size_in_bytes (type))) + ? CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD) + : CEIL (int_size_in_bytes (type), UNITS_PER_WORD)) > NPARM_REGS (mode))) - words = NPARM_REGS (mode) - ROUND_REG (*cum, mode); + words = NPARM_REGS (mode) - sh_round_reg (*cum, mode); else if (!TARGET_SHCOMPACT && SH5_WOULD_BE_PARTIAL_NREGS (*cum, mode, type, named)) @@ -8861,23 +8909,23 @@ sh_function_arg (cumulative_args_t ca_v, enum machine_mode mode, return GEN_INT (ca->renesas_abi ? 1 : 0); if (! TARGET_SH5 - && PASS_IN_REG_P (*ca, mode, type) + && sh_pass_in_reg_p (*ca, mode, type) && (named || ! (TARGET_HITACHI || ca->renesas_abi))) { int regno; if (mode == SCmode && TARGET_SH4 && TARGET_LITTLE_ENDIAN - && (! FUNCTION_ARG_SCmode_WART || (ROUND_REG (*ca, mode) & 1))) + && (! FUNCTION_ARG_SCmode_WART || (sh_round_reg (*ca, mode) & 1))) { rtx r1 = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (SFmode, BASE_ARG_REG (mode) - + (ROUND_REG (*ca, mode) ^ 1)), + + (sh_round_reg (*ca, mode) ^ 1)), const0_rtx); rtx r2 = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (SFmode, BASE_ARG_REG (mode) - + ((ROUND_REG (*ca, mode) + 1) ^ 1)), + + ((sh_round_reg (*ca, mode) + 1) ^ 1)), GEN_INT (4)); return gen_rtx_PARALLEL(SCmode, gen_rtvec(2, r1, r2)); } @@ -8890,7 +8938,7 @@ sh_function_arg (cumulative_args_t ca_v, enum machine_mode mode, && mode == SFmode) return gen_rtx_REG (mode, ca->free_single_fp_reg); - regno = (BASE_ARG_REG (mode) + ROUND_REG (*ca, mode)) + regno = (BASE_ARG_REG (mode) + sh_round_reg (*ca, mode)) ^ (mode == SFmode && TARGET_SH4 && TARGET_LITTLE_ENDIAN && ! TARGET_HITACHI && ! ca->renesas_abi); @@ -9070,20 +9118,20 @@ sh_function_arg_advance (cumulative_args_t ca_v, enum machine_mode mode, register, because the next SF value will use it, and not the SF that follows the DF. */ if (mode == DFmode - && ROUND_REG (*ca, DFmode) != ROUND_REG (*ca, SFmode)) + && sh_round_reg (*ca, DFmode) != sh_round_reg (*ca, SFmode)) { - ca->free_single_fp_reg = (ROUND_REG (*ca, SFmode) + ca->free_single_fp_reg = (sh_round_reg (*ca, SFmode) + BASE_ARG_REG (mode)); } } if (! ((TARGET_SH4 || TARGET_SH2A) || ca->renesas_abi) - || PASS_IN_REG_P (*ca, mode, type)) + || sh_pass_in_reg_p (*ca, mode, type)) (ca->arg_count[(int) GET_SH_ARG_CLASS (mode)] - = (ROUND_REG (*ca, mode) + = (sh_round_reg (*ca, mode) + (mode == BLKmode - ? ROUND_ADVANCE (int_size_in_bytes (type)) - : ROUND_ADVANCE (GET_MODE_SIZE (mode))))); + ? CEIL (int_size_in_bytes (type), UNITS_PER_WORD) + : CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD)))); } /* The Renesas calling convention doesn't quite fit into this scheme since @@ -9178,10 +9226,10 @@ sh_setup_incoming_varargs (cumulative_args_t ca, { int named_parm_regs, anon_parm_regs; - named_parm_regs = (ROUND_REG (*get_cumulative_args (ca), mode) + named_parm_regs = (sh_round_reg (*get_cumulative_args (ca), mode) + (mode == BLKmode - ? ROUND_ADVANCE (int_size_in_bytes (type)) - : ROUND_ADVANCE (GET_MODE_SIZE (mode)))); + ? CEIL (int_size_in_bytes (type), UNITS_PER_WORD) + : CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD))); anon_parm_regs = NPARM_REGS (SImode) - named_parm_regs; if (anon_parm_regs > 0) *pretend_arg_size = anon_parm_regs * 4; diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 8c30e5c..0b6bd1b 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -1361,24 +1361,6 @@ struct sh_args { || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \ ? SH_ARG_FLOAT : SH_ARG_INT) -#define ROUND_ADVANCE(SIZE) \ - (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* Round a register number up to a proper boundary for an arg of mode - MODE. - - The SH doesn't care about double alignment, so we only - round doubles to even regs when asked to explicitly. */ -#define ROUND_REG(CUM, MODE) \ - (((TARGET_ALIGN_DOUBLE \ - || ((TARGET_SH4 || TARGET_SH2A_DOUBLE) \ - && ((MODE) == DFmode || (MODE) == DCmode) \ - && (CUM).arg_count[(int) SH_ARG_FLOAT] < NPARM_REGS (MODE))) \ - && GET_MODE_UNIT_SIZE ((MODE)) > UNITS_PER_WORD) \ - ? ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)] \ - + ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)] & 1)) \ - : (CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)]) - /* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE. For a library call, FNTYPE is 0. @@ -1394,27 +1376,6 @@ struct sh_args { #define INIT_CUMULATIVE_LIBCALL_ARGS(CUM, MODE, LIBNAME) \ sh_init_cumulative_args (& (CUM), NULL_TREE, (LIBNAME), NULL_TREE, 0, (MODE)) -/* Return boolean indicating arg of mode MODE will be passed in a reg. - This macro is only used in this file. */ -#define PASS_IN_REG_P(CUM, MODE, TYPE) \ - (((TYPE) == 0 \ - || (! TREE_ADDRESSABLE ((TYPE)) \ - && (! (TARGET_HITACHI || (CUM).renesas_abi) \ - || ! (AGGREGATE_TYPE_P (TYPE) \ - || (!TARGET_FPU_ANY \ - && (GET_MODE_CLASS (MODE) == MODE_FLOAT \ - && GET_MODE_SIZE (MODE) > GET_MODE_SIZE (SFmode))))))) \ - && ! (CUM).force_mem \ - && (TARGET_SH2E \ - ? ((MODE) == BLKmode \ - ? (((CUM).arg_count[(int) SH_ARG_INT] * UNITS_PER_WORD \ - + int_size_in_bytes (TYPE)) \ - <= NPARM_REGS (SImode) * UNITS_PER_WORD) \ - : ((ROUND_REG((CUM), (MODE)) \ - + HARD_REGNO_NREGS (BASE_ARG_REG (MODE), (MODE))) \ - <= NPARM_REGS (MODE))) \ - : ROUND_REG ((CUM), (MODE)) < NPARM_REGS (MODE))) - /* By accident we got stuck with passing SCmode on SH4 little endian in two registers that are nominally successive - which is different from two single SFmode values, where we take endianness translation into |