aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/lra-remat.c115
2 files changed, 90 insertions, 38 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a2fb881..66deab1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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>
diff --git a/gcc/lra-remat.c b/gcc/lra-remat.c
index e729ea9..785d531 100644
--- a/gcc/lra-remat.c
+++ b/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;
-
- 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
+ int keep_regno = -1;
+ rtx set = single_set (insn);
+ int nop;
+
+ /* See if this is an output reload for a previous insn. */
+ if (set != NULL
+ && REG_P (SET_SRC (set)) && REG_P (SET_DEST (set)))
+ {
+ 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;
+ }
+ }
+
+ nop = operand_to_remat (insn);
+ if (nop >= 0)
{
- regno_potential_cand[regno].insn = insn;
- regno_potential_cand[regno].nop = nop;
- goto fail;
+ 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;
+ }
}
- regno = -1;
- fail:
+
+ 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, &reg_obstack);
+ bitmap_initialize (&active_cands, &reg_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;
}