Remove global call sets: sel-sched.c
The main change here is to replace a crosses_call boolean with a bitmask of the ABIs used by the crossed calls. For space reasons, I didn't also add a HARD_REG_SET that tracks the set of registers that are actually clobbered, which means that this is the one part of the series that doesn't benefit from -fipa-ra. The existing FIXME suggests that the current structures aren't the preferred way of representing this anyhow, and the pass already makes conservative assumptions about call-crossing registers. 2019-09-30 Richard Sandiford <richard.sandiford@arm.com> gcc/ * sel-sched-ir.h (_def::crosses_call): Replace with... (_def::crossed_call_abis): ..this new field. (def_list_add): Take a mask of ABIs instead of a crosses_call boolean. * sel-sched-ir.c (def_list_add): Likewise. Update initialization of _def accordingly. * sel-sched.c: Include function-abi.h. (hard_regs_data::regs_for_call_clobbered): Delete. (reg_rename::crosses_call): Replace with... (reg_rename::crossed_call_abis): ...this new field. (fur_static_params::crosses_call): Replace with... (fur_static_params::crossed_call_abis): ...this new field. (init_regs_for_mode): Don't initialize sel_hrd.regs_for_call_clobbered. (init_hard_regs_data): Use crtl->abi to test which registers the current function would need to save before it uses them. (mark_unavailable_hard_regs): Update handling of call-clobbered registers, using call_clobbers_in_region to find out which registers might be call-clobbered (but without taking -fipa-ra into account for now). Remove separate handling of partially call-clobbered registers. (verify_target_availability): Use crossed_call_abis instead of crosses_call. (get_spec_check_type_for_insn, find_used_regs): Likewise. (fur_orig_expr_found, fur_on_enter, fur_orig_expr_not_found): Likewise. From-SVN: r276336
This commit is contained in:
parent
2e2c6df346
commit
497b699b93
|
@ -1,3 +1,30 @@
|
|||
2019-09-30 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* sel-sched-ir.h (_def::crosses_call): Replace with...
|
||||
(_def::crossed_call_abis): ..this new field.
|
||||
(def_list_add): Take a mask of ABIs instead of a crosses_call
|
||||
boolean.
|
||||
* sel-sched-ir.c (def_list_add): Likewise. Update initialization
|
||||
of _def accordingly.
|
||||
* sel-sched.c: Include function-abi.h.
|
||||
(hard_regs_data::regs_for_call_clobbered): Delete.
|
||||
(reg_rename::crosses_call): Replace with...
|
||||
(reg_rename::crossed_call_abis): ...this new field.
|
||||
(fur_static_params::crosses_call): Replace with...
|
||||
(fur_static_params::crossed_call_abis): ...this new field.
|
||||
(init_regs_for_mode): Don't initialize sel_hrd.regs_for_call_clobbered.
|
||||
(init_hard_regs_data): Use crtl->abi to test which registers the
|
||||
current function would need to save before it uses them.
|
||||
(mark_unavailable_hard_regs): Update handling of call-clobbered
|
||||
registers, using call_clobbers_in_region to find out which registers
|
||||
might be call-clobbered (but without taking -fipa-ra into account
|
||||
for now). Remove separate handling of partially call-clobbered
|
||||
registers.
|
||||
(verify_target_availability): Use crossed_call_abis instead of
|
||||
crosses_call.
|
||||
(get_spec_check_type_for_insn, find_used_regs): Likewise.
|
||||
(fur_orig_expr_found, fur_on_enter, fur_orig_expr_not_found): Likewise.
|
||||
|
||||
2019-09-30 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* sched-deps.c (deps_analyze_insn): Use the ABI of the target
|
||||
|
|
|
@ -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 original_insn, bool crosses_call)
|
|||
d = DEF_LIST_DEF (*dl);
|
||||
|
||||
d->orig_insn = original_insn;
|
||||
d->crosses_call = crosses_call;
|
||||
d->crossed_call_abis = crossed_call_abis;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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_t);
|
|||
|
||||
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);
|
||||
|
|
|
@ -46,6 +46,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#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, struct reg_rename *reg_rename_p,
|
|||
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, struct reg_rename *reg_rename_p,
|
|||
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);
|
||||
|
||||
/* Stop here before reload: we need FRAME_REGS, STACK_REGS, and crosses_call,
|
||||
but not register classes. */
|
||||
/* If there's a call on this path, make regs from full_reg_clobbers
|
||||
unavailable.
|
||||
|
||||
??? 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, struct reg_rename *reg_rename_p,
|
|||
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, regset used_regs,
|
|||
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 insn, expr_t expr)
|
|||
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 orig_ops, regset used_regs,
|
|||
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 orig_ops, regset used_regs,
|
|||
|
||||
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, expr_t expr,
|
|||
|
||||
/* 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 expr ATTRIBUTE_UNUSED,
|
|||
regset tmp;
|
||||
|
||||
if (CALL_P (insn))
|
||||
params->crosses_call = true;
|
||||
params->crossed_call_abis |= 1 << insn_callee_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_UNUSED, cmpd_local_params_p local_params,
|
|||
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_set_t orig_ops, void *static_params)
|
|||
fur_static_params_p sparams = (fur_static_params_p) static_params;
|
||||
|
||||
if (CALL_P (insn))
|
||||
sparams->crosses_call = true;
|
||||
sparams->crossed_call_abis |= 1 << insn_callee_abi (insn).id ();
|
||||
else if (DEBUG_INSN_P (insn))
|
||||
return true;
|
||||
|
||||
|
|
Loading…
Reference in New Issue