diff options
author | Alan Hayward <alan.hayward@arm.com> | 2018-08-06 09:51:01 +0000 |
---|---|---|
committer | Alan Hayward <alahay01@gcc.gnu.org> | 2018-08-06 09:51:01 +0000 |
commit | 30dc1902a777966dc1d1dad0fb5f19b7a960e5ca (patch) | |
tree | 72e457f4dfa5196e0fff6049463f9962e1b6b92b /gcc/lra.c | |
parent | 6a7fa0c213063683b2011c735bbf78ee8185fbfd (diff) | |
download | gcc-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.c | 66 |
1 files changed, 46 insertions, 20 deletions
@@ -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); } |