Commit a25f3e8e by Richard Sandiford Committed by Richard Sandiford

Make lra use per-alternative earlyclobber info

lra_insn_reg and lra_operand_data have both a bitmask of earlyclobber
alternatives and an overall boolean.  The danger is that we then test
the overall boolean when really we should be testing for a particular
alternative.  This patch gets rid of the boolean and tests the mask
against zero when we really do need to test "any alternative might
be earlyclobber".  (I think the only instance of that is the
LRA_UNKNOWN_ALT handling in lra-lives.c:reg_early_clobber_p.)

This is needed (and tested) by an upcoming SVE patch.

2019-07-31  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* lra-int.h (lra_operand_data): Remove early_clobber field.
	(lra_insn_reg): Likewise.
	* lra.c (debug_operand_data): Update accordingly.
	(setup_operand_alternative): Likewise.
	(new_insn_reg): Likewise.  Remove early_clobber parameter.
	(collect_non_operand_hard_regs): Update call accordingly.
	Don't assign to lra_insn_reg::early_clobber.
	(add_regs_to_insn_regno_info): Remove early_clobber parameter
	and update calls to new_insn_reg.
	(lra_update_insn_regno_info): Update calls accordingly.
	* lra-constraints.c (update_and_check_small_class_inputs): Take the
	alternative number as a parameter and test whether the operand
	is earlyclobbered in that particular alternative.
	(process_alt_operands): Update call accordingly.  Use per-alternative
	checks for earyclobber here too.
	* lra-lives.c (reg_early_clobber_p): Check early_clobber_alts
	against zero for IRA_UNKNOWN_ALT.

From-SVN: r273921
parent 68c86af2
2019-07-31 Richard Sandiford <richard.sandiford@arm.com>
* lra-int.h (lra_operand_data): Remove early_clobber field.
(lra_insn_reg): Likewise.
* lra.c (debug_operand_data): Update accordingly.
(setup_operand_alternative): Likewise.
(new_insn_reg): Likewise. Remove early_clobber parameter.
(collect_non_operand_hard_regs): Update call accordingly.
Don't assign to lra_insn_reg::early_clobber.
(add_regs_to_insn_regno_info): Remove early_clobber parameter
and update calls to new_insn_reg.
(lra_update_insn_regno_info): Update calls accordingly.
* lra-constraints.c (update_and_check_small_class_inputs): Take the
alternative number as a parameter and test whether the operand
is earlyclobbered in that particular alternative.
(process_alt_operands): Update call accordingly. Use per-alternative
checks for earyclobber here too.
* lra-lives.c (reg_early_clobber_p): Check early_clobber_alts
against zero for IRA_UNKNOWN_ALT.
2019-07-30 Uroš Bizjak <ubizjak@gmail.com> 2019-07-30 Uroš Bizjak <ubizjak@gmail.com>
* config/alpha/alpha.c (alpha_option_override): Quote a C type. * config/alpha/alpha.c (alpha_option_override): Quote a C type.
......
...@@ -1866,11 +1866,12 @@ prohibited_class_reg_set_mode_p (enum reg_class rclass, ...@@ -1866,11 +1866,12 @@ prohibited_class_reg_set_mode_p (enum reg_class rclass,
alternative. */ alternative. */
static unsigned int curr_small_class_check = 0; static unsigned int curr_small_class_check = 0;
/* Update number of used inputs of class OP_CLASS for operand NOP. /* Update number of used inputs of class OP_CLASS for operand NOP
Return true if we have more such class operands than the number of of alternative NALT. Return true if we have more such class operands
available regs. */ than the number of available regs. */
static bool static bool
update_and_check_small_class_inputs (int nop, enum reg_class op_class) update_and_check_small_class_inputs (int nop, int nalt,
enum reg_class op_class)
{ {
static unsigned int small_class_check[LIM_REG_CLASSES]; static unsigned int small_class_check[LIM_REG_CLASSES];
static int small_class_input_nums[LIM_REG_CLASSES]; static int small_class_input_nums[LIM_REG_CLASSES];
...@@ -1881,7 +1882,7 @@ update_and_check_small_class_inputs (int nop, enum reg_class op_class) ...@@ -1881,7 +1882,7 @@ update_and_check_small_class_inputs (int nop, enum reg_class op_class)
&& hard_reg_set_intersect_p (reg_class_contents[op_class], && hard_reg_set_intersect_p (reg_class_contents[op_class],
ira_no_alloc_regs) ira_no_alloc_regs)
&& (curr_static_id->operand[nop].type != OP_OUT && (curr_static_id->operand[nop].type != OP_OUT
|| curr_static_id->operand[nop].early_clobber)) || TEST_BIT (curr_static_id->operand[nop].early_clobber_alts, nalt)))
{ {
if (small_class_check[op_class] == curr_small_class_check) if (small_class_check[op_class] == curr_small_class_check)
small_class_input_nums[op_class]++; small_class_input_nums[op_class]++;
...@@ -2150,7 +2151,8 @@ process_alt_operands (int only_alternative) ...@@ -2150,7 +2151,8 @@ process_alt_operands (int only_alternative)
/* We should reject matching of an early /* We should reject matching of an early
clobber operand if the matching operand is clobber operand if the matching operand is
not dying in the insn. */ not dying in the insn. */
if (! curr_static_id->operand[m].early_clobber if (!TEST_BIT (curr_static_id->operand[m]
.early_clobber_alts, nalt)
|| operand_reg[nop] == NULL_RTX || operand_reg[nop] == NULL_RTX
|| (find_regno_note (curr_insn, REG_DEAD, || (find_regno_note (curr_insn, REG_DEAD,
REGNO (op)) REGNO (op))
...@@ -2234,7 +2236,8 @@ process_alt_operands (int only_alternative) ...@@ -2234,7 +2236,8 @@ process_alt_operands (int only_alternative)
it results in less hard regs required for it results in less hard regs required for
the insn than a non-matching earlyclobber the insn than a non-matching earlyclobber
alternative. */ alternative. */
if (curr_static_id->operand[m].early_clobber) if (TEST_BIT (curr_static_id->operand[m]
.early_clobber_alts, nalt))
{ {
if (lra_dump_file != NULL) if (lra_dump_file != NULL)
fprintf fprintf
...@@ -2875,7 +2878,8 @@ process_alt_operands (int only_alternative) ...@@ -2875,7 +2878,8 @@ process_alt_operands (int only_alternative)
goto fail; goto fail;
} }
if (update_and_check_small_class_inputs (nop, this_alternative)) if (update_and_check_small_class_inputs (nop, nalt,
this_alternative))
{ {
if (lra_dump_file != NULL) if (lra_dump_file != NULL)
fprintf (lra_dump_file, fprintf (lra_dump_file,
......
...@@ -142,10 +142,6 @@ struct lra_operand_data ...@@ -142,10 +142,6 @@ struct lra_operand_data
unsigned int strict_low : 1; unsigned int strict_low : 1;
/* True if the operand is an operator. */ /* True if the operand is an operator. */
unsigned int is_operator : 1; unsigned int is_operator : 1;
/* True if there is an early clobber alternative for this operand.
This field is set up every time when corresponding
operand_alternative in lra_static_insn_data is set up. */
unsigned int early_clobber : 1;
/* True if the operand is an address. */ /* True if the operand is an address. */
unsigned int is_address : 1; unsigned int is_address : 1;
}; };
...@@ -164,9 +160,6 @@ struct lra_insn_reg ...@@ -164,9 +160,6 @@ struct lra_insn_reg
/* True if the reg is accessed through a subreg and the subreg is /* True if the reg is accessed through a subreg and the subreg is
just a part of the register. */ just a part of the register. */
unsigned int subreg_p : 1; unsigned int subreg_p : 1;
/* True if there is an early clobber alternative for this
operand. */
unsigned int early_clobber : 1;
/* True if the reg is clobber highed by the operand. */ /* True if the reg is clobber highed by the operand. */
unsigned int clobber_high : 1; unsigned int clobber_high : 1;
/* The corresponding regno of the register. */ /* The corresponding regno of the register. */
......
...@@ -624,10 +624,10 @@ check_pseudos_live_through_calls (int regno, ...@@ -624,10 +624,10 @@ check_pseudos_live_through_calls (int regno,
static inline bool static inline bool
reg_early_clobber_p (const struct lra_insn_reg *reg, int n_alt) reg_early_clobber_p (const struct lra_insn_reg *reg, int n_alt)
{ {
return (reg->early_clobber return (n_alt == LRA_UNKNOWN_ALT
&& (n_alt == LRA_UNKNOWN_ALT ? reg->early_clobber_alts != 0
|| (n_alt != LRA_NON_CLOBBERED_ALT : (n_alt != LRA_NON_CLOBBERED_ALT
&& TEST_BIT (reg->early_clobber_alts, n_alt)))); && TEST_BIT (reg->early_clobber_alts, n_alt)));
} }
/* Return true if call instructions CALL1 and CALL2 use ABIs that /* Return true if call instructions CALL1 and CALL2 use ABIs that
......
...@@ -536,16 +536,14 @@ object_allocator<lra_insn_reg> lra_insn_reg_pool ("insn regs"); ...@@ -536,16 +536,14 @@ object_allocator<lra_insn_reg> lra_insn_reg_pool ("insn regs");
/* Create LRA insn related info about a reference to REGNO in INSN /* Create LRA insn related info about a reference to REGNO in INSN
with TYPE (in/out/inout), biggest reference mode MODE, flag that it with TYPE (in/out/inout), biggest reference mode MODE, flag that it
is reference through subreg (SUBREG_P), flag that is early is reference through subreg (SUBREG_P), and reference to the next
clobbered in the insn (EARLY_CLOBBER), and reference to the next
insn reg info (NEXT). If REGNO can be early clobbered, insn reg info (NEXT). If REGNO can be early clobbered,
alternatives in which it can be early clobbered are given by alternatives in which it can be early clobbered are given by
EARLY_CLOBBER_ALTS. CLOBBER_HIGH marks if reference is a clobber EARLY_CLOBBER_ALTS. CLOBBER_HIGH marks if reference is a clobber
high. */ high. */
static struct lra_insn_reg * static struct lra_insn_reg *
new_insn_reg (rtx_insn *insn, int regno, enum op_type type, new_insn_reg (rtx_insn *insn, int regno, enum op_type type,
machine_mode mode, machine_mode mode, bool subreg_p,
bool subreg_p, bool early_clobber,
alternative_mask early_clobber_alts, alternative_mask early_clobber_alts,
struct lra_insn_reg *next, bool clobber_high) struct lra_insn_reg *next, bool clobber_high)
{ {
...@@ -556,7 +554,6 @@ new_insn_reg (rtx_insn *insn, int regno, enum op_type type, ...@@ -556,7 +554,6 @@ new_insn_reg (rtx_insn *insn, int regno, enum op_type type,
&& partial_subreg_p (lra_reg_info[regno].biggest_mode, mode)) && partial_subreg_p (lra_reg_info[regno].biggest_mode, mode))
lra_reg_info[regno].biggest_mode = mode; lra_reg_info[regno].biggest_mode = mode;
ir->subreg_p = subreg_p; ir->subreg_p = subreg_p;
ir->early_clobber = early_clobber;
ir->early_clobber_alts = early_clobber_alts; ir->early_clobber_alts = early_clobber_alts;
ir->clobber_high = clobber_high; ir->clobber_high = clobber_high;
ir->regno = regno; ir->regno = regno;
...@@ -605,7 +602,7 @@ static struct lra_operand_data debug_operand_data = ...@@ -605,7 +602,7 @@ static struct lra_operand_data debug_operand_data =
0, /* early_clobber_alts */ 0, /* early_clobber_alts */
E_VOIDmode, /* We are not interesting in the operand mode. */ E_VOIDmode, /* We are not interesting in the operand mode. */
OP_IN, OP_IN,
0, 0, 0, 0 0, 0, 0
}; };
/* The following data are used as static insn data for all debug /* The following data are used as static insn data for all debug
...@@ -801,7 +798,6 @@ setup_operand_alternative (lra_insn_recog_data_t data, ...@@ -801,7 +798,6 @@ setup_operand_alternative (lra_insn_recog_data_t data,
for (i = 0; i < nop; i++) for (i = 0; i < nop; i++)
{ {
static_data->operand[i].early_clobber_alts = 0; static_data->operand[i].early_clobber_alts = 0;
static_data->operand[i].early_clobber = false;
static_data->operand[i].is_address = false; static_data->operand[i].is_address = false;
if (static_data->operand[i].constraint[0] == '%') if (static_data->operand[i].constraint[0] == '%')
{ {
...@@ -817,7 +813,6 @@ setup_operand_alternative (lra_insn_recog_data_t data, ...@@ -817,7 +813,6 @@ setup_operand_alternative (lra_insn_recog_data_t data,
for (j = 0; j < nalt; j++) for (j = 0; j < nalt; j++)
for (i = 0; i < nop; i++, op_alt++) for (i = 0; i < nop; i++, op_alt++)
{ {
static_data->operand[i].early_clobber |= op_alt->earlyclobber;
if (op_alt->earlyclobber) if (op_alt->earlyclobber)
static_data->operand[i].early_clobber_alts |= (alternative_mask) 1 << j; static_data->operand[i].early_clobber_alts |= (alternative_mask) 1 << j;
static_data->operand[i].is_address |= op_alt->is_address; static_data->operand[i].is_address |= op_alt->is_address;
...@@ -878,10 +873,7 @@ collect_non_operand_hard_regs (rtx_insn *insn, rtx *x, ...@@ -878,10 +873,7 @@ collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
if (curr->type != type) if (curr->type != type)
curr->type = OP_INOUT; curr->type = OP_INOUT;
if (early_clobber) if (early_clobber)
{ curr->early_clobber_alts = ALL_ALTERNATIVES;
curr->early_clobber = true;
curr->early_clobber_alts = ALL_ALTERNATIVES;
}
break; break;
} }
if (curr == NULL) if (curr == NULL)
...@@ -897,7 +889,6 @@ collect_non_operand_hard_regs (rtx_insn *insn, rtx *x, ...@@ -897,7 +889,6 @@ collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
&& regno <= LAST_STACK_REG)); && regno <= LAST_STACK_REG));
#endif #endif
list = new_insn_reg (data->insn, regno, type, mode, subreg_p, list = new_insn_reg (data->insn, regno, type, mode, subreg_p,
early_clobber,
early_clobber ? ALL_ALTERNATIVES : 0, list, early_clobber ? ALL_ALTERNATIVES : 0, list,
clobber_high); clobber_high);
} }
...@@ -1449,15 +1440,13 @@ lra_get_copy (int n) ...@@ -1449,15 +1440,13 @@ lra_get_copy (int n)
/* This page contains code dealing with info about registers in /* This page contains code dealing with info about registers in
insns. */ insns. */
/* Process X of INSN recursively and add info (operand type is /* Process X of INSN recursively and add info (operand type is given
given by TYPE, flag of that it is early clobber is EARLY_CLOBBER) by TYPE) about registers in X to the insn DATA. If X can be early
about registers in X to the insn DATA. If X can be early clobbered, clobbered, alternatives in which it can be early clobbered are given
alternatives in which it can be early clobbered are given by by EARLY_CLOBBER_ALTS. */
EARLY_CLOBBER_ALTS. */
static void static void
add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
rtx_insn *insn, rtx_insn *insn, enum op_type type,
enum op_type type, bool early_clobber,
alternative_mask early_clobber_alts) alternative_mask early_clobber_alts)
{ {
int i, j, regno; int i, j, regno;
...@@ -1487,8 +1476,7 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, ...@@ -1487,8 +1476,7 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
if (bitmap_set_bit (&lra_reg_info[regno].insn_bitmap, INSN_UID (insn))) if (bitmap_set_bit (&lra_reg_info[regno].insn_bitmap, INSN_UID (insn)))
{ {
data->regs = new_insn_reg (data->insn, regno, type, mode, subreg_p, data->regs = new_insn_reg (data->insn, regno, type, mode, subreg_p,
early_clobber, early_clobber_alts, early_clobber_alts, data->regs, false);
data->regs, false);
return; return;
} }
else else
...@@ -1500,15 +1488,12 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, ...@@ -1500,15 +1488,12 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
/* The info cannot be integrated into the found /* The info cannot be integrated into the found
structure. */ structure. */
data->regs = new_insn_reg (data->insn, regno, type, mode, data->regs = new_insn_reg (data->insn, regno, type, mode,
subreg_p, early_clobber, subreg_p, early_clobber_alts,
early_clobber_alts, data->regs, data->regs, false);
false);
else else
{ {
if (curr->type != type) if (curr->type != type)
curr->type = OP_INOUT; curr->type = OP_INOUT;
if (curr->early_clobber != early_clobber)
curr->early_clobber = true;
curr->early_clobber_alts |= early_clobber_alts; curr->early_clobber_alts |= early_clobber_alts;
} }
return; return;
...@@ -1520,23 +1505,23 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, ...@@ -1520,23 +1505,23 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
switch (code) switch (code)
{ {
case SET: case SET:
add_regs_to_insn_regno_info (data, SET_DEST (x), insn, OP_OUT, false, 0); add_regs_to_insn_regno_info (data, SET_DEST (x), insn, OP_OUT, 0);
add_regs_to_insn_regno_info (data, SET_SRC (x), insn, OP_IN, false, 0); add_regs_to_insn_regno_info (data, SET_SRC (x), insn, OP_IN, 0);
break; break;
case CLOBBER: case CLOBBER:
/* We treat clobber of non-operand hard registers as early /* We treat clobber of non-operand hard registers as early
clobber. */ clobber. */
add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_OUT, add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_OUT,
true, ALL_ALTERNATIVES); ALL_ALTERNATIVES);
break; break;
case CLOBBER_HIGH: case CLOBBER_HIGH:
gcc_unreachable (); gcc_unreachable ();
case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC: case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC:
add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_INOUT, false, 0); add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_INOUT, 0);
break; break;
case PRE_MODIFY: case POST_MODIFY: case PRE_MODIFY: case POST_MODIFY:
add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_INOUT, false, 0); add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_INOUT, 0);
add_regs_to_insn_regno_info (data, XEXP (x, 1), insn, OP_IN, false, 0); add_regs_to_insn_regno_info (data, XEXP (x, 1), insn, OP_IN, 0);
break; break;
default: default:
if ((code != PARALLEL && code != EXPR_LIST) || type != OP_OUT) if ((code != PARALLEL && code != EXPR_LIST) || type != OP_OUT)
...@@ -1557,12 +1542,12 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, ...@@ -1557,12 +1542,12 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{ {
if (fmt[i] == 'e') if (fmt[i] == 'e')
add_regs_to_insn_regno_info (data, XEXP (x, i), insn, type, false, 0); add_regs_to_insn_regno_info (data, XEXP (x, i), insn, type, 0);
else if (fmt[i] == 'E') else if (fmt[i] == 'E')
{ {
for (j = XVECLEN (x, i) - 1; j >= 0; j--) for (j = XVECLEN (x, i) - 1; j >= 0; j--)
add_regs_to_insn_regno_info (data, XVECEXP (x, i, j), insn, add_regs_to_insn_regno_info (data, XVECEXP (x, i, j), insn,
type, false, 0); type, 0);
} }
} }
} }
...@@ -1652,11 +1637,10 @@ lra_update_insn_regno_info (rtx_insn *insn) ...@@ -1652,11 +1637,10 @@ lra_update_insn_regno_info (rtx_insn *insn)
for (i = static_data->n_operands - 1; i >= 0; i--) for (i = static_data->n_operands - 1; i >= 0; i--)
add_regs_to_insn_regno_info (data, *data->operand_loc[i], insn, add_regs_to_insn_regno_info (data, *data->operand_loc[i], insn,
static_data->operand[i].type, static_data->operand[i].type,
static_data->operand[i].early_clobber,
static_data->operand[i].early_clobber_alts); static_data->operand[i].early_clobber_alts);
if ((code = GET_CODE (PATTERN (insn))) == CLOBBER || code == USE) if ((code = GET_CODE (PATTERN (insn))) == CLOBBER || code == USE)
add_regs_to_insn_regno_info (data, XEXP (PATTERN (insn), 0), insn, add_regs_to_insn_regno_info (data, XEXP (PATTERN (insn), 0), insn,
code == USE ? OP_IN : OP_OUT, false, 0); code == USE ? OP_IN : OP_OUT, 0);
if (CALL_P (insn)) if (CALL_P (insn))
/* On some targets call insns can refer to pseudos in memory in /* On some targets call insns can refer to pseudos in memory in
CALL_INSN_FUNCTION_USAGE list. Process them in order to CALL_INSN_FUNCTION_USAGE list. Process them in order to
...@@ -1673,7 +1657,7 @@ lra_update_insn_regno_info (rtx_insn *insn) ...@@ -1673,7 +1657,7 @@ lra_update_insn_regno_info (rtx_insn *insn)
if ((code == USE || code == CLOBBER) if ((code == USE || code == CLOBBER)
&& MEM_P (XEXP (XEXP (link, 0), 0))) && MEM_P (XEXP (XEXP (link, 0), 0)))
add_regs_to_insn_regno_info (data, XEXP (XEXP (link, 0), 0), insn, add_regs_to_insn_regno_info (data, XEXP (XEXP (link, 0), 0), insn,
code == USE ? OP_IN : OP_OUT, false, 0); code == USE ? OP_IN : OP_OUT, 0);
} }
if (NONDEBUG_INSN_P (insn)) if (NONDEBUG_INSN_P (insn))
setup_insn_reg_info (data, freq); setup_insn_reg_info (data, freq);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment