aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/epiphany/epiphany-protos.h4
-rw-r--r--gcc/config/epiphany/epiphany.cc2
-rw-r--r--gcc/config/epiphany/mode-switch-use.cc2
-rw-r--r--gcc/config/i386/i386.cc2
-rw-r--r--gcc/config/riscv/riscv.cc2
-rw-r--r--gcc/config/sh/sh.cc4
-rw-r--r--gcc/doc/tm.texi5
-rw-r--r--gcc/mode-switching.cc14
-rw-r--r--gcc/target.def5
9 files changed, 27 insertions, 13 deletions
diff --git a/gcc/config/epiphany/epiphany-protos.h b/gcc/config/epiphany/epiphany-protos.h
index 72c141c..ef49a1e 100644
--- a/gcc/config/epiphany/epiphany-protos.h
+++ b/gcc/config/epiphany/epiphany-protos.h
@@ -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);
diff --git a/gcc/config/epiphany/epiphany.cc b/gcc/config/epiphany/epiphany.cc
index a5460db..60a9b49 100644
--- a/gcc/config/epiphany/epiphany.cc
+++ b/gcc/config/epiphany/epiphany.cc
@@ -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;
diff --git a/gcc/config/epiphany/mode-switch-use.cc b/gcc/config/epiphany/mode-switch-use.cc
index 7153061..183b9b7 100644
--- a/gcc/config/epiphany/mode-switch-use.cc
+++ b/gcc/config/epiphany/mode-switch-use.cc
@@ -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)
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index eec9b42..a041e87 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -15060,7 +15060,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)
{
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index fa2d4d4..750eaf9 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -9426,7 +9426,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);
diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc
index 294faf7..c363490 100644
--- a/gcc/config/sh/sh.cc
+++ b/gcc/config/sh/sh.cc
@@ -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;
}
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 1a825c5..144b3f8 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -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})
diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc
index b8a887d..c5fe90b 100644
--- a/gcc/mode-switching.cc
+++ b/gcc/mode-switching.cc
@@ -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)
diff --git a/gcc/target.def b/gcc/target.def
index a70275b..50bad18 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -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,