aboutsummaryrefslogtreecommitdiff
path: root/gcc/lra.c
diff options
context:
space:
mode:
authorAlan Hayward <alan.hayward@arm.com>2018-08-06 09:51:01 +0000
committerAlan Hayward <alahay01@gcc.gnu.org>2018-08-06 09:51:01 +0000
commit30dc1902a777966dc1d1dad0fb5f19b7a960e5ca (patch)
tree72e457f4dfa5196e0fff6049463f9962e1b6b92b /gcc/lra.c
parent6a7fa0c213063683b2011c735bbf78ee8185fbfd (diff)
downloadgcc-30dc1902a777966dc1d1dad0fb5f19b7a960e5ca.zip
gcc-30dc1902a777966dc1d1dad0fb5f19b7a960e5ca.tar.gz
gcc-30dc1902a777966dc1d1dad0fb5f19b7a960e5ca.tar.bz2
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
Diffstat (limited to 'gcc/lra.c')
-rw-r--r--gcc/lra.c66
1 files changed, 46 insertions, 20 deletions
diff --git a/gcc/lra.c b/gcc/lra.c
index b410b90..aa768fb 100644
--- a/gcc/lra.c
+++ b/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);
}