diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/epiphany/epiphany-protos.h | 4 | ||||
-rw-r--r-- | gcc/config/epiphany/epiphany.cc | 2 | ||||
-rw-r--r-- | gcc/config/epiphany/mode-switch-use.cc | 2 | ||||
-rw-r--r-- | gcc/config/i386/i386.cc | 2 | ||||
-rw-r--r-- | gcc/config/riscv/riscv.cc | 2 | ||||
-rw-r--r-- | gcc/config/sh/sh.cc | 4 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 5 | ||||
-rw-r--r-- | gcc/mode-switching.cc | 14 | ||||
-rw-r--r-- | gcc/target.def | 5 |
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, |