The emit hook already takes the set of live hard registers as input.
This patch passes it to the needed hook too. SME uses this to
optimise the mode choice based on whether state is live or dead.
The main caller already had access to the required info, but the
special handling of return values did not.
gcc/
* target.def (mode_switching.needed): Add a regs_live parameter.
* doc/tm.texi: Regenerate.
* config/epiphany/epiphany-protos.h (epiphany_mode_needed): Update
accordingly.
* config/epiphany/epiphany.cc (epiphany_mode_needed): Likewise.
* config/epiphany/mode-switch-use.cc (insert_uses): Likewise.
* config/i386/i386.cc (ix86_mode_needed): Likewise.
* config/riscv/riscv.cc (riscv_mode_needed): Likewise.
* config/sh/sh.cc (sh_mode_needed): Likewise.
* mode-switching.cc (optimize_mode_switching): Likewise.
(create_pre_exit): Likewise, using the DF simulate functions
to calculate the required information.
#endif
extern void epiphany_insert_mode_switch_use (rtx_insn *insn, int, int);
extern void epiphany_expand_set_fp_mode (rtx *operands);
-extern int epiphany_mode_needed (int entity, rtx_insn *insn);
+#ifdef HARD_CONST
+extern int epiphany_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET);
+#endif
extern int epiphany_mode_after (int entity, int last_mode, rtx_insn *insn);
extern bool epiphany_epilogue_uses (int regno);
extern bool epiphany_optimize_mode_switching (int entity);
}
int
-epiphany_mode_needed (int entity, rtx_insn *insn)
+epiphany_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET)
{
enum attr_fp_mode mode;
{
if (!INSN_P (insn))
continue;
- mode = epiphany_mode_needed (e, insn);
+ mode = epiphany_mode_needed (e, insn, {});
if (mode == no_mode)
continue;
if (target_insert_mode_switch_use)
prior to the execution of insn. */
static int
-ix86_mode_needed (int entity, rtx_insn *insn)
+ix86_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET)
{
switch (entity)
{
prior to the execution of insn. */
static int
-riscv_mode_needed (int entity, rtx_insn *insn)
+riscv_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET)
{
int code = recog_memoized (insn);
static HOST_WIDE_INT rounded_frame_size (int);
static bool sh_frame_pointer_required (void);
static void sh_emit_mode_set (int, int, int, HARD_REG_SET);
-static int sh_mode_needed (int, rtx_insn *);
+static int sh_mode_needed (int, rtx_insn *, HARD_REG_SET);
static int sh_mode_after (int, int, rtx_insn *);
static int sh_mode_entry (int);
static int sh_mode_exit (int);
}
static int
-sh_mode_needed (int entity ATTRIBUTE_UNUSED, rtx_insn *insn)
+sh_mode_needed (int entity ATTRIBUTE_UNUSED, rtx_insn *insn, HARD_REG_SET)
{
return recog_memoized (insn) >= 0 ? get_attr_fp_mode (insn) : FP_MODE_NONE;
}
sets of a higher numbered entity to a mode of the same or lower priority.
@end deftypefn
-@deftypefn {Target Hook} int TARGET_MODE_NEEDED (int @var{entity}, rtx_insn *@var{insn})
+@deftypefn {Target Hook} int TARGET_MODE_NEEDED (int @var{entity}, rtx_insn *@var{insn}, HARD_REG_SET @var{regs_live})
@var{entity} is an integer specifying a mode-switched entity.
If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this hook
to return the mode that @var{entity} must be switched into prior to the
execution of @var{insn}, or the number of modes if @var{insn} has no
-such requirement.
+such requirement. @var{regs_live} contains the set of hard registers
+that are live before @var{insn}.
@end deftypefn
@deftypefn {Target Hook} int TARGET_MODE_AFTER (int @var{entity}, int @var{mode}, rtx_insn *@var{insn})
&& GET_CODE (PATTERN (last_insn)) == USE
&& GET_CODE ((ret_reg = XEXP (PATTERN (last_insn), 0))) == REG)
{
+ auto_bitmap live;
+ df_simulate_initialize_backwards (src_bb, live);
+
int ret_start = REGNO (ret_reg);
int nregs = REG_NREGS (ret_reg);
int ret_end = ret_start + nregs;
bool forced_late_switch = false;
rtx_insn *before_return_copy;
+ df_simulate_one_insn_backwards (src_bb, last_insn, live);
+
do
{
rtx_insn *return_copy = PREV_INSN (last_insn);
int copy_start, copy_num;
int j;
+ df_simulate_one_insn_backwards (src_bb, return_copy, live);
+
if (NONDEBUG_INSN_P (return_copy))
{
/* When using SJLJ exceptions, the call to the
the case for floating point on SH4 - then it might
be set by an arithmetic operation that needs a
different mode than the exit block. */
+ HARD_REG_SET hard_regs_live;
+ REG_SET_TO_HARD_REG_SET (hard_regs_live, live);
for (j = n_entities - 1; j >= 0; j--)
{
int e = entity_map[j];
int mode =
- targetm.mode_switching.needed (e, return_copy);
+ targetm.mode_switching.needed (e, return_copy,
+ hard_regs_live);
if (mode != num_modes[e]
&& mode != targetm.mode_switching.exit (e))
{
if (INSN_P (insn))
{
- int mode = targetm.mode_switching.needed (e, insn);
+ int mode = targetm.mode_switching.needed (e, insn, live_now);
rtx link;
if (mode != no_mode && mode != last_mode)
If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this hook\n\
to return the mode that @var{entity} must be switched into prior to the\n\
execution of @var{insn}, or the number of modes if @var{insn} has no\n\
-such requirement.",
- int, (int entity, rtx_insn *insn), NULL)
+such requirement. @var{regs_live} contains the set of hard registers\n\
+that are live before @var{insn}.",
+ int, (int entity, rtx_insn *insn, HARD_REG_SET regs_live), NULL)
DEFHOOK
(after,