@@ -44,7 +44,9 @@ extern void emit_set_fp_mode (int entity, int mode, int prev_mode,
#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);
@@ -2400,7 +2400,7 @@ epiphany_mode_priority (int entity, int priority)
}
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;
@@ -58,7 +58,7 @@ insert_uses (void)
{
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)
@@ -15061,7 +15061,7 @@ ix86_i387_mode_needed (int entity, rtx_insn *insn)
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)
{
@@ -9413,7 +9413,7 @@ riscv_frm_mode_needed (rtx_insn *cur_insn, int code)
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);
@@ -195,7 +195,7 @@ static int calc_live_regs (HARD_REG_SET *);
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);
@@ -12531,7 +12531,7 @@ sh_emit_mode_set (int entity ATTRIBUTE_UNUSED, int mode,
}
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;
}
@@ -10414,12 +10414,13 @@ known. Sets of a lower numbered entity will be emitted before
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})
@@ -254,6 +254,9 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
&& 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;
@@ -262,6 +265,8 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
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);
@@ -269,6 +274,8 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
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
@@ -368,11 +375,14 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
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))
@@ -610,7 +620,7 @@ optimize_mode_switching (void)
{
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)
@@ -7031,8 +7031,9 @@ DEFHOOK
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,