From 584898ee80100dcdda3f0eb3cbf151976843055d Mon Sep 17 00:00:00 2001 From: Vladimir Makarov Date: Tue, 14 Feb 2017 22:17:19 +0000 Subject: [PATCH] re PR target/79282 ([7 Regresion] FAIL: gcc.target/arm/neon-for-64bits-1.c scan-assembler-times vshr 0) 2017-02-14 Vladimir Makarov PR target/79282 * lra-int.h (struct lra_operand_data, struct lra_insn_reg): Add member early_clobber_alts. * lra-lives.c (reg_early_clobber_p): New. (process_bb_lives): Use it. * lra.c (new_insn_reg): New arg early_clobber_alts. Use it. (debug_operand_data): Initialize early_clobber_alts. (setup_operand_alternative): Set up early_clobber_alts. (collect_non_operand_hard_regs): Ditto. Pass early clobber alternatives to new_insn_reg. (add_regs_to_insn_regno_info): Add arg early_clobber_alts. Use it. (lra_update_insn_regno_info): Pass the new arg. From-SVN: r245459 --- gcc/ChangeLog | 16 ++++++++++++ gcc/lra-int.h | 4 +++ gcc/lra-lives.c | 29 +++++++++++++++------ gcc/lra.c | 67 +++++++++++++++++++++++++++++++------------------ 4 files changed, 85 insertions(+), 31 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 83d4e8f7883..43f404303ee 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2017-02-14 Vladimir Makarov + + PR target/79282 + * lra-int.h (struct lra_operand_data, struct lra_insn_reg): Add + member early_clobber_alts. + * lra-lives.c (reg_early_clobber_p): New. + (process_bb_lives): Use it. + * lra.c (new_insn_reg): New arg early_clobber_alts. Use it. + (debug_operand_data): Initialize early_clobber_alts. + (setup_operand_alternative): Set up early_clobber_alts. + (collect_non_operand_hard_regs): Ditto. Pass early clobber + alternatives to new_insn_reg. + (add_regs_to_insn_regno_info): Add arg early_clobber_alts. Use + it. + (lra_update_insn_regno_info): Pass the new arg. + 2017-02-14 Jakub Jelinek PR middle-end/79505 diff --git a/gcc/lra-int.h b/gcc/lra-int.h index d25d827a5d4..405071708b1 100644 --- a/gcc/lra-int.h +++ b/gcc/lra-int.h @@ -130,6 +130,8 @@ struct lra_operand_data { /* The machine description constraint string of the operand. */ const char *constraint; + /* Alternatives for which early_clobber can be true. */ + alternative_mask early_clobber_alts; /* It is taken only from machine description (which is different from recog_data.operand_mode) and can be of VOIDmode. */ ENUM_BITFIELD(machine_mode) mode : 16; @@ -150,6 +152,8 @@ struct lra_operand_data /* Info about register occurrence in an insn. */ struct lra_insn_reg { + /* Alternatives for which early_clobber can be true. */ + alternative_mask early_clobber_alts; /* The biggest mode through which the insn refers to the register occurrence (remember the register can be accessed through a subreg in the insn). */ diff --git a/gcc/lra-lives.c b/gcc/lra-lives.c index f0194387c63..5d4015b5ab9 100644 --- a/gcc/lra-lives.c +++ b/gcc/lra-lives.c @@ -586,6 +586,16 @@ check_pseudos_live_through_calls (int regno, SET_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs); } +/* Return true if insn REG is an early clobber operand in alternative + NALT. Negative NALT means that we don't know the current insn + alternative. So assume the worst. */ +static inline bool +reg_early_clobber_p (const struct lra_insn_reg *reg, int n_alt) +{ + return (reg->early_clobber + && (n_alt < 0 || TEST_BIT (reg->early_clobber_alts, n_alt))); +} + /* Process insns of the basic block BB to update pseudo live ranges, pseudo hard register conflicts, and insn notes. We do it on backward scan of BB insns. CURR_POINT is the program point where @@ -638,7 +648,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) FOR_BB_INSNS_REVERSE_SAFE (bb, curr_insn, next) { bool call_p; - int dst_regno, src_regno; + int n_alt, dst_regno, src_regno; rtx set; struct lra_insn_reg *reg; @@ -647,9 +657,10 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) curr_id = lra_get_insn_recog_data (curr_insn); curr_static_id = curr_id->insn_static_data; + n_alt = curr_id->used_insn_alternative; if (lra_dump_file != NULL) - fprintf (lra_dump_file, " Insn %u: point = %d\n", - INSN_UID (curr_insn), curr_point); + fprintf (lra_dump_file, " Insn %u: point = %d, n_alt = %d\n", + INSN_UID (curr_insn), curr_point, n_alt); set = single_set (curr_insn); @@ -818,13 +829,15 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) /* See which defined values die here. */ for (reg = curr_id->regs; reg != NULL; reg = reg->next) - if (reg->type == OP_OUT && ! reg->early_clobber && ! reg->subreg_p) + if (reg->type == OP_OUT + && ! reg_early_clobber_p (reg, n_alt) && ! reg->subreg_p) need_curr_point_incr |= mark_regno_dead (reg->regno, reg->biggest_mode, curr_point); for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next) - if (reg->type == OP_OUT && ! reg->early_clobber && ! reg->subreg_p) + if (reg->type == OP_OUT + && ! reg_early_clobber_p (reg, n_alt) && ! reg->subreg_p) make_hard_regno_dead (reg->regno); if (curr_id->arg_hard_regs != NULL) @@ -901,13 +914,15 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) /* Mark early clobber outputs dead. */ for (reg = curr_id->regs; reg != NULL; reg = reg->next) - if (reg->type == OP_OUT && reg->early_clobber && ! reg->subreg_p) + if (reg->type == OP_OUT + && reg_early_clobber_p (reg, n_alt) && ! reg->subreg_p) need_curr_point_incr |= mark_regno_dead (reg->regno, reg->biggest_mode, curr_point); for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next) - if (reg->type == OP_OUT && reg->early_clobber && ! reg->subreg_p) + if (reg->type == OP_OUT + && reg_early_clobber_p (reg, n_alt) && ! reg->subreg_p) make_hard_regno_dead (reg->regno); if (need_curr_point_incr) diff --git a/gcc/lra.c b/gcc/lra.c index 9be0053f543..d551102c8c9 100644 --- a/gcc/lra.c +++ b/gcc/lra.c @@ -529,15 +529,19 @@ lra_update_dups (lra_insn_recog_data_t id, signed char *nops) /* Pools for insn reg info. */ object_allocator lra_insn_reg_pool ("insn regs"); -/* Create LRA insn related info about a reference to REGNO in INSN with - TYPE (in/out/inout), biggest reference mode MODE, flag that it is - reference through subreg (SUBREG_P), flag that is early clobbered - in the insn (EARLY_CLOBBER), and reference to the next insn reg - info (NEXT). */ +/* Create LRA insn related info about a reference to REGNO in INSN + with TYPE (in/out/inout), biggest reference mode MODE, flag that it + is reference through subreg (SUBREG_P), flag that is early + 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. */ 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, struct lra_insn_reg *next) + bool subreg_p, bool early_clobber, + alternative_mask early_clobber_alts, + struct lra_insn_reg *next) { lra_insn_reg *ir = lra_insn_reg_pool.allocate (); ir->type = type; @@ -547,6 +551,7 @@ new_insn_reg (rtx_insn *insn, int regno, enum op_type type, lra_reg_info[regno].biggest_mode = mode; ir->subreg_p = subreg_p; ir->early_clobber = early_clobber; + ir->early_clobber_alts = early_clobber_alts; ir->regno = regno; ir->next = next; return ir; @@ -590,6 +595,7 @@ struct lra_static_insn_data *insn_code_data[NUM_INSN_CODES]; static struct lra_operand_data debug_operand_data = { NULL, /* alternative */ + 0, /* early_clobber_alts */ VOIDmode, /* We are not interesting in the operand mode. */ OP_IN, 0, 0, 0, 0 @@ -771,6 +777,7 @@ setup_operand_alternative (lra_insn_recog_data_t data, static_data->operand_alternative = op_alt; for (i = 0; i < nop; i++) { + static_data->operand[i].early_clobber_alts = 0; static_data->operand[i].early_clobber = false; static_data->operand[i].is_address = false; if (static_data->operand[i].constraint[0] == '%') @@ -788,6 +795,8 @@ setup_operand_alternative (lra_insn_recog_data_t data, for (i = 0; i < nop; i++, op_alt++) { static_data->operand[i].early_clobber |= op_alt->earlyclobber; + if (op_alt->earlyclobber) + static_data->operand[i].early_clobber_alts |= (alternative_mask) 1 << j; static_data->operand[i].is_address |= op_alt->is_address; } } @@ -847,8 +856,11 @@ collect_non_operand_hard_regs (rtx *x, lra_insn_recog_data_t data, { if (curr->type != type) curr->type = OP_INOUT; - if (curr->early_clobber != early_clobber) - curr->early_clobber = true; + if (early_clobber) + { + curr->early_clobber = true; + curr->early_clobber_alts = ALL_ALTERNATIVES; + } break; } if (curr == NULL) @@ -864,7 +876,8 @@ collect_non_operand_hard_regs (rtx *x, lra_insn_recog_data_t data, && regno <= LAST_STACK_REG)); #endif list = new_insn_reg (data->insn, regno, type, mode, subreg_p, - early_clobber, list); + early_clobber, + early_clobber ? ALL_ALTERNATIVES : 0, list); } } return list; @@ -1395,10 +1408,13 @@ lra_get_copy (int n) /* Process X of insn UID recursively and add info (operand type is given by TYPE, flag of that it is early clobber is EARLY_CLOBBER) - about registers in X to the insn DATA. */ + about registers in X to the insn DATA. If X can be early clobbered, + alternatives in which it can be early clobbered are given by + EARLY_CLOBBER_ALTS. */ static void add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, int uid, - enum op_type type, bool early_clobber) + enum op_type type, bool early_clobber, + alternative_mask early_clobber_alts) { int i, j, regno; bool subreg_p; @@ -1430,7 +1446,8 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, int uid, if (bitmap_set_bit (&lra_reg_info[regno].insn_bitmap, uid)) { data->regs = new_insn_reg (data->insn, regno, type, mode, subreg_p, - early_clobber, data->regs); + early_clobber, early_clobber_alts, + data->regs); return; } else @@ -1443,13 +1460,14 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, int uid, structure. */ data->regs = new_insn_reg (data->insn, regno, type, mode, subreg_p, early_clobber, - data->regs); + early_clobber_alts, data->regs); else { if (curr->type != type) curr->type = OP_INOUT; if (curr->early_clobber != early_clobber) curr->early_clobber = true; + curr->early_clobber_alts |= early_clobber_alts; } return; } @@ -1460,20 +1478,20 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, int uid, switch (code) { case SET: - add_regs_to_insn_regno_info (data, SET_DEST (x), uid, OP_OUT, false); - add_regs_to_insn_regno_info (data, SET_SRC (x), uid, OP_IN, false); + add_regs_to_insn_regno_info (data, SET_DEST (x), uid, OP_OUT, false, 0); + add_regs_to_insn_regno_info (data, SET_SRC (x), uid, OP_IN, false, 0); break; case CLOBBER: /* We treat clobber of non-operand hard registers as early clobber (the behavior is expected from asm). */ - add_regs_to_insn_regno_info (data, XEXP (x, 0), uid, OP_OUT, true); + add_regs_to_insn_regno_info (data, XEXP (x, 0), uid, OP_OUT, true, ALL_ALTERNATIVES); break; case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC: - add_regs_to_insn_regno_info (data, XEXP (x, 0), uid, OP_INOUT, false); + add_regs_to_insn_regno_info (data, XEXP (x, 0), uid, OP_INOUT, false, 0); break; case PRE_MODIFY: case POST_MODIFY: - add_regs_to_insn_regno_info (data, XEXP (x, 0), uid, OP_INOUT, false); - add_regs_to_insn_regno_info (data, XEXP (x, 1), uid, OP_IN, false); + add_regs_to_insn_regno_info (data, XEXP (x, 0), uid, OP_INOUT, false, 0); + add_regs_to_insn_regno_info (data, XEXP (x, 1), uid, OP_IN, false, 0); break; default: if ((code != PARALLEL && code != EXPR_LIST) || type != OP_OUT) @@ -1494,12 +1512,12 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, int uid, for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') - add_regs_to_insn_regno_info (data, XEXP (x, i), uid, type, false); + add_regs_to_insn_regno_info (data, XEXP (x, i), uid, type, false, 0); else if (fmt[i] == 'E') { for (j = XVECLEN (x, i) - 1; j >= 0; j--) add_regs_to_insn_regno_info (data, XVECEXP (x, i, j), uid, - type, false); + type, false, 0); } } } @@ -1590,10 +1608,11 @@ lra_update_insn_regno_info (rtx_insn *insn) for (i = static_data->n_operands - 1; i >= 0; i--) add_regs_to_insn_regno_info (data, *data->operand_loc[i], uid, static_data->operand[i].type, - static_data->operand[i].early_clobber); + static_data->operand[i].early_clobber, + static_data->operand[i].early_clobber_alts); if ((code = GET_CODE (PATTERN (insn))) == CLOBBER || code == USE) add_regs_to_insn_regno_info (data, XEXP (PATTERN (insn), 0), uid, - code == USE ? OP_IN : OP_OUT, false); + code == USE ? OP_IN : OP_OUT, false, 0); if (CALL_P (insn)) /* On some targets call insns can refer to pseudos in memory in CALL_INSN_FUNCTION_USAGE list. Process them in order to @@ -1605,7 +1624,7 @@ lra_update_insn_regno_info (rtx_insn *insn) 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), uid, - code == USE ? OP_IN : OP_OUT, false); + code == USE ? OP_IN : OP_OUT, false, 0); if (NONDEBUG_INSN_P (insn)) setup_insn_reg_info (data, freq); } -- 2.30.2