Message ID | B5E67142681B53468FAF6B7C31356562441BCDA8@hhmail02.hh.imgtec.org |
---|---|
State | New |
Headers | show |
Hi Robert, > gcc/ > * regrename.c (create_new_chain): Initialize terminated_dead, > renamed and tied_chain. > (find_best_rename_reg): Pick and check register from the tied chain. > (regrename_do_replace): Mark head as renamed. > (scan_rtx_reg): Tie chains in move insns. Set terminate_dead flag. > * regrename.h (struct du_head): Add tied_chain, renamed and > terminated_dead members. Thanks - this looks a lot better already. You didn't say how it was bootstrapped and tested; please include this information for future submissions. For a patch like this, some data on the improvement you got would also be appreciated. I'd still like to investigate the possibility of further simplification: > + { > + /* Find the input chain. */ > + for (i = c->id - 1; id_to_chain.iterate (i, &head); i--) > + if (head->last && head->last->insn == insn > + && head->terminated_dead) > + { > + gcc_assert (head->regno == REGNO (recog_data.operand[1])); > + c->tied_chain = head; > + head->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[head->regno], head->id); > + /* Once tied, we're done. */ > + break; > + } > + } > + } > + This looks like it's a little more complicated than necessary. Couldn't you add a static var "terminated_this_insn" which gets initialized to NULL and set when a reg dies, and then you check this here rather than having a loop? That would also eliminate the new "terminated_dead" field. Other than that I'm pretty happy with this. Bernd
Hi Bernd, > Hi Robert, > > gcc/ > > * regrename.c (create_new_chain): Initialize terminated_dead, > > renamed and tied_chain. > > (find_best_rename_reg): Pick and check register from the tied chain. > > (regrename_do_replace): Mark head as renamed. > > (scan_rtx_reg): Tie chains in move insns. Set terminate_dead flag. > > * regrename.h (struct du_head): Add tied_chain, renamed and > > terminated_dead members. > > Thanks - this looks a lot better already. You didn't say how it was > bootstrapped and tested; please include this information for future > submissions. For a patch like this, some data on the improvement you got > would also be appreciated. Ah, sorry. I bootstrapped on x86_64-unknown-linux-gnu and ran the Dejagnu with -frename-registers. All looked fine. As for the data, I'll do the comparison and will update this thread by next week. > > I'd still like to investigate the possibility of further simplification: > > > + { > > + /* Find the input chain. */ > > + for (i = c->id - 1; id_to_chain.iterate (i, &head); i--) > > + if (head->last && head->last->insn == insn > > + && head->terminated_dead) > > + { > > + gcc_assert (head->regno == REGNO (recog_data.operand[1])); > > + c->tied_chain = head; > > + head->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[head->regno], head->id); > > + /* Once tied, we're done. */ > > + break; > > + } > > + } > > + } > > + > This looks like it's a little more complicated than necessary. Couldn't > you add a static var "terminated_this_insn" which gets initialized to > NULL and set when a reg dies, and then you check this here rather than > having a loop? That would also eliminate the new "terminated_dead" field. That is a good idea. I'll add the changes and update together with the results. > Other than that I'm pretty happy with this. > > > Bernd Regards, Robert
diff --git a/gcc/regrename.c b/gcc/regrename.c index 6517f4e..7356a20 100644 --- a/gcc/regrename.c +++ b/gcc/regrename.c @@ -230,6 +230,9 @@ 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->terminated_dead = 0; + head->renamed = 0; + head->tied_chain = NULL; id_to_chain.safe_push (head); head->id = current_id++; @@ -373,6 +376,13 @@ find_best_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 @@ -952,6 +962,7 @@ regrename_do_replace (struct du_head *head, int reg) } mode = GET_MODE (*head->first->loc); + head->renamed = 1; head->regno = reg; head->nregs = hard_regno_nregs[reg][mode]; } @@ -1035,7 +1046,40 @@ scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action, if (action == mark_write) { if (type == OP_OUT) - create_new_chain (this_regno, this_nregs, loc, insn, cl); + { + int i; + du_head_p c; + du_head_p head; + 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) + { + /* Find the input chain. */ + for (i = c->id - 1; id_to_chain.iterate (i, &head); i--) + if (head->last && head->last->insn == insn + && head->terminated_dead) + { + gcc_assert (head->regno == REGNO (recog_data.operand[1])); + c->tied_chain = head; + head->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[head->regno], head->id); + /* Once tied, we're done. */ + break; + } + } + } + return; } @@ -1143,6 +1187,8 @@ scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action, SET_HARD_REG_BIT (live_hard_regs, head->regno + nregs); } + if (action == terminate_dead) + (*p)->terminated_dead = 1; *p = next; if (dump_file) fprintf (dump_file, diff --git a/gcc/regrename.h b/gcc/regrename.h index 9a611f0..a61c5bd 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,10 @@ 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 is renamed. */ + unsigned int renamed:1; + /* Nonzero if the chain is marked as dead. */ + unsigned int terminated_dead:1; }; typedef struct du_head *du_head_p;