===================================================================
@@ -188,12 +188,12 @@ struct _def
{
insn_t orig_insn;
- /* FIXME: Get rid of CROSSES_CALL in each def, since if we're moving up
+ /* FIXME: Get rid of CROSSED_CALL_ABIS in each def, since if we're moving up
rhs from two different places, but only one of the code motion paths
crosses a call, we can't use any of the call_used_regs, no matter which
- path or whether all paths crosses a call. Thus we should move CROSSES_CALL
- to static params. */
- bool crosses_call;
+ path or whether all paths crosses a call. Thus we should move
+ CROSSED_CALL_ABIS to static params. */
+ unsigned int crossed_call_abis;
};
typedef struct _def *def_t;
@@ -1510,7 +1510,7 @@ extern void flist_tail_init (flist_tail_
extern fence_t flist_lookup (flist_t, insn_t);
extern void flist_clear (flist_t *);
-extern void def_list_add (def_list_t *, insn_t, bool);
+extern void def_list_add (def_list_t *, insn_t, unsigned int);
/* Target context functions. */
extern tc_t create_target_context (bool);
===================================================================
@@ -311,9 +311,10 @@ flist_clear (flist_t *lp)
flist_remove (lp);
}
-/* Add ORIGINAL_INSN the def list DL honoring CROSSES_CALL. */
+/* Add ORIGINAL_INSN the def list DL honoring CROSSED_CALL_ABIS. */
void
-def_list_add (def_list_t *dl, insn_t original_insn, bool crosses_call)
+def_list_add (def_list_t *dl, insn_t original_insn,
+ unsigned int crossed_call_abis)
{
def_t d;
@@ -321,7 +322,7 @@ def_list_add (def_list_t *dl, insn_t ori
d = DEF_LIST_DEF (*dl);
d->orig_insn = original_insn;
- d->crosses_call = crosses_call;
+ d->crossed_call_abis = crossed_call_abis;
}
===================================================================
@@ -46,6 +46,7 @@ Software Foundation; either version 3, o
#include "sel-sched-dump.h"
#include "sel-sched.h"
#include "dbgcnt.h"
+#include "function-abi.h"
/* Implementation of selective scheduling approach.
The below implementation follows the original approach with the following
@@ -302,10 +303,6 @@ struct hard_regs_data
that the whole set is not computed yet. */
HARD_REG_SET regs_for_rename[FIRST_PSEUDO_REGISTER];
- /* For every mode, this stores registers not available due to
- call clobbering. */
- HARD_REG_SET regs_for_call_clobbered[NUM_MACHINE_MODES];
-
/* All registers that are used or call used. */
HARD_REG_SET regs_ever_used;
@@ -325,8 +322,8 @@ struct reg_rename
/* These are *available* for renaming. */
HARD_REG_SET available_for_renaming;
- /* Whether this code motion path crosses a call. */
- bool crosses_call;
+ /* The set of ABIs used by calls that the code motion path crosses. */
+ unsigned int crossed_call_abis : NUM_ABI_IDS;
};
/* A global structure that contains the needed information about harg
@@ -390,8 +387,8 @@ struct fur_static_params
/* Pointer to the list of original insns definitions. */
def_list_t *original_insns;
- /* True if a code motion path contains a CALL insn. */
- bool crosses_call;
+ /* The set of ABIs used by calls that the code motion path crosses. */
+ unsigned int crossed_call_abis : NUM_ABI_IDS;
};
typedef struct fur_static_params *fur_static_params_p;
@@ -1067,7 +1064,6 @@ init_regs_for_mode (machine_mode mode)
int cur_reg;
CLEAR_HARD_REG_SET (sel_hrd.regs_for_mode[mode]);
- CLEAR_HARD_REG_SET (sel_hrd.regs_for_call_clobbered[mode]);
for (cur_reg = 0; cur_reg < FIRST_PSEUDO_REGISTER; cur_reg++)
{
@@ -1102,10 +1098,6 @@ init_regs_for_mode (machine_mode mode)
if (i >= 0)
continue;
- if (targetm.hard_regno_call_part_clobbered (0, cur_reg, mode))
- SET_HARD_REG_BIT (sel_hrd.regs_for_call_clobbered[mode],
- cur_reg);
-
/* If the CUR_REG passed all the checks above,
then it's ok. */
SET_HARD_REG_BIT (sel_hrd.regs_for_mode[mode], cur_reg);
@@ -1123,7 +1115,8 @@ init_hard_regs_data (void)
CLEAR_HARD_REG_SET (sel_hrd.regs_ever_used);
for (cur_reg = 0; cur_reg < FIRST_PSEUDO_REGISTER; cur_reg++)
- if (df_regs_ever_live_p (cur_reg) || call_used_or_fixed_reg_p (cur_reg))
+ if (df_regs_ever_live_p (cur_reg)
+ || crtl->abi->clobbers_full_reg_p (cur_reg))
SET_HARD_REG_BIT (sel_hrd.regs_ever_used, cur_reg);
/* Initialize registers that are valid based on mode when this is
@@ -1193,7 +1186,7 @@ mark_unavailable_hard_regs (def_t def, s
SET_HARD_REG_SET (reg_rename_p->unavailable_hard_regs);
/* Give a chance for original register, if it isn't in used_regs. */
- if (!def->crosses_call)
+ if (!def->crossed_call_abis)
CLEAR_HARD_REG_BIT (reg_rename_p->unavailable_hard_regs, regno);
return;
@@ -1224,13 +1217,20 @@ mark_unavailable_hard_regs (def_t def, s
reg_rename_p->unavailable_hard_regs |= sel_hrd.stack_regs;
#endif
- /* If there's a call on this path, make regs from call_used_or_fixed_regs
- unavailable. */
- if (def->crosses_call)
- reg_rename_p->unavailable_hard_regs |= call_used_or_fixed_regs;
+ mode = GET_MODE (orig_dest);
+
+ /* If there's a call on this path, make regs from full_reg_clobbers
+ unavailable.
- /* Stop here before reload: we need FRAME_REGS, STACK_REGS, and crosses_call,
- but not register classes. */
+ ??? It would be better to track the set of clobbered registers
+ directly, but that would be quite expensive in a def_t. */
+ if (def->crossed_call_abis)
+ reg_rename_p->unavailable_hard_regs
+ |= call_clobbers_in_region (def->crossed_call_abis,
+ reg_class_contents[ALL_REGS], mode);
+
+ /* Stop here before reload: we need FRAME_REGS, STACK_REGS, and
+ crossed_call_abis, but not register classes. */
if (!reload_completed)
return;
@@ -1238,19 +1238,11 @@ mark_unavailable_hard_regs (def_t def, s
register class. */
reg_rename_p->available_for_renaming = reg_class_contents[cl];
- mode = GET_MODE (orig_dest);
-
/* Leave only registers available for this mode. */
if (!sel_hrd.regs_for_mode_ok[mode])
init_regs_for_mode (mode);
reg_rename_p->available_for_renaming &= sel_hrd.regs_for_mode[mode];
- /* Exclude registers that are partially call clobbered. */
- if (def->crosses_call
- && !targetm.hard_regno_call_part_clobbered (0, regno, mode))
- reg_rename_p->available_for_renaming
- &= ~sel_hrd.regs_for_call_clobbered[mode];
-
/* Leave only those that are ok to rename. */
EXECUTE_IF_SET_IN_HARD_REG_SET (reg_rename_p->available_for_renaming,
0, cur_reg, hrsi)
@@ -1481,7 +1473,7 @@ choose_best_pseudo_reg (regset used_regs
/* Don't let register cross a call if it doesn't already
cross one. This condition is written in accordance with
that in sched-deps.c sched_analyze_reg(). */
- if (!reg_rename_p->crosses_call
+ if (!reg_rename_p->crossed_call_abis
|| REG_N_CALLS_CROSSED (orig_regno) > 0)
return gen_rtx_REG (mode, orig_regno);
}
@@ -1508,7 +1500,8 @@ choose_best_pseudo_reg (regset used_regs
max_regno = max_reg_num ();
maybe_extend_reg_info_p ();
- REG_N_CALLS_CROSSED (REGNO (new_reg)) = reg_rename_p->crosses_call ? 1 : 0;
+ REG_N_CALLS_CROSSED (REGNO (new_reg))
+ = reg_rename_p->crossed_call_abis ? 1 : 0;
return new_reg;
}
@@ -1560,7 +1553,8 @@ verify_target_availability (expr_t expr,
as well. */
gcc_assert (scheduled_something_on_previous_fence || !live_available
|| !hard_available
- || (!reload_completed && reg_rename_p->crosses_call
+ || (!reload_completed
+ && reg_rename_p->crossed_call_abis
&& REG_N_CALLS_CROSSED (regno) == 0));
}
@@ -3248,7 +3242,7 @@ get_spec_check_type_for_insn (insn_t ins
All the original operations found during the traversal are saved in the
ORIGINAL_INSNS list.
- REG_RENAME_P->CROSSES_CALL is true, if there is a call insn on the path
+ REG_RENAME_P->CROSSED_CALL_ABIS is true, if there is a call insn on the path
from INSN to original insn. In this case CALL_USED_REG_SET will be added
to unavailable hard regs at the point original operation is found. */
@@ -3269,7 +3263,7 @@ find_used_regs (insn_t insn, av_set_t or
bitmap_clear (code_motion_visited_blocks);
/* Init parameters for code_motion_path_driver. */
- sparams.crosses_call = false;
+ sparams.crossed_call_abis = 0;
sparams.original_insns = original_insns;
sparams.used_regs = used_regs;
@@ -3278,7 +3272,7 @@ find_used_regs (insn_t insn, av_set_t or
res = code_motion_path_driver (insn, orig_ops, NULL, &lparams, &sparams);
- reg_rename_p->crosses_call |= sparams.crosses_call;
+ reg_rename_p->crossed_call_abis |= sparams.crossed_call_abis;
gcc_assert (res == 1);
gcc_assert (original_insns && *original_insns);
@@ -6006,7 +6000,7 @@ move_op_orig_expr_found (insn_t insn, ex
/* The function is called when original expr is found.
INSN - current insn traversed, EXPR - the corresponding expr found,
- crosses_call and original_insns in STATIC_PARAMS are updated. */
+ crossed_call_abis and original_insns in STATIC_PARAMS are updated. */
static void
fur_orig_expr_found (insn_t insn, expr_t expr ATTRIBUTE_UNUSED,
cmpd_local_params_p lparams ATTRIBUTE_UNUSED,
@@ -6016,9 +6010,9 @@ fur_orig_expr_found (insn_t insn, expr_t
regset tmp;
if (CALL_P (insn))
- params->crosses_call = true;
+ params->crossed_call_abis |= 1 << call_insn_abi (insn).id ();
- def_list_add (params->original_insns, insn, params->crosses_call);
+ def_list_add (params->original_insns, insn, params->crossed_call_abis);
/* Mark the registers that do not meet the following condition:
(2) not among the live registers of the point
@@ -6176,10 +6170,10 @@ fur_on_enter (insn_t insn ATTRIBUTE_UNUS
least one insn in ORIGINAL_INSNS. */
gcc_assert (*sparams->original_insns);
- /* Adjust CROSSES_CALL, since we may have come to this block along
+ /* Adjust CROSSED_CALL_ABIS, since we may have come to this block along
different path. */
- DEF_LIST_DEF (*sparams->original_insns)->crosses_call
- |= sparams->crosses_call;
+ DEF_LIST_DEF (*sparams->original_insns)->crossed_call_abis
+ |= sparams->crossed_call_abis;
}
else
local_params->old_original_insns = *sparams->original_insns;
@@ -6233,7 +6227,7 @@ fur_orig_expr_not_found (insn_t insn, av
fur_static_params_p sparams = (fur_static_params_p) static_params;
if (CALL_P (insn))
- sparams->crosses_call = true;
+ sparams->crossed_call_abis |= 1 << call_insn_abi (insn).id ();
else if (DEBUG_INSN_P (insn))
return true;