Commit 30dc1902 by Alan Hayward Committed by Alan Hayward

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
parent 6a7fa0c2
2018-08-06 Alan Hayward <alan.hayward@arm.com> 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. * rtl.h (reg_is_clobbered_by_clobber_high): Add declarations.
* rtlanal.c (reg_is_clobbered_by_clobber_high): Add function. * rtlanal.c (reg_is_clobbered_by_clobber_high): Add function.
......
...@@ -654,6 +654,7 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode, ...@@ -654,6 +654,7 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
return x; return x;
case CLOBBER: case CLOBBER:
case CLOBBER_HIGH:
case SET: case SET:
gcc_unreachable (); gcc_unreachable ();
...@@ -806,6 +807,16 @@ mark_not_eliminable (rtx x, machine_mode mem_mode) ...@@ -806,6 +807,16 @@ mark_not_eliminable (rtx x, machine_mode mem_mode)
setup_can_eliminate (ep, false); setup_can_eliminate (ep, false);
return; 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 < &reg_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: case SET:
if (SET_DEST (x) == stack_pointer_rtx if (SET_DEST (x) == stack_pointer_rtx
&& GET_CODE (SET_SRC (x)) == PLUS && GET_CODE (SET_SRC (x)) == PLUS
......
...@@ -168,6 +168,8 @@ struct lra_insn_reg ...@@ -168,6 +168,8 @@ struct lra_insn_reg
/* True if there is an early clobber alternative for this /* True if there is an early clobber alternative for this
operand. */ operand. */
unsigned int early_clobber : 1; 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. */ /* The corresponding regno of the register. */
int regno; int regno;
/* Next reg info of the same insn. */ /* Next reg info of the same insn. */
......
...@@ -658,7 +658,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -658,7 +658,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
bool call_p; bool call_p;
int n_alt, dst_regno, src_regno; int n_alt, dst_regno, src_regno;
rtx set; rtx set;
struct lra_insn_reg *reg; struct lra_insn_reg *reg, *hr;
if (!NONDEBUG_INSN_P (curr_insn)) if (!NONDEBUG_INSN_P (curr_insn))
continue; continue;
...@@ -690,11 +690,12 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -690,11 +690,12 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
break; break;
} }
for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next) 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; remove_p = false;
break; break;
} }
if (remove_p && ! volatile_refs_p (PATTERN (curr_insn))) if (remove_p && ! volatile_refs_p (PATTERN (curr_insn)))
{ {
dst_regno = REGNO (SET_DEST (set)); dst_regno = REGNO (SET_DEST (set));
...@@ -812,14 +813,24 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -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 unused values because they still conflict with quantities
that are live at the time of the definition. */ that are live at the time of the definition. */
for (reg = curr_id->regs; reg != NULL; reg = reg->next) for (reg = curr_id->regs; reg != NULL; reg = reg->next)
if (reg->type != OP_IN) {
{ if (reg->type != OP_IN)
need_curr_point_incr {
|= mark_regno_live (reg->regno, reg->biggest_mode, need_curr_point_incr
curr_point); |= mark_regno_live (reg->regno, reg->biggest_mode,
check_pseudos_live_through_calls (reg->regno, curr_point);
last_call_used_reg_set); 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) for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
if (reg->type != OP_IN) if (reg->type != OP_IN)
......
...@@ -535,13 +535,14 @@ object_allocator<lra_insn_reg> lra_insn_reg_pool ("insn regs"); ...@@ -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 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. */ EARLY_CLOBBER_ALTS. CLOBBER_HIGH marks if reference is a clobber
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 early_clobber, bool subreg_p, bool early_clobber,
alternative_mask early_clobber_alts, 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 (); lra_insn_reg *ir = lra_insn_reg_pool.allocate ();
ir->type = type; ir->type = type;
...@@ -552,6 +553,7 @@ new_insn_reg (rtx_insn *insn, int regno, enum op_type type, ...@@ -552,6 +553,7 @@ new_insn_reg (rtx_insn *insn, int regno, enum op_type type,
ir->subreg_p = subreg_p; ir->subreg_p = subreg_p;
ir->early_clobber = early_clobber; 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->regno = regno; ir->regno = regno;
ir->next = next; ir->next = next;
return ir; return ir;
...@@ -821,12 +823,13 @@ setup_operand_alternative (lra_insn_recog_data_t data, ...@@ -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 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 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 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 * static struct lra_insn_reg *
collect_non_operand_hard_regs (rtx_insn *insn, rtx *x, collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
lra_insn_recog_data_t data, lra_insn_recog_data_t data,
struct lra_insn_reg *list, 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; int i, j, regno, last;
bool subreg_p; bool subreg_p;
...@@ -890,7 +893,8 @@ collect_non_operand_hard_regs (rtx_insn *insn, rtx *x, ...@@ -890,7 +893,8 @@ collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
#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,
early_clobber ? ALL_ALTERNATIVES : 0, list); early_clobber ? ALL_ALTERNATIVES : 0, list,
clobber_high);
} }
} }
return list; return list;
...@@ -899,24 +903,31 @@ collect_non_operand_hard_regs (rtx_insn *insn, rtx *x, ...@@ -899,24 +903,31 @@ collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
{ {
case SET: case SET:
list = collect_non_operand_hard_regs (insn, &SET_DEST (op), data, 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 = collect_non_operand_hard_regs (insn, &SET_SRC (op), data,
list, OP_IN, false); list, OP_IN, false, false);
break; break;
case CLOBBER: case CLOBBER:
/* We treat clobber of non-operand hard registers as early clobber. */ /* We treat clobber of non-operand hard registers as early clobber. */
list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data, 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; break;
case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC: case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC:
list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data, list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
list, OP_INOUT, false); list, OP_INOUT, false, false);
break; break;
case PRE_MODIFY: case POST_MODIFY: case PRE_MODIFY: case POST_MODIFY:
list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data, 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 = collect_non_operand_hard_regs (insn, &XEXP (op, 1), data,
list, OP_IN, false); list, OP_IN, false, false);
break; break;
default: default:
fmt = GET_RTX_FORMAT (code); fmt = GET_RTX_FORMAT (code);
...@@ -924,11 +935,12 @@ collect_non_operand_hard_regs (rtx_insn *insn, rtx *x, ...@@ -924,11 +935,12 @@ collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
{ {
if (fmt[i] == 'e') if (fmt[i] == 'e')
list = collect_non_operand_hard_regs (insn, &XEXP (op, i), data, 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') else if (fmt[i] == 'E')
for (j = XVECLEN (op, i) - 1; j >= 0; j--) for (j = XVECLEN (op, i) - 1; j >= 0; j--)
list = collect_non_operand_hard_regs (insn, &XVECEXP (op, i, 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; return list;
...@@ -1081,7 +1093,7 @@ lra_set_insn_recog_data (rtx_insn *insn) ...@@ -1081,7 +1093,7 @@ lra_set_insn_recog_data (rtx_insn *insn)
else else
insn_static_data->hard_regs insn_static_data->hard_regs
= collect_non_operand_hard_regs (insn, &PATTERN (insn), data, = collect_non_operand_hard_regs (insn, &PATTERN (insn), data,
NULL, OP_IN, false); NULL, OP_IN, false, false);
data->arg_hard_regs = NULL; data->arg_hard_regs = NULL;
if (CALL_P (insn)) if (CALL_P (insn))
{ {
...@@ -1107,6 +1119,11 @@ lra_set_insn_recog_data (rtx_insn *insn) ...@@ -1107,6 +1119,11 @@ lra_set_insn_recog_data (rtx_insn *insn)
arg_hard_regs[n_hard_regs++] arg_hard_regs[n_hard_regs++]
= regno + i + (use_p ? 0 : FIRST_PSEUDO_REGISTER); = 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) if (n_hard_regs != 0)
{ {
arg_hard_regs[n_hard_regs++] = -1; 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, ...@@ -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, data->regs = new_insn_reg (data->insn, regno, type, mode, subreg_p,
early_clobber, early_clobber_alts, early_clobber, early_clobber_alts,
data->regs); data->regs, false);
return; return;
} }
else else
...@@ -1482,7 +1499,8 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, ...@@ -1482,7 +1499,8 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
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,
early_clobber_alts, data->regs); early_clobber_alts, data->regs,
false);
else else
{ {
if (curr->type != type) if (curr->type != type)
...@@ -1509,6 +1527,8 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, ...@@ -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, add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_OUT,
true, ALL_ALTERNATIVES); true, ALL_ALTERNATIVES);
break; break;
case CLOBBER_HIGH:
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, false, 0);
break; break;
...@@ -1643,10 +1663,16 @@ lra_update_insn_regno_info (rtx_insn *insn) ...@@ -1643,10 +1663,16 @@ lra_update_insn_regno_info (rtx_insn *insn)
for (link = CALL_INSN_FUNCTION_USAGE (insn); for (link = CALL_INSN_FUNCTION_USAGE (insn);
link != NULL_RTX; link != NULL_RTX;
link = XEXP (link, 1)) link = XEXP (link, 1))
if (((code = GET_CODE (XEXP (link, 0))) == USE || code == CLOBBER) {
&& MEM_P (XEXP (XEXP (link, 0), 0))) code = GET_CODE (XEXP (link, 0));
add_regs_to_insn_regno_info (data, XEXP (XEXP (link, 0), 0), insn, /* We could support CLOBBER_HIGH and treat it in the same way as
code == USE ? OP_IN : OP_OUT, false, 0); 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)) 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