mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-28 16:01:00 +08:00
Fix latent LRA remat issue (PR68730)
PR rtl-optimization/68730 * lra-remat.c (insn_to_cand_activation): New static variable. (lra_remat): Allocate and free it. (create_cand): New arg activation. Initialize a field in insn_to_cand_activation if it is nonnull. (create_cands): Pass the activation insn to create_cand when making a candidate involving an output reload. Reorganize code a little. (do_remat): Keep track of active status of candidates in a separate bitmap. From-SVN: r233215
This commit is contained in:
parent
cc07da33ae
commit
ae9dd7f3f8
@ -1,3 +1,15 @@
|
||||
2016-02-08 Bernd Schmidt <bschmidt@redhat.com>
|
||||
|
||||
PR rtl-optimization/68730
|
||||
* lra-remat.c (insn_to_cand_activation): New static variable.
|
||||
(lra_remat): Allocate and free it.
|
||||
(create_cand): New arg activation. Initialize a field in
|
||||
insn_to_cand_activation if it is nonnull.
|
||||
(create_cands): Pass the activation insn to create_cand when making
|
||||
a candidate involving an output reload. Reorganize code a little.
|
||||
(do_remat): Keep track of active status of candidates in a separate
|
||||
bitmap.
|
||||
|
||||
2016-02-08 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/69719
|
||||
@ -30,7 +42,6 @@
|
||||
* tree-ssa-scopedtables.c
|
||||
(const_and_copies::record_const_or_copy_raw): New, factored out of
|
||||
(const_and_copies::record_const_or_copy): Call new member function.
|
||||
|
||||
|
||||
2016-02-05 Jeff Law <law@redhat.com>
|
||||
|
||||
|
113
gcc/lra-remat.c
113
gcc/lra-remat.c
@ -112,6 +112,10 @@ static vec<cand_t> all_cands;
|
||||
/* Map: insn -> candidate representing it. It is null if the insn can
|
||||
not be used for rematerialization. */
|
||||
static cand_t *insn_to_cand;
|
||||
/* A secondary map, for candidates that involve two insns, where the
|
||||
second one makes the equivalence. The candidate must not be used
|
||||
before seeing this activation insn. */
|
||||
static cand_t *insn_to_cand_activation;
|
||||
|
||||
/* Map regno -> candidates can be used for the regno
|
||||
rematerialization. */
|
||||
@ -461,7 +465,7 @@ operand_to_remat (rtx_insn *insn)
|
||||
REGNO. Insert the candidate into the table and set up the
|
||||
corresponding INSN_TO_CAND element. */
|
||||
static void
|
||||
create_cand (rtx_insn *insn, int nop, int regno)
|
||||
create_cand (rtx_insn *insn, int nop, int regno, rtx_insn *activation = NULL)
|
||||
{
|
||||
lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
|
||||
rtx reg = *id->operand_loc[nop];
|
||||
@ -486,6 +490,8 @@ create_cand (rtx_insn *insn, int nop, int regno)
|
||||
cand->next_regno_cand = regno_cands[cand->regno];
|
||||
regno_cands[cand->regno] = cand;
|
||||
}
|
||||
if (activation)
|
||||
insn_to_cand_activation[INSN_UID (activation)] = cand_in_table;
|
||||
}
|
||||
|
||||
/* Create rematerialization candidates (inserting them into the
|
||||
@ -504,43 +510,55 @@ create_cands (void)
|
||||
/* Create candidates. */
|
||||
regno_potential_cand = XCNEWVEC (struct potential_cand, max_reg_num ());
|
||||
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
|
||||
if (INSN_P (insn))
|
||||
if (NONDEBUG_INSN_P (insn))
|
||||
{
|
||||
rtx set;
|
||||
int src_regno, dst_regno;
|
||||
rtx_insn *insn2;
|
||||
lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
|
||||
int nop = operand_to_remat (insn);
|
||||
int regno = -1;
|
||||
int keep_regno = -1;
|
||||
rtx set = single_set (insn);
|
||||
int nop;
|
||||
|
||||
if ((set = single_set (insn)) != NULL
|
||||
&& REG_P (SET_SRC (set)) && REG_P (SET_DEST (set))
|
||||
&& ((src_regno = REGNO (SET_SRC (set)))
|
||||
>= lra_constraint_new_regno_start)
|
||||
&& (dst_regno = REGNO (SET_DEST (set))) >= FIRST_PSEUDO_REGISTER
|
||||
&& reg_renumber[dst_regno] < 0
|
||||
&& (insn2 = regno_potential_cand[src_regno].insn) != NULL
|
||||
&& BLOCK_FOR_INSN (insn2) == BLOCK_FOR_INSN (insn))
|
||||
/* It is an output reload insn after insn can be
|
||||
rematerialized (potential candidate). */
|
||||
create_cand (insn2, regno_potential_cand[src_regno].nop, dst_regno);
|
||||
if (nop < 0)
|
||||
goto fail;
|
||||
gcc_assert (REG_P (*id->operand_loc[nop]));
|
||||
regno = REGNO (*id->operand_loc[nop]);
|
||||
gcc_assert (regno >= FIRST_PSEUDO_REGISTER);
|
||||
if (reg_renumber[regno] < 0)
|
||||
create_cand (insn, nop, regno);
|
||||
else
|
||||
/* See if this is an output reload for a previous insn. */
|
||||
if (set != NULL
|
||||
&& REG_P (SET_SRC (set)) && REG_P (SET_DEST (set)))
|
||||
{
|
||||
regno_potential_cand[regno].insn = insn;
|
||||
regno_potential_cand[regno].nop = nop;
|
||||
goto fail;
|
||||
rtx dstreg = SET_DEST (set);
|
||||
int src_regno = REGNO (SET_SRC (set));
|
||||
int dst_regno = REGNO (dstreg);
|
||||
rtx_insn *insn2 = regno_potential_cand[src_regno].insn;
|
||||
|
||||
if (insn2 != NULL
|
||||
&& dst_regno >= FIRST_PSEUDO_REGISTER
|
||||
&& reg_renumber[dst_regno] < 0
|
||||
&& BLOCK_FOR_INSN (insn2) == BLOCK_FOR_INSN (insn))
|
||||
{
|
||||
create_cand (insn2, regno_potential_cand[src_regno].nop,
|
||||
dst_regno, insn);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
regno = -1;
|
||||
fail:
|
||||
|
||||
nop = operand_to_remat (insn);
|
||||
if (nop >= 0)
|
||||
{
|
||||
gcc_assert (REG_P (*id->operand_loc[nop]));
|
||||
int regno = REGNO (*id->operand_loc[nop]);
|
||||
gcc_assert (regno >= FIRST_PSEUDO_REGISTER);
|
||||
/* If we're setting an unrenumbered pseudo, make a candidate immediately.
|
||||
If it's an output reload register, save it for later; the code above
|
||||
looks for output reload insns later on. */
|
||||
if (reg_renumber[regno] < 0)
|
||||
create_cand (insn, nop, regno);
|
||||
else if (regno >= lra_constraint_new_regno_start)
|
||||
{
|
||||
regno_potential_cand[regno].insn = insn;
|
||||
regno_potential_cand[regno].nop = nop;
|
||||
keep_regno = regno;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
for (struct lra_insn_reg *reg = id->regs; reg != NULL; reg = reg->next)
|
||||
if (reg->type != OP_IN && reg->regno != regno
|
||||
if (reg->type != OP_IN && reg->regno != keep_regno
|
||||
&& reg->regno >= FIRST_PSEUDO_REGISTER)
|
||||
regno_potential_cand[reg->regno].insn = NULL;
|
||||
}
|
||||
@ -1072,16 +1090,21 @@ do_remat (void)
|
||||
rtx_insn *insn;
|
||||
basic_block bb;
|
||||
bitmap_head avail_cands;
|
||||
bitmap_head active_cands;
|
||||
bool changed_p = false;
|
||||
/* Living hard regs and hard registers of living pseudos. */
|
||||
HARD_REG_SET live_hard_regs;
|
||||
|
||||
bitmap_initialize (&avail_cands, ®_obstack);
|
||||
bitmap_initialize (&active_cands, ®_obstack);
|
||||
FOR_EACH_BB_FN (bb, cfun)
|
||||
{
|
||||
REG_SET_TO_HARD_REG_SET (live_hard_regs, df_get_live_out (bb));
|
||||
bitmap_and (&avail_cands, &get_remat_bb_data (bb)->avin_cands,
|
||||
&get_remat_bb_data (bb)->livein_cands);
|
||||
/* Activating insns are always in the same block as their corresponding
|
||||
remat insn, so at the start of a block the two bitsets are equal. */
|
||||
bitmap_copy (&active_cands, &avail_cands);
|
||||
FOR_BB_INSNS (bb, insn)
|
||||
{
|
||||
if (!NONDEBUG_INSN_P (insn))
|
||||
@ -1115,7 +1138,8 @@ do_remat (void)
|
||||
for (cand = regno_cands[src_regno];
|
||||
cand != NULL;
|
||||
cand = cand->next_regno_cand)
|
||||
if (bitmap_bit_p (&avail_cands, cand->index))
|
||||
if (bitmap_bit_p (&avail_cands, cand->index)
|
||||
&& bitmap_bit_p (&active_cands, cand->index))
|
||||
break;
|
||||
}
|
||||
int i, hard_regno, nregs;
|
||||
@ -1209,9 +1233,23 @@ do_remat (void)
|
||||
}
|
||||
|
||||
bitmap_and_compl_into (&avail_cands, &temp_bitmap);
|
||||
if ((cand = insn_to_cand[INSN_UID (insn)]) != NULL)
|
||||
bitmap_set_bit (&avail_cands, cand->index);
|
||||
|
||||
|
||||
/* Now see whether a candidate is made active or available
|
||||
by this insn. */
|
||||
cand = insn_to_cand_activation[INSN_UID (insn)];
|
||||
if (cand)
|
||||
bitmap_set_bit (&active_cands, cand->index);
|
||||
|
||||
cand = insn_to_cand[INSN_UID (insn)];
|
||||
if (cand != NULL)
|
||||
{
|
||||
bitmap_set_bit (&avail_cands, cand->index);
|
||||
if (cand->reload_regno == -1)
|
||||
bitmap_set_bit (&active_cands, cand->index);
|
||||
else
|
||||
bitmap_clear_bit (&active_cands, cand->index);
|
||||
}
|
||||
|
||||
if (remat_insn != NULL)
|
||||
{
|
||||
HOST_WIDE_INT sp_offset_change = cand_sp_offset - id->sp_offset;
|
||||
@ -1258,6 +1296,7 @@ do_remat (void)
|
||||
}
|
||||
}
|
||||
bitmap_clear (&avail_cands);
|
||||
bitmap_clear (&active_cands);
|
||||
return changed_p;
|
||||
}
|
||||
|
||||
@ -1286,6 +1325,7 @@ lra_remat (void)
|
||||
lra_rematerialization_iter);
|
||||
timevar_push (TV_LRA_REMAT);
|
||||
insn_to_cand = XCNEWVEC (cand_t, get_max_uid ());
|
||||
insn_to_cand_activation = XCNEWVEC (cand_t, get_max_uid ());
|
||||
regno_cands = XCNEWVEC (cand_t, max_regno);
|
||||
all_cands.create (8000);
|
||||
call_used_regs_arr_len = 0;
|
||||
@ -1314,6 +1354,7 @@ lra_remat (void)
|
||||
bitmap_clear (&all_blocks);
|
||||
free (regno_cands);
|
||||
free (insn_to_cand);
|
||||
free (insn_to_cand_activation);
|
||||
timevar_pop (TV_LRA_REMAT);
|
||||
return result;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user