Commit 584898ee by Vladimir Makarov Committed by Vladimir Makarov

re PR target/79282 ([7 Regresion] FAIL: gcc.target/arm/neon-for-64bits-1.c…

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  <vmakarov@redhat.com>

	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
parent 2932fe90
2017-02-14 Vladimir Makarov <vmakarov@redhat.com>
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 <jakub@redhat.com> 2017-02-14 Jakub Jelinek <jakub@redhat.com>
PR middle-end/79505 PR middle-end/79505
......
...@@ -130,6 +130,8 @@ struct lra_operand_data ...@@ -130,6 +130,8 @@ struct lra_operand_data
{ {
/* The machine description constraint string of the operand. */ /* The machine description constraint string of the operand. */
const char *constraint; 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 /* It is taken only from machine description (which is different
from recog_data.operand_mode) and can be of VOIDmode. */ from recog_data.operand_mode) and can be of VOIDmode. */
ENUM_BITFIELD(machine_mode) mode : 16; ENUM_BITFIELD(machine_mode) mode : 16;
...@@ -150,6 +152,8 @@ struct lra_operand_data ...@@ -150,6 +152,8 @@ struct lra_operand_data
/* Info about register occurrence in an insn. */ /* Info about register occurrence in an insn. */
struct lra_insn_reg 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 /* The biggest mode through which the insn refers to the register
occurrence (remember the register can be accessed through a occurrence (remember the register can be accessed through a
subreg in the insn). */ subreg in the insn). */
......
...@@ -586,6 +586,16 @@ check_pseudos_live_through_calls (int regno, ...@@ -586,6 +586,16 @@ check_pseudos_live_through_calls (int regno,
SET_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs); 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, /* Process insns of the basic block BB to update pseudo live ranges,
pseudo hard register conflicts, and insn notes. We do it on pseudo hard register conflicts, and insn notes. We do it on
backward scan of BB insns. CURR_POINT is the program point where 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) ...@@ -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) FOR_BB_INSNS_REVERSE_SAFE (bb, curr_insn, next)
{ {
bool call_p; bool call_p;
int 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;
...@@ -647,9 +657,10 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -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_id = lra_get_insn_recog_data (curr_insn);
curr_static_id = curr_id->insn_static_data; curr_static_id = curr_id->insn_static_data;
n_alt = curr_id->used_insn_alternative;
if (lra_dump_file != NULL) if (lra_dump_file != NULL)
fprintf (lra_dump_file, " Insn %u: point = %d\n", fprintf (lra_dump_file, " Insn %u: point = %d, n_alt = %d\n",
INSN_UID (curr_insn), curr_point); INSN_UID (curr_insn), curr_point, n_alt);
set = single_set (curr_insn); set = single_set (curr_insn);
...@@ -818,13 +829,15 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -818,13 +829,15 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
/* See which defined values die here. */ /* See which defined values die here. */
for (reg = curr_id->regs; reg != NULL; reg = reg->next) 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 need_curr_point_incr
|= mark_regno_dead (reg->regno, reg->biggest_mode, |= mark_regno_dead (reg->regno, reg->biggest_mode,
curr_point); curr_point);
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_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); make_hard_regno_dead (reg->regno);
if (curr_id->arg_hard_regs != NULL) if (curr_id->arg_hard_regs != NULL)
...@@ -901,13 +914,15 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -901,13 +914,15 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
/* Mark early clobber outputs dead. */ /* Mark early clobber outputs dead. */
for (reg = curr_id->regs; reg != NULL; reg = reg->next) 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 need_curr_point_incr
|= mark_regno_dead (reg->regno, reg->biggest_mode, |= mark_regno_dead (reg->regno, reg->biggest_mode,
curr_point); curr_point);
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_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); make_hard_regno_dead (reg->regno);
if (need_curr_point_incr) if (need_curr_point_incr)
......
...@@ -529,15 +529,19 @@ lra_update_dups (lra_insn_recog_data_t id, signed char *nops) ...@@ -529,15 +529,19 @@ lra_update_dups (lra_insn_recog_data_t id, signed char *nops)
/* Pools for insn reg info. */ /* Pools for insn reg info. */
object_allocator<lra_insn_reg> lra_insn_reg_pool ("insn regs"); object_allocator<lra_insn_reg> lra_insn_reg_pool ("insn regs");
/* Create LRA insn related info about a reference to REGNO in INSN with /* Create LRA insn related info about a reference to REGNO in INSN
TYPE (in/out/inout), biggest reference mode MODE, flag that it is with TYPE (in/out/inout), biggest reference mode MODE, flag that it
reference through subreg (SUBREG_P), flag that is early clobbered is reference through subreg (SUBREG_P), flag that is early
in the insn (EARLY_CLOBBER), and reference to the next insn reg clobbered in the insn (EARLY_CLOBBER), and reference to the next
info (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 * 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, 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 (); lra_insn_reg *ir = lra_insn_reg_pool.allocate ();
ir->type = type; ir->type = type;
...@@ -547,6 +551,7 @@ new_insn_reg (rtx_insn *insn, int regno, enum op_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; lra_reg_info[regno].biggest_mode = mode;
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->regno = regno; ir->regno = regno;
ir->next = next; ir->next = next;
return ir; return ir;
...@@ -590,6 +595,7 @@ struct lra_static_insn_data *insn_code_data[NUM_INSN_CODES]; ...@@ -590,6 +595,7 @@ struct lra_static_insn_data *insn_code_data[NUM_INSN_CODES];
static struct lra_operand_data debug_operand_data = static struct lra_operand_data debug_operand_data =
{ {
NULL, /* alternative */ NULL, /* alternative */
0, /* early_clobber_alts */
VOIDmode, /* We are not interesting in the operand mode. */ VOIDmode, /* We are not interesting in the operand mode. */
OP_IN, OP_IN,
0, 0, 0, 0 0, 0, 0, 0
...@@ -771,6 +777,7 @@ setup_operand_alternative (lra_insn_recog_data_t data, ...@@ -771,6 +777,7 @@ setup_operand_alternative (lra_insn_recog_data_t data,
static_data->operand_alternative = op_alt; static_data->operand_alternative = op_alt;
for (i = 0; i < nop; i++) 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].early_clobber = false;
static_data->operand[i].is_address = false; static_data->operand[i].is_address = false;
if (static_data->operand[i].constraint[0] == '%') if (static_data->operand[i].constraint[0] == '%')
...@@ -788,6 +795,8 @@ setup_operand_alternative (lra_insn_recog_data_t data, ...@@ -788,6 +795,8 @@ setup_operand_alternative (lra_insn_recog_data_t data,
for (i = 0; i < nop; i++, op_alt++) for (i = 0; i < nop; i++, op_alt++)
{ {
static_data->operand[i].early_clobber |= op_alt->earlyclobber; 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; 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, ...@@ -847,8 +856,11 @@ collect_non_operand_hard_regs (rtx *x, lra_insn_recog_data_t data,
{ {
if (curr->type != type) if (curr->type != type)
curr->type = OP_INOUT; curr->type = OP_INOUT;
if (curr->early_clobber != early_clobber) if (early_clobber)
{
curr->early_clobber = true; curr->early_clobber = true;
curr->early_clobber_alts = ALL_ALTERNATIVES;
}
break; break;
} }
if (curr == NULL) if (curr == NULL)
...@@ -864,7 +876,8 @@ collect_non_operand_hard_regs (rtx *x, lra_insn_recog_data_t data, ...@@ -864,7 +876,8 @@ collect_non_operand_hard_regs (rtx *x, lra_insn_recog_data_t data,
&& regno <= LAST_STACK_REG)); && regno <= LAST_STACK_REG));
#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, list); early_clobber,
early_clobber ? ALL_ALTERNATIVES : 0, list);
} }
} }
return list; return list;
...@@ -1395,10 +1408,13 @@ lra_get_copy (int n) ...@@ -1395,10 +1408,13 @@ lra_get_copy (int n)
/* Process X of insn UID recursively and add info (operand type is /* 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) 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 static void
add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, int uid, 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; int i, j, regno;
bool subreg_p; bool subreg_p;
...@@ -1430,7 +1446,8 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, int uid, ...@@ -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)) if (bitmap_set_bit (&lra_reg_info[regno].insn_bitmap, uid))
{ {
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, data->regs); early_clobber, early_clobber_alts,
data->regs);
return; return;
} }
else else
...@@ -1443,13 +1460,14 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, int uid, ...@@ -1443,13 +1460,14 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, int uid,
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,
data->regs); early_clobber_alts, data->regs);
else else
{ {
if (curr->type != type) if (curr->type != type)
curr->type = OP_INOUT; curr->type = OP_INOUT;
if (curr->early_clobber != early_clobber) if (curr->early_clobber != early_clobber)
curr->early_clobber = true; curr->early_clobber = true;
curr->early_clobber_alts |= early_clobber_alts;
} }
return; return;
} }
...@@ -1460,20 +1478,20 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, int uid, ...@@ -1460,20 +1478,20 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, int uid,
switch (code) switch (code)
{ {
case SET: case SET:
add_regs_to_insn_regno_info (data, SET_DEST (x), uid, OP_OUT, 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); add_regs_to_insn_regno_info (data, SET_SRC (x), uid, OP_IN, false, 0);
break; break;
case CLOBBER: case CLOBBER:
/* We treat clobber of non-operand hard registers as early /* We treat clobber of non-operand hard registers as early
clobber (the behavior is expected from asm). */ 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; 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:
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; break;
case PRE_MODIFY: case POST_MODIFY: 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, 0), uid, OP_INOUT, false, 0);
add_regs_to_insn_regno_info (data, XEXP (x, 1), uid, OP_IN, false); add_regs_to_insn_regno_info (data, XEXP (x, 1), uid, OP_IN, false, 0);
break; break;
default: default:
if ((code != PARALLEL && code != EXPR_LIST) || type != OP_OUT) 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, ...@@ -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--) for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{ {
if (fmt[i] == 'e') 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') else if (fmt[i] == 'E')
{ {
for (j = XVECLEN (x, i) - 1; j >= 0; j--) for (j = XVECLEN (x, i) - 1; j >= 0; j--)
add_regs_to_insn_regno_info (data, XVECEXP (x, i, j), uid, 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) ...@@ -1590,10 +1608,11 @@ lra_update_insn_regno_info (rtx_insn *insn)
for (i = static_data->n_operands - 1; i >= 0; i--) for (i = static_data->n_operands - 1; i >= 0; i--)
add_regs_to_insn_regno_info (data, *data->operand_loc[i], uid, add_regs_to_insn_regno_info (data, *data->operand_loc[i], uid,
static_data->operand[i].type, 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) if ((code = GET_CODE (PATTERN (insn))) == CLOBBER || code == USE)
add_regs_to_insn_regno_info (data, XEXP (PATTERN (insn), 0), uid, 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)) if (CALL_P (insn))
/* On some targets call insns can refer to pseudos in memory in /* On some targets call insns can refer to pseudos in memory in
CALL_INSN_FUNCTION_USAGE list. Process them in order to CALL_INSN_FUNCTION_USAGE list. Process them in order to
...@@ -1605,7 +1624,7 @@ lra_update_insn_regno_info (rtx_insn *insn) ...@@ -1605,7 +1624,7 @@ lra_update_insn_regno_info (rtx_insn *insn)
if (((code = GET_CODE (XEXP (link, 0))) == USE || code == CLOBBER) if (((code = GET_CODE (XEXP (link, 0))) == USE || code == CLOBBER)
&& MEM_P (XEXP (XEXP (link, 0), 0))) && MEM_P (XEXP (XEXP (link, 0), 0)))
add_regs_to_insn_regno_info (data, XEXP (XEXP (link, 0), 0), uid, 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)) 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