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
This commit is contained in:
Oleg Endo 2014-05-03 09:42:52 +00:00
parent 3c922bcd25
commit f6982a08ca
3 changed files with 79 additions and 58 deletions

View File

@ -1,3 +1,15 @@
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> 2014-05-03 Oleg Endo <olegendo@gcc.gnu.org>
PR target/61026 PR target/61026

View File

@ -8809,6 +8809,54 @@ sh_callee_copies (cumulative_args_t cum, enum machine_mode mode,
% SH_MIN_ALIGN_FOR_CALLEE_COPY == 0)); % 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 static int
sh_arg_partial_bytes (cumulative_args_t cum_v, enum machine_mode mode, sh_arg_partial_bytes (cumulative_args_t cum_v, enum machine_mode mode,
tree type, bool named ATTRIBUTE_UNUSED) 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; int words = 0;
if (!TARGET_SH5 if (!TARGET_SH5
&& PASS_IN_REG_P (*cum, mode, type) && sh_pass_in_reg_p (*cum, mode, type)
&& !(TARGET_SH4 || TARGET_SH2A_DOUBLE) && !(TARGET_SH4 || TARGET_SH2A_DOUBLE)
&& (ROUND_REG (*cum, mode) && (sh_round_reg (*cum, mode)
+ (mode != BLKmode + (mode != BLKmode
? ROUND_ADVANCE (GET_MODE_SIZE (mode)) ? CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD)
: ROUND_ADVANCE (int_size_in_bytes (type))) : CEIL (int_size_in_bytes (type), UNITS_PER_WORD))
> NPARM_REGS (mode))) > NPARM_REGS (mode)))
words = NPARM_REGS (mode) - ROUND_REG (*cum, mode); words = NPARM_REGS (mode) - sh_round_reg (*cum, mode);
else if (!TARGET_SHCOMPACT else if (!TARGET_SHCOMPACT
&& SH5_WOULD_BE_PARTIAL_NREGS (*cum, mode, type, named)) && 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); return GEN_INT (ca->renesas_abi ? 1 : 0);
if (! TARGET_SH5 if (! TARGET_SH5
&& PASS_IN_REG_P (*ca, mode, type) && sh_pass_in_reg_p (*ca, mode, type)
&& (named || ! (TARGET_HITACHI || ca->renesas_abi))) && (named || ! (TARGET_HITACHI || ca->renesas_abi)))
{ {
int regno; int regno;
if (mode == SCmode && TARGET_SH4 && TARGET_LITTLE_ENDIAN 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, rtx r1 = gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (SFmode, gen_rtx_REG (SFmode,
BASE_ARG_REG (mode) BASE_ARG_REG (mode)
+ (ROUND_REG (*ca, mode) ^ 1)), + (sh_round_reg (*ca, mode) ^ 1)),
const0_rtx); const0_rtx);
rtx r2 = gen_rtx_EXPR_LIST (VOIDmode, rtx r2 = gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (SFmode, gen_rtx_REG (SFmode,
BASE_ARG_REG (mode) BASE_ARG_REG (mode)
+ ((ROUND_REG (*ca, mode) + 1) ^ 1)), + ((sh_round_reg (*ca, mode) + 1) ^ 1)),
GEN_INT (4)); GEN_INT (4));
return gen_rtx_PARALLEL(SCmode, gen_rtvec(2, r1, r2)); 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) && mode == SFmode)
return gen_rtx_REG (mode, ca->free_single_fp_reg); 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 ^ (mode == SFmode && TARGET_SH4
&& TARGET_LITTLE_ENDIAN && TARGET_LITTLE_ENDIAN
&& ! TARGET_HITACHI && ! ca->renesas_abi); && ! 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 register, because the next SF value will use it, and not the
SF that follows the DF. */ SF that follows the DF. */
if (mode == DFmode 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)); + BASE_ARG_REG (mode));
} }
} }
if (! ((TARGET_SH4 || TARGET_SH2A) || ca->renesas_abi) 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)] (ca->arg_count[(int) GET_SH_ARG_CLASS (mode)]
= (ROUND_REG (*ca, mode) = (sh_round_reg (*ca, mode)
+ (mode == BLKmode + (mode == BLKmode
? ROUND_ADVANCE (int_size_in_bytes (type)) ? CEIL (int_size_in_bytes (type), UNITS_PER_WORD)
: ROUND_ADVANCE (GET_MODE_SIZE (mode))))); : CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD))));
} }
/* The Renesas calling convention doesn't quite fit into this scheme since /* 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; 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 + (mode == BLKmode
? ROUND_ADVANCE (int_size_in_bytes (type)) ? CEIL (int_size_in_bytes (type), UNITS_PER_WORD)
: ROUND_ADVANCE (GET_MODE_SIZE (mode)))); : CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD)));
anon_parm_regs = NPARM_REGS (SImode) - named_parm_regs; anon_parm_regs = NPARM_REGS (SImode) - named_parm_regs;
if (anon_parm_regs > 0) if (anon_parm_regs > 0)
*pretend_arg_size = anon_parm_regs * 4; *pretend_arg_size = anon_parm_regs * 4;

View File

@ -1361,24 +1361,6 @@ struct sh_args {
|| GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \ || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
? SH_ARG_FLOAT : SH_ARG_INT) ? 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 /* Initialize a variable CUM of type CUMULATIVE_ARGS
for a call to a function whose data type is FNTYPE. for a call to a function whose data type is FNTYPE.
For a library call, FNTYPE is 0. For a library call, FNTYPE is 0.
@ -1394,27 +1376,6 @@ struct sh_args {
#define INIT_CUMULATIVE_LIBCALL_ARGS(CUM, MODE, LIBNAME) \ #define INIT_CUMULATIVE_LIBCALL_ARGS(CUM, MODE, LIBNAME) \
sh_init_cumulative_args (& (CUM), NULL_TREE, (LIBNAME), NULL_TREE, 0, (MODE)) 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 /* By accident we got stuck with passing SCmode on SH4 little endian
in two registers that are nominally successive - which is different from in two registers that are nominally successive - which is different from
two single SFmode values, where we take endianness translation into two single SFmode values, where we take endianness translation into