lra support for clobber_high
gcc/ * lra-eliminations.c (lra_eliminate_regs_1): Check for clobber high. (mark_not_eliminable): Likewise. * lra-int.h (struct lra_insn_reg): Add clobber high marker. * lra-lives.c (process_bb_lives): Check for clobber high. * lra.c (new_insn_reg): Remember clobber highs. (collect_non_operand_hard_regs): Check for clobber high. (lra_set_insn_recog_data): Likewise. (add_regs_to_insn_regno_info): Likewise. (lra_update_insn_regno_info): Likewise. From-SVN: r263329
This commit is contained in:
parent
6a7fa0c213
commit
30dc1902a7
|
@ -1,3 +1,15 @@
|
|||
2018-08-06 Alan Hayward <alan.hayward@arm.com>
|
||||
|
||||
* lra-eliminations.c (lra_eliminate_regs_1): Check for clobber high.
|
||||
(mark_not_eliminable): Likewise.
|
||||
* lra-int.h (struct lra_insn_reg): Add clobber high marker.
|
||||
* lra-lives.c (process_bb_lives): Check for clobber high.
|
||||
* lra.c (new_insn_reg): Remember clobber highs.
|
||||
(collect_non_operand_hard_regs): Check for clobber high.
|
||||
(lra_set_insn_recog_data): Likewise.
|
||||
(add_regs_to_insn_regno_info): Likewise.
|
||||
(lra_update_insn_regno_info): Likewise.
|
||||
|
||||
2018-08-06 Alan Hayward <alan.hayward@arm.com>
|
||||
|
||||
* rtl.h (reg_is_clobbered_by_clobber_high): Add declarations.
|
||||
|
|
|
@ -654,6 +654,7 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
|
|||
return x;
|
||||
|
||||
case CLOBBER:
|
||||
case CLOBBER_HIGH:
|
||||
case SET:
|
||||
gcc_unreachable ();
|
||||
|
||||
|
@ -806,6 +807,16 @@ mark_not_eliminable (rtx x, machine_mode mem_mode)
|
|||
setup_can_eliminate (ep, false);
|
||||
return;
|
||||
|
||||
case CLOBBER_HIGH:
|
||||
gcc_assert (REG_P (XEXP (x, 0)));
|
||||
gcc_assert (REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER);
|
||||
for (ep = reg_eliminate;
|
||||
ep < ®_eliminate[NUM_ELIMINABLE_REGS];
|
||||
ep++)
|
||||
if (reg_is_clobbered_by_clobber_high (ep->to_rtx, XEXP (x, 0)))
|
||||
setup_can_eliminate (ep, false);
|
||||
return;
|
||||
|
||||
case SET:
|
||||
if (SET_DEST (x) == stack_pointer_rtx
|
||||
&& GET_CODE (SET_SRC (x)) == PLUS
|
||||
|
|
|
@ -168,6 +168,8 @@ struct lra_insn_reg
|
|||
/* 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. */
|
||||
unsigned int clobber_high : 1;
|
||||
/* The corresponding regno of the register. */
|
||||
int regno;
|
||||
/* Next reg info of the same insn. */
|
||||
|
|
|
@ -658,7 +658,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
|
|||
bool call_p;
|
||||
int n_alt, dst_regno, src_regno;
|
||||
rtx set;
|
||||
struct lra_insn_reg *reg;
|
||||
struct lra_insn_reg *reg, *hr;
|
||||
|
||||
if (!NONDEBUG_INSN_P (curr_insn))
|
||||
continue;
|
||||
|
@ -690,11 +690,12 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
|
|||
break;
|
||||
}
|
||||
for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
|
||||
if (reg->type != OP_IN)
|
||||
if (reg->type != OP_IN && !reg->clobber_high)
|
||||
{
|
||||
remove_p = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (remove_p && ! volatile_refs_p (PATTERN (curr_insn)))
|
||||
{
|
||||
dst_regno = REGNO (SET_DEST (set));
|
||||
|
@ -812,14 +813,24 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
|
|||
unused values because they still conflict with quantities
|
||||
that are live at the time of the definition. */
|
||||
for (reg = curr_id->regs; reg != NULL; reg = reg->next)
|
||||
if (reg->type != OP_IN)
|
||||
{
|
||||
need_curr_point_incr
|
||||
|= mark_regno_live (reg->regno, reg->biggest_mode,
|
||||
curr_point);
|
||||
check_pseudos_live_through_calls (reg->regno,
|
||||
last_call_used_reg_set);
|
||||
}
|
||||
{
|
||||
if (reg->type != OP_IN)
|
||||
{
|
||||
need_curr_point_incr
|
||||
|= mark_regno_live (reg->regno, reg->biggest_mode,
|
||||
curr_point);
|
||||
check_pseudos_live_through_calls (reg->regno,
|
||||
last_call_used_reg_set);
|
||||
}
|
||||
|
||||
if (reg->regno >= FIRST_PSEUDO_REGISTER)
|
||||
for (hr = curr_static_id->hard_regs; hr != NULL; hr = hr->next)
|
||||
if (hr->clobber_high
|
||||
&& maybe_gt (GET_MODE_SIZE (PSEUDO_REGNO_MODE (reg->regno)),
|
||||
GET_MODE_SIZE (hr->biggest_mode)))
|
||||
SET_HARD_REG_BIT (lra_reg_info[reg->regno].conflict_hard_regs,
|
||||
hr->regno);
|
||||
}
|
||||
|
||||
for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
|
||||
if (reg->type != OP_IN)
|
||||
|
|
66
gcc/lra.c
66
gcc/lra.c
|
@ -535,13 +535,14 @@ object_allocator<lra_insn_reg> lra_insn_reg_pool ("insn regs");
|
|||
clobbered in the insn (EARLY_CLOBBER), and reference to the next
|
||||
insn reg info (NEXT). If REGNO can be early clobbered,
|
||||
alternatives in which it can be early clobbered are given by
|
||||
EARLY_CLOBBER_ALTS. */
|
||||
EARLY_CLOBBER_ALTS. CLOBBER_HIGH marks if reference is a clobber
|
||||
high. */
|
||||
static struct lra_insn_reg *
|
||||
new_insn_reg (rtx_insn *insn, int regno, enum op_type type,
|
||||
machine_mode mode,
|
||||
bool subreg_p, bool early_clobber,
|
||||
alternative_mask early_clobber_alts,
|
||||
struct lra_insn_reg *next)
|
||||
struct lra_insn_reg *next, bool clobber_high)
|
||||
{
|
||||
lra_insn_reg *ir = lra_insn_reg_pool.allocate ();
|
||||
ir->type = type;
|
||||
|
@ -552,6 +553,7 @@ new_insn_reg (rtx_insn *insn, int regno, enum op_type type,
|
|||
ir->subreg_p = subreg_p;
|
||||
ir->early_clobber = early_clobber;
|
||||
ir->early_clobber_alts = early_clobber_alts;
|
||||
ir->clobber_high = clobber_high;
|
||||
ir->regno = regno;
|
||||
ir->next = next;
|
||||
return ir;
|
||||
|
@ -821,12 +823,13 @@ setup_operand_alternative (lra_insn_recog_data_t data,
|
|||
not the insn operands, in X with TYPE (in/out/inout) and flag that
|
||||
it is early clobbered in the insn (EARLY_CLOBBER) and add the info
|
||||
to LIST. X is a part of insn given by DATA. Return the result
|
||||
list. */
|
||||
list. CLOBBER_HIGH marks if X is a clobber high. */
|
||||
static struct lra_insn_reg *
|
||||
collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
|
||||
lra_insn_recog_data_t data,
|
||||
struct lra_insn_reg *list,
|
||||
enum op_type type, bool early_clobber)
|
||||
enum op_type type, bool early_clobber,
|
||||
bool clobber_high)
|
||||
{
|
||||
int i, j, regno, last;
|
||||
bool subreg_p;
|
||||
|
@ -890,7 +893,8 @@ collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
|
|||
#endif
|
||||
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);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
|
@ -899,24 +903,31 @@ collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
|
|||
{
|
||||
case SET:
|
||||
list = collect_non_operand_hard_regs (insn, &SET_DEST (op), data,
|
||||
list, OP_OUT, false);
|
||||
list, OP_OUT, false, false);
|
||||
list = collect_non_operand_hard_regs (insn, &SET_SRC (op), data,
|
||||
list, OP_IN, false);
|
||||
list, OP_IN, false, false);
|
||||
break;
|
||||
case CLOBBER:
|
||||
/* We treat clobber of non-operand hard registers as early clobber. */
|
||||
list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
|
||||
list, OP_OUT, true);
|
||||
list, OP_OUT, true, false);
|
||||
break;
|
||||
case CLOBBER_HIGH:
|
||||
/* Clobber high should always span exactly one register. */
|
||||
gcc_assert (REG_NREGS (XEXP (op, 0)) == 1);
|
||||
/* We treat clobber of non-operand hard registers as early clobber. */
|
||||
list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
|
||||
list, OP_OUT, true, true);
|
||||
break;
|
||||
case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC:
|
||||
list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
|
||||
list, OP_INOUT, false);
|
||||
list, OP_INOUT, false, false);
|
||||
break;
|
||||
case PRE_MODIFY: case POST_MODIFY:
|
||||
list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
|
||||
list, OP_INOUT, false);
|
||||
list, OP_INOUT, false, false);
|
||||
list = collect_non_operand_hard_regs (insn, &XEXP (op, 1), data,
|
||||
list, OP_IN, false);
|
||||
list, OP_IN, false, false);
|
||||
break;
|
||||
default:
|
||||
fmt = GET_RTX_FORMAT (code);
|
||||
|
@ -924,11 +935,12 @@ collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
|
|||
{
|
||||
if (fmt[i] == 'e')
|
||||
list = collect_non_operand_hard_regs (insn, &XEXP (op, i), data,
|
||||
list, OP_IN, false);
|
||||
list, OP_IN, false, false);
|
||||
else if (fmt[i] == 'E')
|
||||
for (j = XVECLEN (op, i) - 1; j >= 0; j--)
|
||||
list = collect_non_operand_hard_regs (insn, &XVECEXP (op, i, j),
|
||||
data, list, OP_IN, false);
|
||||
data, list, OP_IN, false,
|
||||
false);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
|
@ -1081,7 +1093,7 @@ lra_set_insn_recog_data (rtx_insn *insn)
|
|||
else
|
||||
insn_static_data->hard_regs
|
||||
= collect_non_operand_hard_regs (insn, &PATTERN (insn), data,
|
||||
NULL, OP_IN, false);
|
||||
NULL, OP_IN, false, false);
|
||||
data->arg_hard_regs = NULL;
|
||||
if (CALL_P (insn))
|
||||
{
|
||||
|
@ -1107,6 +1119,11 @@ lra_set_insn_recog_data (rtx_insn *insn)
|
|||
arg_hard_regs[n_hard_regs++]
|
||||
= regno + i + (use_p ? 0 : FIRST_PSEUDO_REGISTER);
|
||||
}
|
||||
else if (GET_CODE (XEXP (link, 0)) == CLOBBER_HIGH)
|
||||
/* We could support CLOBBER_HIGH and treat it in the same way as
|
||||
HARD_REGNO_CALL_PART_CLOBBERED, but no port needs that yet. */
|
||||
gcc_unreachable ();
|
||||
|
||||
if (n_hard_regs != 0)
|
||||
{
|
||||
arg_hard_regs[n_hard_regs++] = -1;
|
||||
|
@ -1469,7 +1486,7 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
|
|||
{
|
||||
data->regs = new_insn_reg (data->insn, regno, type, mode, subreg_p,
|
||||
early_clobber, early_clobber_alts,
|
||||
data->regs);
|
||||
data->regs, false);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
@ -1482,7 +1499,8 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
|
|||
structure. */
|
||||
data->regs = new_insn_reg (data->insn, regno, type, mode,
|
||||
subreg_p, early_clobber,
|
||||
early_clobber_alts, data->regs);
|
||||
early_clobber_alts, data->regs,
|
||||
false);
|
||||
else
|
||||
{
|
||||
if (curr->type != type)
|
||||
|
@ -1509,6 +1527,8 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
|
|||
add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_OUT,
|
||||
true, ALL_ALTERNATIVES);
|
||||
break;
|
||||
case CLOBBER_HIGH:
|
||||
gcc_unreachable ();
|
||||
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);
|
||||
break;
|
||||
|
@ -1643,10 +1663,16 @@ lra_update_insn_regno_info (rtx_insn *insn)
|
|||
for (link = CALL_INSN_FUNCTION_USAGE (insn);
|
||||
link != NULL_RTX;
|
||||
link = XEXP (link, 1))
|
||||
if (((code = GET_CODE (XEXP (link, 0))) == USE || code == CLOBBER)
|
||||
&& MEM_P (XEXP (XEXP (link, 0), 0)))
|
||||
add_regs_to_insn_regno_info (data, XEXP (XEXP (link, 0), 0), insn,
|
||||
code == USE ? OP_IN : OP_OUT, false, 0);
|
||||
{
|
||||
code = GET_CODE (XEXP (link, 0));
|
||||
/* We could support CLOBBER_HIGH and treat it in the same way as
|
||||
HARD_REGNO_CALL_PART_CLOBBERED, but no port needs that yet. */
|
||||
gcc_assert (code != CLOBBER_HIGH);
|
||||
if ((code == USE || code == CLOBBER)
|
||||
&& MEM_P (XEXP (XEXP (link, 0), 0)))
|
||||
add_regs_to_insn_regno_info (data, XEXP (XEXP (link, 0), 0), insn,
|
||||
code == USE ? OP_IN : OP_OUT, false, 0);
|
||||
}
|
||||
if (NONDEBUG_INSN_P (insn))
|
||||
setup_insn_reg_info (data, freq);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue