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>
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));
}
/* 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;

View File

@ -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