aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Suchanek <robert.suchanek@imgtec.com>2015-11-10 09:12:52 +0000
committerRobert Suchanek <rts@gcc.gnu.org>2015-11-10 09:12:52 +0000
commit0d20a76b28b1ea7935412f2778b250aea5d63f22 (patch)
tree6d7c7be18694fc0b82bcf54def8e11de69eb30a8
parent66d662de1cc20000cb56a1c19685ad9b6b62d353 (diff)
downloadgcc-0d20a76b28b1ea7935412f2778b250aea5d63f22.zip
gcc-0d20a76b28b1ea7935412f2778b250aea5d63f22.tar.gz
gcc-0d20a76b28b1ea7935412f2778b250aea5d63f22.tar.bz2
Tie chains for move instructions.
gcc/ * regrename.c (create_new_chain): Initialize renamed and tied_chain. (build_def_use): Initialize terminated_this_insn. (find_best_rename_reg): Pick and check register from the tied chain. (regrename_do_replace): Mark head as renamed. (struct du_head *terminated_this_insn). New static variable. (scan_rtx_reg): Tie chains in move insns. Set terminated_this_insn. * regrename.h (struct du_head): Add tied_chain, renamed members. From-SVN: r230087
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/regrename.c46
-rw-r--r--gcc/regrename.h4
3 files changed, 59 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 577267a..5abb84b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2015-11-10 Robert Suchanek <robert.suchanek@imgtec.com>
+
+ * regrename.c (create_new_chain): Initialize renamed and tied_chain.
+ (build_def_use): Initialize terminated_this_insn.
+ (find_best_rename_reg): Pick and check register from the tied chain.
+ (regrename_do_replace): Mark head as renamed.
+ (struct du_head *terminated_this_insn). New static variable.
+ (scan_rtx_reg): Tie chains in move insns. Set terminated_this_insn.
+ * regrename.h (struct du_head): Add tied_chain, renamed members.
+
2015-11-10 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
PR bootstrap/68256
diff --git a/gcc/regrename.c b/gcc/regrename.c
index 5f383fc..d727dd9 100644
--- a/gcc/regrename.c
+++ b/gcc/regrename.c
@@ -130,6 +130,9 @@ static HARD_REG_SET live_hard_regs;
record_operand_use. */
static operand_rr_info *cur_operand;
+/* Set while scanning RTL if a register dies. Used to tie chains. */
+static struct du_head *terminated_this_insn;
+
/* Return the chain corresponding to id number ID. Take into account that
chains may have been merged. */
du_head_p
@@ -224,6 +227,8 @@ create_new_chain (unsigned this_regno, unsigned this_nregs, rtx *loc,
head->nregs = this_nregs;
head->need_caller_save_reg = 0;
head->cannot_rename = 0;
+ head->renamed = 0;
+ head->tied_chain = NULL;
id_to_chain.safe_push (head);
head->id = current_id++;
@@ -366,6 +371,13 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
preferred_class
= (enum reg_class) targetm.preferred_rename_class (super_class);
+ /* Pick and check the register from the tied chain iff the tied chain
+ is not renamed. */
+ if (this_head->tied_chain && !this_head->tied_chain->renamed
+ && check_new_reg_p (old_reg, this_head->tied_chain->regno,
+ this_head, *unavailable))
+ return this_head->tied_chain->regno;
+
/* If PREFERRED_CLASS is not NO_REGS, we iterate in the first pass
over registers that belong to PREFERRED_CLASS and try to find the
best register within the class. If that failed, we iterate in
@@ -960,6 +972,7 @@ regrename_do_replace (struct du_head *head, int reg)
return false;
mode = GET_MODE (*head->first->loc);
+ head->renamed = 1;
head->regno = reg;
head->nregs = hard_regno_nregs[reg][mode];
return true;
@@ -1043,7 +1056,34 @@ scan_rtx_reg (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions act
if (action == mark_write)
{
if (type == OP_OUT)
- create_new_chain (this_regno, this_nregs, loc, insn, cl);
+ {
+ du_head_p c;
+ rtx pat = PATTERN (insn);
+
+ c = create_new_chain (this_regno, this_nregs, loc, insn, cl);
+
+ /* We try to tie chains in a move instruction for
+ a single output. */
+ if (recog_data.n_operands == 2
+ && GET_CODE (pat) == SET
+ && GET_CODE (SET_DEST (pat)) == REG
+ && GET_CODE (SET_SRC (pat)) == REG
+ && terminated_this_insn)
+ {
+ gcc_assert (terminated_this_insn->regno
+ == REGNO (recog_data.operand[1]));
+
+ c->tied_chain = terminated_this_insn;
+ terminated_this_insn->tied_chain = c;
+
+ if (dump_file)
+ fprintf (dump_file, "Tying chain %s (%d) with %s (%d)\n",
+ reg_names[c->regno], c->id,
+ reg_names[terminated_this_insn->regno],
+ terminated_this_insn->id);
+ }
+ }
+
return;
}
@@ -1151,6 +1191,8 @@ scan_rtx_reg (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions act
SET_HARD_REG_BIT (live_hard_regs, head->regno + nregs);
}
+ if (action == terminate_dead)
+ terminated_this_insn = *p;
*p = next;
if (dump_file)
fprintf (dump_file,
@@ -1707,6 +1749,8 @@ build_def_use (basic_block bb)
scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_read,
OP_INOUT);
+ terminated_this_insn = NULL;
+
/* Step 4: Close chains for registers that die here, unless
the register is mentioned in a REG_UNUSED note. In that
case we keep the chain open until step #7 below to ensure
diff --git a/gcc/regrename.h b/gcc/regrename.h
index bbe156d..77cc2fe 100644
--- a/gcc/regrename.h
+++ b/gcc/regrename.h
@@ -28,6 +28,8 @@ struct du_head
struct du_head *next_chain;
/* The first and last elements of this chain. */
struct du_chain *first, *last;
+ /* The chain that this chain is tied to. */
+ struct du_head *tied_chain;
/* Describes the register being tracked. */
unsigned regno;
int nregs;
@@ -45,6 +47,8 @@ struct du_head
such as the SET_DEST of a CALL_INSN or an asm operand that used
to be a hard register. */
unsigned int cannot_rename:1;
+ /* Nonzero if the chain has already been renamed. */
+ unsigned int renamed:1;
};
typedef struct du_head *du_head_p;