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:
Richard Sandiford 2019-09-30 16:21:39 +00:00 committed by Richard Sandiford
parent 2e2c6df346
commit 497b699b93
4 changed files with 72 additions and 50 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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;