xref: /dflybsd-src/contrib/gcc-8.0/gcc/regrename.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj /* Register renaming for the GNU compiler.
238fd1498Szrj    Copyright (C) 2000-2018 Free Software Foundation, Inc.
338fd1498Szrj 
438fd1498Szrj    This file is part of GCC.
538fd1498Szrj 
638fd1498Szrj    GCC is free software; you can redistribute it and/or modify it
738fd1498Szrj    under the terms of the GNU General Public License as published by
838fd1498Szrj    the Free Software Foundation; either version 3, or (at your option)
938fd1498Szrj    any later version.
1038fd1498Szrj 
1138fd1498Szrj    GCC is distributed in the hope that it will be useful, but WITHOUT
1238fd1498Szrj    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1338fd1498Szrj    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
1438fd1498Szrj    License for more details.
1538fd1498Szrj 
1638fd1498Szrj    You should have received a copy of the GNU General Public License
1738fd1498Szrj    along with GCC; see the file COPYING3.  If not see
1838fd1498Szrj    <http://www.gnu.org/licenses/>.  */
1938fd1498Szrj 
2038fd1498Szrj #include "config.h"
2138fd1498Szrj #include "system.h"
2238fd1498Szrj #include "coretypes.h"
2338fd1498Szrj #include "backend.h"
2438fd1498Szrj #include "target.h"
2538fd1498Szrj #include "rtl.h"
2638fd1498Szrj #include "df.h"
2738fd1498Szrj #include "memmodel.h"
2838fd1498Szrj #include "tm_p.h"
2938fd1498Szrj #include "insn-config.h"
3038fd1498Szrj #include "regs.h"
3138fd1498Szrj #include "emit-rtl.h"
3238fd1498Szrj #include "recog.h"
3338fd1498Szrj #include "addresses.h"
3438fd1498Szrj #include "cfganal.h"
3538fd1498Szrj #include "tree-pass.h"
3638fd1498Szrj #include "regrename.h"
3738fd1498Szrj 
3838fd1498Szrj /* This file implements the RTL register renaming pass of the compiler.  It is
3938fd1498Szrj    a semi-local pass whose goal is to maximize the usage of the register file
4038fd1498Szrj    of the processor by substituting registers for others in the solution given
4138fd1498Szrj    by the register allocator.  The algorithm is as follows:
4238fd1498Szrj 
4338fd1498Szrj      1. Local def/use chains are built: within each basic block, chains are
4438fd1498Szrj 	opened and closed; if a chain isn't closed at the end of the block,
4538fd1498Szrj 	it is dropped.  We pre-open chains if we have already examined a
4638fd1498Szrj 	predecessor block and found chains live at the end which match
4738fd1498Szrj 	live registers at the start of the new block.
4838fd1498Szrj 
4938fd1498Szrj      2. We try to combine the local chains across basic block boundaries by
5038fd1498Szrj         comparing chains that were open at the start or end of a block to
5138fd1498Szrj 	those in successor/predecessor blocks.
5238fd1498Szrj 
5338fd1498Szrj      3. For each chain, the set of possible renaming registers is computed.
5438fd1498Szrj 	This takes into account the renaming of previously processed chains.
5538fd1498Szrj 	Optionally, a preferred class is computed for the renaming register.
5638fd1498Szrj 
5738fd1498Szrj      4. The best renaming register is computed for the chain in the above set,
5838fd1498Szrj 	using a round-robin allocation.  If a preferred class exists, then the
5938fd1498Szrj 	round-robin allocation is done within the class first, if possible.
6038fd1498Szrj 	The round-robin allocation of renaming registers itself is global.
6138fd1498Szrj 
6238fd1498Szrj      5. If a renaming register has been found, it is substituted in the chain.
6338fd1498Szrj 
6438fd1498Szrj   Targets can parameterize the pass by specifying a preferred class for the
6538fd1498Szrj   renaming register for a given (super)class of registers to be renamed.
6638fd1498Szrj 
6738fd1498Szrj   DEBUG_INSNs are treated specially, in particular registers occurring inside
6838fd1498Szrj   them are treated as requiring ALL_REGS as a class.  */
6938fd1498Szrj 
7038fd1498Szrj #if HOST_BITS_PER_WIDE_INT <= MAX_RECOG_OPERANDS
7138fd1498Szrj #error "Use a different bitmap implementation for untracked_operands."
7238fd1498Szrj #endif
7338fd1498Szrj 
7438fd1498Szrj enum scan_actions
7538fd1498Szrj {
7638fd1498Szrj   terminate_write,
7738fd1498Szrj   terminate_dead,
7838fd1498Szrj   mark_all_read,
7938fd1498Szrj   mark_read,
8038fd1498Szrj   mark_write,
8138fd1498Szrj   /* mark_access is for marking the destination regs in
8238fd1498Szrj      REG_FRAME_RELATED_EXPR notes (as if they were read) so that the
8338fd1498Szrj      note is updated properly.  */
8438fd1498Szrj   mark_access
8538fd1498Szrj };
8638fd1498Szrj 
8738fd1498Szrj static const char * const scan_actions_name[] =
8838fd1498Szrj {
8938fd1498Szrj   "terminate_write",
9038fd1498Szrj   "terminate_dead",
9138fd1498Szrj   "mark_all_read",
9238fd1498Szrj   "mark_read",
9338fd1498Szrj   "mark_write",
9438fd1498Szrj   "mark_access"
9538fd1498Szrj };
9638fd1498Szrj 
9738fd1498Szrj /* TICK and THIS_TICK are used to record the last time we saw each
9838fd1498Szrj    register.  */
9938fd1498Szrj static int tick[FIRST_PSEUDO_REGISTER];
10038fd1498Szrj static int this_tick = 0;
10138fd1498Szrj 
10238fd1498Szrj static struct obstack rename_obstack;
10338fd1498Szrj 
10438fd1498Szrj /* If nonnull, the code calling into the register renamer requested
10538fd1498Szrj    information about insn operands, and we store it here.  */
10638fd1498Szrj vec<insn_rr_info> insn_rr;
10738fd1498Szrj 
10838fd1498Szrj static void scan_rtx (rtx_insn *, rtx *, enum reg_class, enum scan_actions,
10938fd1498Szrj 		      enum op_type);
11038fd1498Szrj static bool build_def_use (basic_block);
11138fd1498Szrj 
11238fd1498Szrj /* The id to be given to the next opened chain.  */
11338fd1498Szrj static unsigned current_id;
11438fd1498Szrj 
11538fd1498Szrj /* A mapping of unique id numbers to chains.  */
11638fd1498Szrj static vec<du_head_p> id_to_chain;
11738fd1498Szrj 
11838fd1498Szrj /* List of currently open chains.  */
11938fd1498Szrj static struct du_head *open_chains;
12038fd1498Szrj 
12138fd1498Szrj /* Bitmap of open chains.  The bits set always match the list found in
12238fd1498Szrj    open_chains.  */
12338fd1498Szrj static bitmap_head open_chains_set;
12438fd1498Szrj 
12538fd1498Szrj /* Record the registers being tracked in open_chains.  */
12638fd1498Szrj static HARD_REG_SET live_in_chains;
12738fd1498Szrj 
12838fd1498Szrj /* Record the registers that are live but not tracked.  The intersection
12938fd1498Szrj    between this and live_in_chains is empty.  */
13038fd1498Szrj static HARD_REG_SET live_hard_regs;
13138fd1498Szrj 
13238fd1498Szrj /* Set while scanning RTL if INSN_RR is nonnull, i.e. if the current analysis
13338fd1498Szrj    is for a caller that requires operand data.  Used in
13438fd1498Szrj    record_operand_use.  */
13538fd1498Szrj static operand_rr_info *cur_operand;
13638fd1498Szrj 
13738fd1498Szrj /* Set while scanning RTL if a register dies.  Used to tie chains.  */
13838fd1498Szrj static struct du_head *terminated_this_insn;
13938fd1498Szrj 
14038fd1498Szrj /* Return the chain corresponding to id number ID.  Take into account that
14138fd1498Szrj    chains may have been merged.  */
14238fd1498Szrj du_head_p
regrename_chain_from_id(unsigned int id)14338fd1498Szrj regrename_chain_from_id (unsigned int id)
14438fd1498Szrj {
14538fd1498Szrj   du_head_p first_chain = id_to_chain[id];
14638fd1498Szrj   du_head_p chain = first_chain;
14738fd1498Szrj   while (chain->id != id)
14838fd1498Szrj     {
14938fd1498Szrj       id = chain->id;
15038fd1498Szrj       chain = id_to_chain[id];
15138fd1498Szrj     }
15238fd1498Szrj   first_chain->id = id;
15338fd1498Szrj   return chain;
15438fd1498Szrj }
15538fd1498Szrj 
15638fd1498Szrj /* Dump all def/use chains, starting at id FROM.  */
15738fd1498Szrj 
15838fd1498Szrj static void
dump_def_use_chain(int from)15938fd1498Szrj dump_def_use_chain (int from)
16038fd1498Szrj {
16138fd1498Szrj   du_head_p head;
16238fd1498Szrj   int i;
16338fd1498Szrj   FOR_EACH_VEC_ELT_FROM (id_to_chain, i, head, from)
16438fd1498Szrj     {
16538fd1498Szrj       struct du_chain *this_du = head->first;
16638fd1498Szrj 
16738fd1498Szrj       fprintf (dump_file, "Register %s (%d):",
16838fd1498Szrj 	       reg_names[head->regno], head->nregs);
16938fd1498Szrj       while (this_du)
17038fd1498Szrj 	{
17138fd1498Szrj 	  fprintf (dump_file, " %d [%s]", INSN_UID (this_du->insn),
17238fd1498Szrj 		   reg_class_names[this_du->cl]);
17338fd1498Szrj 	  this_du = this_du->next_use;
17438fd1498Szrj 	}
17538fd1498Szrj       fprintf (dump_file, "\n");
17638fd1498Szrj       head = head->next_chain;
17738fd1498Szrj     }
17838fd1498Szrj }
17938fd1498Szrj 
18038fd1498Szrj static void
free_chain_data(void)18138fd1498Szrj free_chain_data (void)
18238fd1498Szrj {
18338fd1498Szrj   int i;
18438fd1498Szrj   du_head_p ptr;
18538fd1498Szrj   for (i = 0; id_to_chain.iterate (i, &ptr); i++)
18638fd1498Szrj     bitmap_clear (&ptr->conflicts);
18738fd1498Szrj 
18838fd1498Szrj   id_to_chain.release ();
18938fd1498Szrj }
19038fd1498Szrj 
19138fd1498Szrj /* Walk all chains starting with CHAINS and record that they conflict with
19238fd1498Szrj    another chain whose id is ID.  */
19338fd1498Szrj 
19438fd1498Szrj static void
mark_conflict(struct du_head * chains,unsigned id)19538fd1498Szrj mark_conflict (struct du_head *chains, unsigned id)
19638fd1498Szrj {
19738fd1498Szrj   while (chains)
19838fd1498Szrj     {
19938fd1498Szrj       bitmap_set_bit (&chains->conflicts, id);
20038fd1498Szrj       chains = chains->next_chain;
20138fd1498Szrj     }
20238fd1498Szrj }
20338fd1498Szrj 
20438fd1498Szrj /* Examine cur_operand, and if it is nonnull, record information about the
20538fd1498Szrj    use THIS_DU which is part of the chain HEAD.  */
20638fd1498Szrj 
20738fd1498Szrj static void
record_operand_use(struct du_head * head,struct du_chain * this_du)20838fd1498Szrj record_operand_use (struct du_head *head, struct du_chain *this_du)
20938fd1498Szrj {
21038fd1498Szrj   if (cur_operand == NULL || cur_operand->failed)
21138fd1498Szrj     return;
21238fd1498Szrj   if (head->cannot_rename)
21338fd1498Szrj     {
21438fd1498Szrj       cur_operand->failed = true;
21538fd1498Szrj       return;
21638fd1498Szrj     }
21738fd1498Szrj   gcc_assert (cur_operand->n_chains < MAX_REGS_PER_ADDRESS);
21838fd1498Szrj   cur_operand->heads[cur_operand->n_chains] = head;
21938fd1498Szrj   cur_operand->chains[cur_operand->n_chains++] = this_du;
22038fd1498Szrj }
22138fd1498Szrj 
22238fd1498Szrj /* Create a new chain for THIS_NREGS registers starting at THIS_REGNO,
22338fd1498Szrj    and record its occurrence in *LOC, which is being written to in INSN.
22438fd1498Szrj    This access requires a register of class CL.  */
22538fd1498Szrj 
22638fd1498Szrj static du_head_p
create_new_chain(unsigned this_regno,unsigned this_nregs,rtx * loc,rtx_insn * insn,enum reg_class cl)22738fd1498Szrj create_new_chain (unsigned this_regno, unsigned this_nregs, rtx *loc,
22838fd1498Szrj 		  rtx_insn *insn, enum reg_class cl)
22938fd1498Szrj {
23038fd1498Szrj   struct du_head *head = XOBNEW (&rename_obstack, struct du_head);
23138fd1498Szrj   struct du_chain *this_du;
23238fd1498Szrj   int nregs;
23338fd1498Szrj 
23438fd1498Szrj   memset (head, 0, sizeof *head);
23538fd1498Szrj   head->next_chain = open_chains;
23638fd1498Szrj   head->regno = this_regno;
23738fd1498Szrj   head->nregs = this_nregs;
23838fd1498Szrj 
23938fd1498Szrj   id_to_chain.safe_push (head);
24038fd1498Szrj   head->id = current_id++;
24138fd1498Szrj 
24238fd1498Szrj   bitmap_initialize (&head->conflicts, &bitmap_default_obstack);
24338fd1498Szrj   bitmap_copy (&head->conflicts, &open_chains_set);
24438fd1498Szrj   mark_conflict (open_chains, head->id);
24538fd1498Szrj 
24638fd1498Szrj   /* Since we're tracking this as a chain now, remove it from the
24738fd1498Szrj      list of conflicting live hard registers and track it in
24838fd1498Szrj      live_in_chains instead.  */
24938fd1498Szrj   nregs = head->nregs;
25038fd1498Szrj   while (nregs-- > 0)
25138fd1498Szrj     {
25238fd1498Szrj       SET_HARD_REG_BIT (live_in_chains, head->regno + nregs);
25338fd1498Szrj       CLEAR_HARD_REG_BIT (live_hard_regs, head->regno + nregs);
25438fd1498Szrj     }
25538fd1498Szrj 
25638fd1498Szrj   COPY_HARD_REG_SET (head->hard_conflicts, live_hard_regs);
25738fd1498Szrj   bitmap_set_bit (&open_chains_set, head->id);
25838fd1498Szrj 
25938fd1498Szrj   open_chains = head;
26038fd1498Szrj 
26138fd1498Szrj   if (dump_file)
26238fd1498Szrj     {
26338fd1498Szrj       fprintf (dump_file, "Creating chain %s (%d)",
26438fd1498Szrj 	       reg_names[head->regno], head->id);
26538fd1498Szrj       if (insn != NULL_RTX)
26638fd1498Szrj 	fprintf (dump_file, " at insn %d", INSN_UID (insn));
26738fd1498Szrj       fprintf (dump_file, "\n");
26838fd1498Szrj     }
26938fd1498Szrj 
27038fd1498Szrj   if (insn == NULL_RTX)
27138fd1498Szrj     {
27238fd1498Szrj       head->first = head->last = NULL;
27338fd1498Szrj       return head;
27438fd1498Szrj     }
27538fd1498Szrj 
27638fd1498Szrj   this_du = XOBNEW (&rename_obstack, struct du_chain);
27738fd1498Szrj   head->first = head->last = this_du;
27838fd1498Szrj 
27938fd1498Szrj   this_du->next_use = 0;
28038fd1498Szrj   this_du->loc = loc;
28138fd1498Szrj   this_du->insn = insn;
28238fd1498Szrj   this_du->cl = cl;
28338fd1498Szrj   record_operand_use (head, this_du);
28438fd1498Szrj   return head;
28538fd1498Szrj }
28638fd1498Szrj 
28738fd1498Szrj /* For a def-use chain HEAD, find which registers overlap its lifetime and
28838fd1498Szrj    set the corresponding bits in *PSET.  */
28938fd1498Szrj 
29038fd1498Szrj static void
merge_overlapping_regs(HARD_REG_SET * pset,struct du_head * head)29138fd1498Szrj merge_overlapping_regs (HARD_REG_SET *pset, struct du_head *head)
29238fd1498Szrj {
29338fd1498Szrj   bitmap_iterator bi;
29438fd1498Szrj   unsigned i;
29538fd1498Szrj   IOR_HARD_REG_SET (*pset, head->hard_conflicts);
29638fd1498Szrj   EXECUTE_IF_SET_IN_BITMAP (&head->conflicts, 0, i, bi)
29738fd1498Szrj     {
29838fd1498Szrj       du_head_p other = regrename_chain_from_id (i);
29938fd1498Szrj       unsigned j = other->nregs;
30038fd1498Szrj       gcc_assert (other != head);
30138fd1498Szrj       while (j-- > 0)
30238fd1498Szrj 	SET_HARD_REG_BIT (*pset, other->regno + j);
30338fd1498Szrj     }
30438fd1498Szrj }
30538fd1498Szrj 
30638fd1498Szrj /* Check if NEW_REG can be the candidate register to rename for
30738fd1498Szrj    REG in THIS_HEAD chain.  THIS_UNAVAILABLE is a set of unavailable hard
30838fd1498Szrj    registers.  */
30938fd1498Szrj 
31038fd1498Szrj static bool
check_new_reg_p(int reg ATTRIBUTE_UNUSED,int new_reg,struct du_head * this_head,HARD_REG_SET this_unavailable)31138fd1498Szrj check_new_reg_p (int reg ATTRIBUTE_UNUSED, int new_reg,
31238fd1498Szrj 		 struct du_head *this_head, HARD_REG_SET this_unavailable)
31338fd1498Szrj {
31438fd1498Szrj   machine_mode mode = GET_MODE (*this_head->first->loc);
31538fd1498Szrj   int nregs = hard_regno_nregs (new_reg, mode);
31638fd1498Szrj   int i;
31738fd1498Szrj   struct du_chain *tmp;
31838fd1498Szrj 
31938fd1498Szrj   for (i = nregs - 1; i >= 0; --i)
32038fd1498Szrj     if (TEST_HARD_REG_BIT (this_unavailable, new_reg + i)
32138fd1498Szrj 	|| fixed_regs[new_reg + i]
32238fd1498Szrj 	|| global_regs[new_reg + i]
32338fd1498Szrj 	/* Can't use regs which aren't saved by the prologue.  */
32438fd1498Szrj 	|| (! df_regs_ever_live_p (new_reg + i)
32538fd1498Szrj 	    && ! call_used_regs[new_reg + i])
32638fd1498Szrj #ifdef LEAF_REGISTERS
32738fd1498Szrj 	/* We can't use a non-leaf register if we're in a
32838fd1498Szrj 	   leaf function.  */
32938fd1498Szrj 	|| (crtl->is_leaf
33038fd1498Szrj 	    && !LEAF_REGISTERS[new_reg + i])
33138fd1498Szrj #endif
33238fd1498Szrj 	|| ! HARD_REGNO_RENAME_OK (reg + i, new_reg + i))
33338fd1498Szrj       return false;
33438fd1498Szrj 
33538fd1498Szrj   /* See whether it accepts all modes that occur in
33638fd1498Szrj      definition and uses.  */
33738fd1498Szrj   for (tmp = this_head->first; tmp; tmp = tmp->next_use)
33838fd1498Szrj     if ((!targetm.hard_regno_mode_ok (new_reg, GET_MODE (*tmp->loc))
33938fd1498Szrj 	 && ! DEBUG_INSN_P (tmp->insn))
34038fd1498Szrj 	|| (this_head->need_caller_save_reg
34138fd1498Szrj 	    && ! (targetm.hard_regno_call_part_clobbered
34238fd1498Szrj 		  (reg, GET_MODE (*tmp->loc)))
34338fd1498Szrj 	    && (targetm.hard_regno_call_part_clobbered
34438fd1498Szrj 		(new_reg, GET_MODE (*tmp->loc)))))
34538fd1498Szrj       return false;
34638fd1498Szrj 
34738fd1498Szrj   return true;
34838fd1498Szrj }
34938fd1498Szrj 
35038fd1498Szrj /* For the chain THIS_HEAD, compute and return the best register to
35138fd1498Szrj    rename to.  SUPER_CLASS is the superunion of register classes in
35238fd1498Szrj    the chain.  UNAVAILABLE is a set of registers that cannot be used.
35338fd1498Szrj    OLD_REG is the register currently used for the chain.  BEST_RENAME
35438fd1498Szrj    controls whether the register chosen must be better than the
35538fd1498Szrj    current one or just respect the given constraint.  */
35638fd1498Szrj 
35738fd1498Szrj int
find_rename_reg(du_head_p this_head,enum reg_class super_class,HARD_REG_SET * unavailable,int old_reg,bool best_rename)35838fd1498Szrj find_rename_reg (du_head_p this_head, enum reg_class super_class,
35938fd1498Szrj 		 HARD_REG_SET *unavailable, int old_reg, bool best_rename)
36038fd1498Szrj {
36138fd1498Szrj   bool has_preferred_class;
36238fd1498Szrj   enum reg_class preferred_class;
36338fd1498Szrj   int pass;
36438fd1498Szrj   int best_new_reg = old_reg;
36538fd1498Szrj 
36638fd1498Szrj   /* Further narrow the set of registers we can use for renaming.
36738fd1498Szrj      If the chain needs a call-saved register, mark the call-used
36838fd1498Szrj      registers as unavailable.  */
36938fd1498Szrj   if (this_head->need_caller_save_reg)
37038fd1498Szrj     IOR_HARD_REG_SET (*unavailable, call_used_reg_set);
37138fd1498Szrj 
37238fd1498Szrj   /* Mark registers that overlap this chain's lifetime as unavailable.  */
37338fd1498Szrj   merge_overlapping_regs (unavailable, this_head);
37438fd1498Szrj 
37538fd1498Szrj   /* Compute preferred rename class of super union of all the classes
37638fd1498Szrj      in the chain.  */
37738fd1498Szrj   preferred_class
37838fd1498Szrj     = (enum reg_class) targetm.preferred_rename_class (super_class);
37938fd1498Szrj 
38038fd1498Szrj   /* Pick and check the register from the tied chain iff the tied chain
38138fd1498Szrj      is not renamed.  */
38238fd1498Szrj   if (this_head->tied_chain && !this_head->tied_chain->renamed
38338fd1498Szrj       && check_new_reg_p (old_reg, this_head->tied_chain->regno,
38438fd1498Szrj 			  this_head, *unavailable))
38538fd1498Szrj     return this_head->tied_chain->regno;
38638fd1498Szrj 
38738fd1498Szrj   /* If PREFERRED_CLASS is not NO_REGS, we iterate in the first pass
38838fd1498Szrj      over registers that belong to PREFERRED_CLASS and try to find the
38938fd1498Szrj      best register within the class.  If that failed, we iterate in
39038fd1498Szrj      the second pass over registers that don't belong to the class.
39138fd1498Szrj      If PREFERRED_CLASS is NO_REGS, we iterate over all registers in
39238fd1498Szrj      ascending order without any preference.  */
39338fd1498Szrj   has_preferred_class = (preferred_class != NO_REGS);
39438fd1498Szrj   for (pass = (has_preferred_class ? 0 : 1); pass < 2; pass++)
39538fd1498Szrj     {
39638fd1498Szrj       int new_reg;
39738fd1498Szrj       for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++)
39838fd1498Szrj 	{
39938fd1498Szrj 	  if (has_preferred_class
40038fd1498Szrj 	      && (pass == 0)
40138fd1498Szrj 	      != TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
40238fd1498Szrj 				    new_reg))
40338fd1498Szrj 	    continue;
40438fd1498Szrj 
40538fd1498Szrj 	  if (!check_new_reg_p (old_reg, new_reg, this_head, *unavailable))
40638fd1498Szrj 	    continue;
40738fd1498Szrj 
40838fd1498Szrj 	  if (!best_rename)
40938fd1498Szrj 	    return new_reg;
41038fd1498Szrj 
41138fd1498Szrj 	  /* In the first pass, we force the renaming of registers that
41238fd1498Szrj 	     don't belong to PREFERRED_CLASS to registers that do, even
41338fd1498Szrj 	     though the latters were used not very long ago.  */
41438fd1498Szrj 	  if ((pass == 0
41538fd1498Szrj 	      && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
41638fd1498Szrj 				     best_new_reg))
41738fd1498Szrj 	      || tick[best_new_reg] > tick[new_reg])
41838fd1498Szrj 	    best_new_reg = new_reg;
41938fd1498Szrj 	}
42038fd1498Szrj       if (pass == 0 && best_new_reg != old_reg)
42138fd1498Szrj 	break;
42238fd1498Szrj     }
42338fd1498Szrj   return best_new_reg;
42438fd1498Szrj }
42538fd1498Szrj 
42638fd1498Szrj /* Iterate over elements in the chain HEAD in order to:
42738fd1498Szrj    1. Count number of uses, storing it in *PN_USES.
42838fd1498Szrj    2. Narrow the set of registers we can use for renaming, adding
42938fd1498Szrj       unavailable registers to *PUNAVAILABLE, which must be
43038fd1498Szrj       initialized by the caller.
43138fd1498Szrj    3. Compute the superunion of register classes in this chain
43238fd1498Szrj       and return it.  */
43338fd1498Szrj reg_class
regrename_find_superclass(du_head_p head,int * pn_uses,HARD_REG_SET * punavailable)43438fd1498Szrj regrename_find_superclass (du_head_p head, int *pn_uses,
43538fd1498Szrj 			   HARD_REG_SET *punavailable)
43638fd1498Szrj {
43738fd1498Szrj   int n_uses = 0;
43838fd1498Szrj   reg_class super_class = NO_REGS;
43938fd1498Szrj   for (du_chain *tmp = head->first; tmp; tmp = tmp->next_use)
44038fd1498Szrj     {
44138fd1498Szrj       if (DEBUG_INSN_P (tmp->insn))
44238fd1498Szrj 	continue;
44338fd1498Szrj       n_uses++;
44438fd1498Szrj       IOR_COMPL_HARD_REG_SET (*punavailable,
44538fd1498Szrj 			      reg_class_contents[tmp->cl]);
44638fd1498Szrj       super_class
44738fd1498Szrj 	= reg_class_superunion[(int) super_class][(int) tmp->cl];
44838fd1498Szrj     }
44938fd1498Szrj   *pn_uses = n_uses;
45038fd1498Szrj   return super_class;
45138fd1498Szrj }
45238fd1498Szrj 
45338fd1498Szrj /* Perform register renaming on the current function.  */
45438fd1498Szrj static void
rename_chains(void)45538fd1498Szrj rename_chains (void)
45638fd1498Szrj {
45738fd1498Szrj   HARD_REG_SET unavailable;
45838fd1498Szrj   du_head_p this_head;
45938fd1498Szrj   int i;
46038fd1498Szrj 
46138fd1498Szrj   memset (tick, 0, sizeof tick);
46238fd1498Szrj 
46338fd1498Szrj   CLEAR_HARD_REG_SET (unavailable);
46438fd1498Szrj   /* Don't clobber traceback for noreturn functions.  */
46538fd1498Szrj   if (frame_pointer_needed)
46638fd1498Szrj     {
46738fd1498Szrj       add_to_hard_reg_set (&unavailable, Pmode, FRAME_POINTER_REGNUM);
46838fd1498Szrj       if (!HARD_FRAME_POINTER_IS_FRAME_POINTER)
46938fd1498Szrj 	add_to_hard_reg_set (&unavailable, Pmode, HARD_FRAME_POINTER_REGNUM);
47038fd1498Szrj     }
47138fd1498Szrj 
47238fd1498Szrj   FOR_EACH_VEC_ELT (id_to_chain, i, this_head)
47338fd1498Szrj     {
47438fd1498Szrj       int best_new_reg;
47538fd1498Szrj       int n_uses;
47638fd1498Szrj       HARD_REG_SET this_unavailable;
47738fd1498Szrj       int reg = this_head->regno;
47838fd1498Szrj 
47938fd1498Szrj       if (this_head->cannot_rename)
48038fd1498Szrj 	continue;
48138fd1498Szrj 
48238fd1498Szrj       if (fixed_regs[reg] || global_regs[reg]
48338fd1498Szrj 	  || (!HARD_FRAME_POINTER_IS_FRAME_POINTER && frame_pointer_needed
48438fd1498Szrj 	      && reg == HARD_FRAME_POINTER_REGNUM)
48538fd1498Szrj 	  || (HARD_FRAME_POINTER_IS_FRAME_POINTER && frame_pointer_needed
48638fd1498Szrj 	      && reg == FRAME_POINTER_REGNUM))
48738fd1498Szrj 	continue;
48838fd1498Szrj 
48938fd1498Szrj       COPY_HARD_REG_SET (this_unavailable, unavailable);
49038fd1498Szrj 
49138fd1498Szrj       reg_class super_class = regrename_find_superclass (this_head, &n_uses,
49238fd1498Szrj 							 &this_unavailable);
49338fd1498Szrj       if (n_uses < 2)
49438fd1498Szrj 	continue;
49538fd1498Szrj 
49638fd1498Szrj       best_new_reg = find_rename_reg (this_head, super_class,
49738fd1498Szrj 				      &this_unavailable, reg, true);
49838fd1498Szrj 
49938fd1498Szrj       if (dump_file)
50038fd1498Szrj 	{
50138fd1498Szrj 	  fprintf (dump_file, "Register %s in insn %d",
50238fd1498Szrj 		   reg_names[reg], INSN_UID (this_head->first->insn));
50338fd1498Szrj 	  if (this_head->need_caller_save_reg)
50438fd1498Szrj 	    fprintf (dump_file, " crosses a call");
50538fd1498Szrj 	}
50638fd1498Szrj 
50738fd1498Szrj       if (best_new_reg == reg)
50838fd1498Szrj 	{
50938fd1498Szrj 	  tick[reg] = ++this_tick;
51038fd1498Szrj 	  if (dump_file)
51138fd1498Szrj 	    fprintf (dump_file, "; no available better choice\n");
51238fd1498Szrj 	  continue;
51338fd1498Szrj 	}
51438fd1498Szrj 
51538fd1498Szrj       if (regrename_do_replace (this_head, best_new_reg))
51638fd1498Szrj 	{
51738fd1498Szrj 	  if (dump_file)
51838fd1498Szrj 	    fprintf (dump_file, ", renamed as %s\n", reg_names[best_new_reg]);
51938fd1498Szrj 	  tick[best_new_reg] = ++this_tick;
52038fd1498Szrj 	  df_set_regs_ever_live (best_new_reg, true);
52138fd1498Szrj 	}
52238fd1498Szrj       else
52338fd1498Szrj 	{
52438fd1498Szrj 	  if (dump_file)
52538fd1498Szrj 	    fprintf (dump_file, ", renaming as %s failed\n",
52638fd1498Szrj 		     reg_names[best_new_reg]);
52738fd1498Szrj 	  tick[reg] = ++this_tick;
52838fd1498Szrj 	}
52938fd1498Szrj     }
53038fd1498Szrj }
53138fd1498Szrj 
53238fd1498Szrj /* A structure to record information for each hard register at the start of
53338fd1498Szrj    a basic block.  */
53438fd1498Szrj struct incoming_reg_info {
53538fd1498Szrj   /* Holds the number of registers used in the chain that gave us information
53638fd1498Szrj      about this register.  Zero means no information known yet, while a
53738fd1498Szrj      negative value is used for something that is part of, but not the first
53838fd1498Szrj      register in a multi-register value.  */
53938fd1498Szrj   int nregs;
54038fd1498Szrj   /* Set to true if we have accesses that conflict in the number of registers
54138fd1498Szrj      used.  */
54238fd1498Szrj   bool unusable;
54338fd1498Szrj };
54438fd1498Szrj 
54538fd1498Szrj /* A structure recording information about each basic block.  It is saved
54638fd1498Szrj    and restored around basic block boundaries.
54738fd1498Szrj    A pointer to such a structure is stored in each basic block's aux field
54838fd1498Szrj    during regrename_analyze, except for blocks we know can't be optimized
54938fd1498Szrj    (such as entry and exit blocks).  */
55038fd1498Szrj struct bb_rename_info
55138fd1498Szrj {
55238fd1498Szrj   /* The basic block corresponding to this structure.  */
55338fd1498Szrj   basic_block bb;
55438fd1498Szrj   /* Copies of the global information.  */
55538fd1498Szrj   bitmap_head open_chains_set;
55638fd1498Szrj   bitmap_head incoming_open_chains_set;
55738fd1498Szrj   struct incoming_reg_info incoming[FIRST_PSEUDO_REGISTER];
55838fd1498Szrj };
55938fd1498Szrj 
56038fd1498Szrj /* Initialize a rename_info structure P for basic block BB, which starts a new
56138fd1498Szrj    scan.  */
56238fd1498Szrj static void
init_rename_info(struct bb_rename_info * p,basic_block bb)56338fd1498Szrj init_rename_info (struct bb_rename_info *p, basic_block bb)
56438fd1498Szrj {
56538fd1498Szrj   int i;
56638fd1498Szrj   df_ref def;
56738fd1498Szrj   HARD_REG_SET start_chains_set;
56838fd1498Szrj 
56938fd1498Szrj   p->bb = bb;
57038fd1498Szrj   bitmap_initialize (&p->open_chains_set, &bitmap_default_obstack);
57138fd1498Szrj   bitmap_initialize (&p->incoming_open_chains_set, &bitmap_default_obstack);
57238fd1498Szrj 
57338fd1498Szrj   open_chains = NULL;
57438fd1498Szrj   bitmap_clear (&open_chains_set);
57538fd1498Szrj 
57638fd1498Szrj   CLEAR_HARD_REG_SET (live_in_chains);
57738fd1498Szrj   REG_SET_TO_HARD_REG_SET (live_hard_regs, df_get_live_in (bb));
57838fd1498Szrj   FOR_EACH_ARTIFICIAL_DEF (def, bb->index)
57938fd1498Szrj     if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
58038fd1498Szrj       SET_HARD_REG_BIT (live_hard_regs, DF_REF_REGNO (def));
58138fd1498Szrj 
58238fd1498Szrj   /* Open chains based on information from (at least one) predecessor
58338fd1498Szrj      block.  This gives us a chance later on to combine chains across
58438fd1498Szrj      basic block boundaries.  Inconsistencies (in access sizes) will
58538fd1498Szrj      be caught normally and dealt with conservatively by disabling the
58638fd1498Szrj      chain for renaming, and there is no risk of losing optimization
58738fd1498Szrj      opportunities by opening chains either: if we did not open the
58838fd1498Szrj      chains, we'd have to track the live register as a hard reg, and
58938fd1498Szrj      we'd be unable to rename it in any case.  */
59038fd1498Szrj   CLEAR_HARD_REG_SET (start_chains_set);
59138fd1498Szrj   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
59238fd1498Szrj     {
59338fd1498Szrj       struct incoming_reg_info *iri = p->incoming + i;
59438fd1498Szrj       if (iri->nregs > 0 && !iri->unusable
59538fd1498Szrj 	  && range_in_hard_reg_set_p (live_hard_regs, i, iri->nregs))
59638fd1498Szrj 	{
59738fd1498Szrj 	  SET_HARD_REG_BIT (start_chains_set, i);
59838fd1498Szrj 	  remove_range_from_hard_reg_set (&live_hard_regs, i, iri->nregs);
59938fd1498Szrj 	}
60038fd1498Szrj     }
60138fd1498Szrj   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
60238fd1498Szrj     {
60338fd1498Szrj       struct incoming_reg_info *iri = p->incoming + i;
60438fd1498Szrj       if (TEST_HARD_REG_BIT (start_chains_set, i))
60538fd1498Szrj 	{
60638fd1498Szrj 	  du_head_p chain;
60738fd1498Szrj 	  if (dump_file)
60838fd1498Szrj 	    fprintf (dump_file, "opening incoming chain\n");
60938fd1498Szrj 	  chain = create_new_chain (i, iri->nregs, NULL, NULL, NO_REGS);
61038fd1498Szrj 	  bitmap_set_bit (&p->incoming_open_chains_set, chain->id);
61138fd1498Szrj 	}
61238fd1498Szrj     }
61338fd1498Szrj }
61438fd1498Szrj 
61538fd1498Szrj /* Record in RI that the block corresponding to it has an incoming
61638fd1498Szrj    live value, described by CHAIN.  */
61738fd1498Szrj static void
set_incoming_from_chain(struct bb_rename_info * ri,du_head_p chain)61838fd1498Szrj set_incoming_from_chain (struct bb_rename_info *ri, du_head_p chain)
61938fd1498Szrj {
62038fd1498Szrj   int i;
62138fd1498Szrj   int incoming_nregs = ri->incoming[chain->regno].nregs;
62238fd1498Szrj   int nregs;
62338fd1498Szrj 
62438fd1498Szrj   /* If we've recorded the same information before, everything is fine.  */
62538fd1498Szrj   if (incoming_nregs == chain->nregs)
62638fd1498Szrj     {
62738fd1498Szrj       if (dump_file)
62838fd1498Szrj 	fprintf (dump_file, "reg %d/%d already recorded\n",
62938fd1498Szrj 		 chain->regno, chain->nregs);
63038fd1498Szrj       return;
63138fd1498Szrj     }
63238fd1498Szrj 
63338fd1498Szrj   /* If we have no information for any of the involved registers, update
63438fd1498Szrj      the incoming array.  */
63538fd1498Szrj   nregs = chain->nregs;
63638fd1498Szrj   while (nregs-- > 0)
63738fd1498Szrj     if (ri->incoming[chain->regno + nregs].nregs != 0
63838fd1498Szrj 	|| ri->incoming[chain->regno + nregs].unusable)
63938fd1498Szrj       break;
64038fd1498Szrj   if (nregs < 0)
64138fd1498Szrj     {
64238fd1498Szrj       nregs = chain->nregs;
64338fd1498Szrj       ri->incoming[chain->regno].nregs = nregs;
64438fd1498Szrj       while (nregs-- > 1)
64538fd1498Szrj 	ri->incoming[chain->regno + nregs].nregs = -nregs;
64638fd1498Szrj       if (dump_file)
64738fd1498Szrj 	fprintf (dump_file, "recorded reg %d/%d\n",
64838fd1498Szrj 		 chain->regno, chain->nregs);
64938fd1498Szrj       return;
65038fd1498Szrj     }
65138fd1498Szrj 
65238fd1498Szrj   /* There must be some kind of conflict.  Prevent both the old and
65338fd1498Szrj      new ranges from being used.  */
65438fd1498Szrj   if (incoming_nregs < 0)
65538fd1498Szrj     ri->incoming[chain->regno + incoming_nregs].unusable = true;
65638fd1498Szrj   for (i = 0; i < chain->nregs; i++)
65738fd1498Szrj     ri->incoming[chain->regno + i].unusable = true;
65838fd1498Szrj }
65938fd1498Szrj 
66038fd1498Szrj /* Merge the two chains C1 and C2 so that all conflict information is
66138fd1498Szrj    recorded and C1, and the id of C2 is changed to that of C1.  */
66238fd1498Szrj static void
merge_chains(du_head_p c1,du_head_p c2)66338fd1498Szrj merge_chains (du_head_p c1, du_head_p c2)
66438fd1498Szrj {
66538fd1498Szrj   if (c1 == c2)
66638fd1498Szrj     return;
66738fd1498Szrj 
66838fd1498Szrj   if (c2->first != NULL)
66938fd1498Szrj     {
67038fd1498Szrj       if (c1->first == NULL)
67138fd1498Szrj 	c1->first = c2->first;
67238fd1498Szrj       else
67338fd1498Szrj 	c1->last->next_use = c2->first;
67438fd1498Szrj       c1->last = c2->last;
67538fd1498Szrj     }
67638fd1498Szrj 
67738fd1498Szrj   c2->first = c2->last = NULL;
67838fd1498Szrj   c2->id = c1->id;
67938fd1498Szrj 
68038fd1498Szrj   IOR_HARD_REG_SET (c1->hard_conflicts, c2->hard_conflicts);
68138fd1498Szrj   bitmap_ior_into (&c1->conflicts, &c2->conflicts);
68238fd1498Szrj 
68338fd1498Szrj   c1->need_caller_save_reg |= c2->need_caller_save_reg;
68438fd1498Szrj   c1->cannot_rename |= c2->cannot_rename;
68538fd1498Szrj }
68638fd1498Szrj 
68738fd1498Szrj /* Analyze the current function and build chains for renaming.  */
68838fd1498Szrj 
68938fd1498Szrj void
regrename_analyze(bitmap bb_mask)69038fd1498Szrj regrename_analyze (bitmap bb_mask)
69138fd1498Szrj {
69238fd1498Szrj   struct bb_rename_info *rename_info;
69338fd1498Szrj   int i;
69438fd1498Szrj   basic_block bb;
69538fd1498Szrj   int n_bbs;
69638fd1498Szrj   int *inverse_postorder;
69738fd1498Szrj 
69838fd1498Szrj   inverse_postorder = XNEWVEC (int, last_basic_block_for_fn (cfun));
69938fd1498Szrj   n_bbs = pre_and_rev_post_order_compute (NULL, inverse_postorder, false);
70038fd1498Szrj 
70138fd1498Szrj   /* Gather some information about the blocks in this function.  */
70238fd1498Szrj   rename_info = XCNEWVEC (struct bb_rename_info, n_basic_blocks_for_fn (cfun));
70338fd1498Szrj   i = 0;
70438fd1498Szrj   FOR_EACH_BB_FN (bb, cfun)
70538fd1498Szrj     {
70638fd1498Szrj       struct bb_rename_info *ri = rename_info + i;
70738fd1498Szrj       ri->bb = bb;
70838fd1498Szrj       if (bb_mask != NULL && !bitmap_bit_p (bb_mask, bb->index))
70938fd1498Szrj 	bb->aux = NULL;
71038fd1498Szrj       else
71138fd1498Szrj 	bb->aux = ri;
71238fd1498Szrj       i++;
71338fd1498Szrj     }
71438fd1498Szrj 
71538fd1498Szrj   current_id = 0;
71638fd1498Szrj   id_to_chain.create (0);
71738fd1498Szrj   bitmap_initialize (&open_chains_set, &bitmap_default_obstack);
71838fd1498Szrj 
71938fd1498Szrj   /* The order in which we visit blocks ensures that whenever
72038fd1498Szrj      possible, we only process a block after at least one of its
72138fd1498Szrj      predecessors, which provides a "seeding" effect to make the logic
72238fd1498Szrj      in set_incoming_from_chain and init_rename_info useful.  */
72338fd1498Szrj 
72438fd1498Szrj   for (i = 0; i < n_bbs; i++)
72538fd1498Szrj     {
72638fd1498Szrj       basic_block bb1 = BASIC_BLOCK_FOR_FN (cfun, inverse_postorder[i]);
72738fd1498Szrj       struct bb_rename_info *this_info;
72838fd1498Szrj       bool success;
72938fd1498Szrj       edge e;
73038fd1498Szrj       edge_iterator ei;
73138fd1498Szrj       int old_length = id_to_chain.length ();
73238fd1498Szrj 
73338fd1498Szrj       this_info = (struct bb_rename_info *) bb1->aux;
73438fd1498Szrj       if (this_info == NULL)
73538fd1498Szrj 	continue;
73638fd1498Szrj 
73738fd1498Szrj       if (dump_file)
73838fd1498Szrj 	fprintf (dump_file, "\nprocessing block %d:\n", bb1->index);
73938fd1498Szrj 
74038fd1498Szrj       init_rename_info (this_info, bb1);
74138fd1498Szrj 
74238fd1498Szrj       success = build_def_use (bb1);
74338fd1498Szrj       if (!success)
74438fd1498Szrj 	{
74538fd1498Szrj 	  if (dump_file)
74638fd1498Szrj 	    fprintf (dump_file, "failed\n");
74738fd1498Szrj 	  bb1->aux = NULL;
74838fd1498Szrj 	  id_to_chain.truncate (old_length);
74938fd1498Szrj 	  current_id = old_length;
75038fd1498Szrj 	  bitmap_clear (&this_info->incoming_open_chains_set);
75138fd1498Szrj 	  open_chains = NULL;
75238fd1498Szrj 	  if (insn_rr.exists ())
75338fd1498Szrj 	    {
75438fd1498Szrj 	      rtx_insn *insn;
75538fd1498Szrj 	      FOR_BB_INSNS (bb1, insn)
75638fd1498Szrj 		{
75738fd1498Szrj 		  insn_rr_info *p = &insn_rr[INSN_UID (insn)];
75838fd1498Szrj 		  p->op_info = NULL;
75938fd1498Szrj 		}
76038fd1498Szrj 	    }
76138fd1498Szrj 	  continue;
76238fd1498Szrj 	}
76338fd1498Szrj 
76438fd1498Szrj       if (dump_file)
76538fd1498Szrj 	dump_def_use_chain (old_length);
76638fd1498Szrj       bitmap_copy (&this_info->open_chains_set, &open_chains_set);
76738fd1498Szrj 
76838fd1498Szrj       /* Add successor blocks to the worklist if necessary, and record
76938fd1498Szrj 	 data about our own open chains at the end of this block, which
77038fd1498Szrj 	 will be used to pre-open chains when processing the successors.  */
77138fd1498Szrj       FOR_EACH_EDGE (e, ei, bb1->succs)
77238fd1498Szrj 	{
77338fd1498Szrj 	  struct bb_rename_info *dest_ri;
77438fd1498Szrj 	  struct du_head *chain;
77538fd1498Szrj 
77638fd1498Szrj 	  if (dump_file)
77738fd1498Szrj 	    fprintf (dump_file, "successor block %d\n", e->dest->index);
77838fd1498Szrj 
77938fd1498Szrj 	  if (e->flags & (EDGE_EH | EDGE_ABNORMAL))
78038fd1498Szrj 	    continue;
78138fd1498Szrj 	  dest_ri = (struct bb_rename_info *)e->dest->aux;
78238fd1498Szrj 	  if (dest_ri == NULL)
78338fd1498Szrj 	    continue;
78438fd1498Szrj 	  for (chain = open_chains; chain; chain = chain->next_chain)
78538fd1498Szrj 	    set_incoming_from_chain (dest_ri, chain);
78638fd1498Szrj 	}
78738fd1498Szrj     }
78838fd1498Szrj 
78938fd1498Szrj   free (inverse_postorder);
79038fd1498Szrj 
79138fd1498Szrj   /* Now, combine the chains data we have gathered across basic block
79238fd1498Szrj      boundaries.
79338fd1498Szrj 
79438fd1498Szrj      For every basic block, there may be chains open at the start, or at the
79538fd1498Szrj      end.  Rather than exclude them from renaming, we look for open chains
79638fd1498Szrj      with matching registers at the other side of the CFG edge.
79738fd1498Szrj 
79838fd1498Szrj      For a given chain using register R, open at the start of block B, we
79938fd1498Szrj      must find an open chain using R on the other side of every edge leading
80038fd1498Szrj      to B, if the register is live across this edge.  In the code below,
80138fd1498Szrj      N_PREDS_USED counts the number of edges where the register is live, and
80238fd1498Szrj      N_PREDS_JOINED counts those where we found an appropriate chain for
80338fd1498Szrj      joining.
80438fd1498Szrj 
80538fd1498Szrj      We perform the analysis for both incoming and outgoing edges, but we
80638fd1498Szrj      only need to merge once (in the second part, after verifying outgoing
80738fd1498Szrj      edges).  */
80838fd1498Szrj   FOR_EACH_BB_FN (bb, cfun)
80938fd1498Szrj     {
81038fd1498Szrj       struct bb_rename_info *bb_ri = (struct bb_rename_info *) bb->aux;
81138fd1498Szrj       unsigned j;
81238fd1498Szrj       bitmap_iterator bi;
81338fd1498Szrj 
81438fd1498Szrj       if (bb_ri == NULL)
81538fd1498Szrj 	continue;
81638fd1498Szrj 
81738fd1498Szrj       if (dump_file)
81838fd1498Szrj 	fprintf (dump_file, "processing bb %d in edges\n", bb->index);
81938fd1498Szrj 
82038fd1498Szrj       EXECUTE_IF_SET_IN_BITMAP (&bb_ri->incoming_open_chains_set, 0, j, bi)
82138fd1498Szrj 	{
82238fd1498Szrj 	  edge e;
82338fd1498Szrj 	  edge_iterator ei;
82438fd1498Szrj 	  struct du_head *chain = regrename_chain_from_id (j);
82538fd1498Szrj 	  int n_preds_used = 0, n_preds_joined = 0;
82638fd1498Szrj 
82738fd1498Szrj 	  FOR_EACH_EDGE (e, ei, bb->preds)
82838fd1498Szrj 	    {
82938fd1498Szrj 	      struct bb_rename_info *src_ri;
83038fd1498Szrj 	      unsigned k;
83138fd1498Szrj 	      bitmap_iterator bi2;
83238fd1498Szrj 	      HARD_REG_SET live;
83338fd1498Szrj 	      bool success = false;
83438fd1498Szrj 
83538fd1498Szrj 	      REG_SET_TO_HARD_REG_SET (live, df_get_live_out (e->src));
83638fd1498Szrj 	      if (!range_overlaps_hard_reg_set_p (live, chain->regno,
83738fd1498Szrj 						  chain->nregs))
83838fd1498Szrj 		continue;
83938fd1498Szrj 	      n_preds_used++;
84038fd1498Szrj 
84138fd1498Szrj 	      if (e->flags & (EDGE_EH | EDGE_ABNORMAL))
84238fd1498Szrj 		continue;
84338fd1498Szrj 
84438fd1498Szrj 	      src_ri = (struct bb_rename_info *)e->src->aux;
84538fd1498Szrj 	      if (src_ri == NULL)
84638fd1498Szrj 		continue;
84738fd1498Szrj 
84838fd1498Szrj 	      EXECUTE_IF_SET_IN_BITMAP (&src_ri->open_chains_set,
84938fd1498Szrj 					0, k, bi2)
85038fd1498Szrj 		{
85138fd1498Szrj 		  struct du_head *outgoing_chain = regrename_chain_from_id (k);
85238fd1498Szrj 
85338fd1498Szrj 		  if (outgoing_chain->regno == chain->regno
85438fd1498Szrj 		      && outgoing_chain->nregs == chain->nregs)
85538fd1498Szrj 		    {
85638fd1498Szrj 		      n_preds_joined++;
85738fd1498Szrj 		      success = true;
85838fd1498Szrj 		      break;
85938fd1498Szrj 		    }
86038fd1498Szrj 		}
86138fd1498Szrj 	      if (!success && dump_file)
86238fd1498Szrj 		fprintf (dump_file, "failure to match with pred block %d\n",
86338fd1498Szrj 			 e->src->index);
86438fd1498Szrj 	    }
86538fd1498Szrj 	  if (n_preds_joined < n_preds_used)
86638fd1498Szrj 	    {
86738fd1498Szrj 	      if (dump_file)
86838fd1498Szrj 		fprintf (dump_file, "cannot rename chain %d\n", j);
86938fd1498Szrj 	      chain->cannot_rename = 1;
87038fd1498Szrj 	    }
87138fd1498Szrj 	}
87238fd1498Szrj     }
87338fd1498Szrj   FOR_EACH_BB_FN (bb, cfun)
87438fd1498Szrj     {
87538fd1498Szrj       struct bb_rename_info *bb_ri = (struct bb_rename_info *) bb->aux;
87638fd1498Szrj       unsigned j;
87738fd1498Szrj       bitmap_iterator bi;
87838fd1498Szrj 
87938fd1498Szrj       if (bb_ri == NULL)
88038fd1498Szrj 	continue;
88138fd1498Szrj 
88238fd1498Szrj       if (dump_file)
88338fd1498Szrj 	fprintf (dump_file, "processing bb %d out edges\n", bb->index);
88438fd1498Szrj 
88538fd1498Szrj       EXECUTE_IF_SET_IN_BITMAP (&bb_ri->open_chains_set, 0, j, bi)
88638fd1498Szrj 	{
88738fd1498Szrj 	  edge e;
88838fd1498Szrj 	  edge_iterator ei;
88938fd1498Szrj 	  struct du_head *chain = regrename_chain_from_id (j);
89038fd1498Szrj 	  int n_succs_used = 0, n_succs_joined = 0;
89138fd1498Szrj 
89238fd1498Szrj 	  FOR_EACH_EDGE (e, ei, bb->succs)
89338fd1498Szrj 	    {
89438fd1498Szrj 	      bool printed = false;
89538fd1498Szrj 	      struct bb_rename_info *dest_ri;
89638fd1498Szrj 	      unsigned k;
89738fd1498Szrj 	      bitmap_iterator bi2;
89838fd1498Szrj 	      HARD_REG_SET live;
89938fd1498Szrj 
90038fd1498Szrj 	      REG_SET_TO_HARD_REG_SET (live, df_get_live_in (e->dest));
90138fd1498Szrj 	      if (!range_overlaps_hard_reg_set_p (live, chain->regno,
90238fd1498Szrj 						  chain->nregs))
90338fd1498Szrj 		continue;
90438fd1498Szrj 
90538fd1498Szrj 	      n_succs_used++;
90638fd1498Szrj 
90738fd1498Szrj 	      dest_ri = (struct bb_rename_info *)e->dest->aux;
90838fd1498Szrj 	      if (dest_ri == NULL)
90938fd1498Szrj 		continue;
91038fd1498Szrj 
91138fd1498Szrj 	      EXECUTE_IF_SET_IN_BITMAP (&dest_ri->incoming_open_chains_set,
91238fd1498Szrj 					0, k, bi2)
91338fd1498Szrj 		{
91438fd1498Szrj 		  struct du_head *incoming_chain = regrename_chain_from_id (k);
91538fd1498Szrj 
91638fd1498Szrj 		  if (incoming_chain->regno == chain->regno
91738fd1498Szrj 		      && incoming_chain->nregs == chain->nregs)
91838fd1498Szrj 		    {
91938fd1498Szrj 		      if (dump_file)
92038fd1498Szrj 			{
92138fd1498Szrj 			  if (!printed)
92238fd1498Szrj 			    fprintf (dump_file,
92338fd1498Szrj 				     "merging blocks for edge %d -> %d\n",
92438fd1498Szrj 				     e->src->index, e->dest->index);
92538fd1498Szrj 			  printed = true;
92638fd1498Szrj 			  fprintf (dump_file,
92738fd1498Szrj 				   "  merging chains %d (->%d) and %d (->%d) [%s]\n",
92838fd1498Szrj 				   k, incoming_chain->id, j, chain->id,
92938fd1498Szrj 				   reg_names[incoming_chain->regno]);
93038fd1498Szrj 			}
93138fd1498Szrj 
93238fd1498Szrj 		      merge_chains (chain, incoming_chain);
93338fd1498Szrj 		      n_succs_joined++;
93438fd1498Szrj 		      break;
93538fd1498Szrj 		    }
93638fd1498Szrj 		}
93738fd1498Szrj 	    }
93838fd1498Szrj 	  if (n_succs_joined < n_succs_used)
93938fd1498Szrj 	    {
94038fd1498Szrj 	      if (dump_file)
94138fd1498Szrj 		fprintf (dump_file, "cannot rename chain %d\n",
94238fd1498Szrj 			 j);
94338fd1498Szrj 	      chain->cannot_rename = 1;
94438fd1498Szrj 	    }
94538fd1498Szrj 	}
94638fd1498Szrj     }
94738fd1498Szrj 
94838fd1498Szrj   free (rename_info);
94938fd1498Szrj 
95038fd1498Szrj   FOR_EACH_BB_FN (bb, cfun)
95138fd1498Szrj     bb->aux = NULL;
95238fd1498Szrj }
95338fd1498Szrj 
95438fd1498Szrj /* Attempt to replace all uses of the register in the chain beginning with
95538fd1498Szrj    HEAD with REG.  Returns true on success and false if the replacement is
95638fd1498Szrj    rejected because the insns would not validate.  The latter can happen
95738fd1498Szrj    e.g. if a match_parallel predicate enforces restrictions on register
95838fd1498Szrj    numbering in its subpatterns.  */
95938fd1498Szrj 
96038fd1498Szrj bool
regrename_do_replace(struct du_head * head,int reg)96138fd1498Szrj regrename_do_replace (struct du_head *head, int reg)
96238fd1498Szrj {
96338fd1498Szrj   struct du_chain *chain;
96438fd1498Szrj   unsigned int base_regno = head->regno;
96538fd1498Szrj   machine_mode mode;
96638fd1498Szrj   rtx last_reg = NULL_RTX, last_repl = NULL_RTX;
96738fd1498Szrj 
96838fd1498Szrj   for (chain = head->first; chain; chain = chain->next_use)
96938fd1498Szrj     {
97038fd1498Szrj       unsigned int regno = ORIGINAL_REGNO (*chain->loc);
97138fd1498Szrj       struct reg_attrs *attr = REG_ATTRS (*chain->loc);
97238fd1498Szrj       int reg_ptr = REG_POINTER (*chain->loc);
97338fd1498Szrj 
97438fd1498Szrj       if (DEBUG_INSN_P (chain->insn) && REGNO (*chain->loc) != base_regno)
97538fd1498Szrj 	validate_change (chain->insn, &(INSN_VAR_LOCATION_LOC (chain->insn)),
97638fd1498Szrj 			 gen_rtx_UNKNOWN_VAR_LOC (), true);
97738fd1498Szrj       else
97838fd1498Szrj 	{
97938fd1498Szrj 	  if (*chain->loc != last_reg)
98038fd1498Szrj 	    {
98138fd1498Szrj 	      last_repl = gen_raw_REG (GET_MODE (*chain->loc), reg);
98238fd1498Szrj 	      if (regno >= FIRST_PSEUDO_REGISTER)
98338fd1498Szrj 		ORIGINAL_REGNO (last_repl) = regno;
98438fd1498Szrj 	      REG_ATTRS (last_repl) = attr;
98538fd1498Szrj 	      REG_POINTER (last_repl) = reg_ptr;
98638fd1498Szrj 	      last_reg = *chain->loc;
98738fd1498Szrj 	    }
98838fd1498Szrj 	  validate_change (chain->insn, chain->loc, last_repl, true);
98938fd1498Szrj 	}
99038fd1498Szrj     }
99138fd1498Szrj 
99238fd1498Szrj   if (!apply_change_group ())
99338fd1498Szrj     return false;
99438fd1498Szrj 
99538fd1498Szrj   mode = GET_MODE (*head->first->loc);
99638fd1498Szrj   head->renamed = 1;
99738fd1498Szrj   head->regno = reg;
99838fd1498Szrj   head->nregs = hard_regno_nregs (reg, mode);
99938fd1498Szrj   return true;
100038fd1498Szrj }
100138fd1498Szrj 
100238fd1498Szrj 
100338fd1498Szrj /* True if we found a register with a size mismatch, which means that we
100438fd1498Szrj    can't track its lifetime accurately.  If so, we abort the current block
100538fd1498Szrj    without renaming.  */
100638fd1498Szrj static bool fail_current_block;
100738fd1498Szrj 
100838fd1498Szrj /* Return true if OP is a reg for which all bits are set in PSET, false
100938fd1498Szrj    if all bits are clear.
101038fd1498Szrj    In other cases, set fail_current_block and return false.  */
101138fd1498Szrj 
101238fd1498Szrj static bool
verify_reg_in_set(rtx op,HARD_REG_SET * pset)101338fd1498Szrj verify_reg_in_set (rtx op, HARD_REG_SET *pset)
101438fd1498Szrj {
101538fd1498Szrj   unsigned regno, nregs;
101638fd1498Szrj   bool all_live, all_dead;
101738fd1498Szrj   if (!REG_P (op))
101838fd1498Szrj     return false;
101938fd1498Szrj 
102038fd1498Szrj   regno = REGNO (op);
102138fd1498Szrj   nregs = REG_NREGS (op);
102238fd1498Szrj   all_live = all_dead = true;
102338fd1498Szrj   while (nregs-- > 0)
102438fd1498Szrj     if (TEST_HARD_REG_BIT (*pset, regno + nregs))
102538fd1498Szrj       all_dead = false;
102638fd1498Szrj     else
102738fd1498Szrj       all_live = false;
102838fd1498Szrj   if (!all_dead && !all_live)
102938fd1498Szrj     {
103038fd1498Szrj       fail_current_block = true;
103138fd1498Szrj       return false;
103238fd1498Szrj     }
103338fd1498Szrj   return all_live;
103438fd1498Szrj }
103538fd1498Szrj 
103638fd1498Szrj /* Return true if OP is a reg that is being tracked already in some form.
103738fd1498Szrj    May set fail_current_block if it sees an unhandled case of overlap.  */
103838fd1498Szrj 
103938fd1498Szrj static bool
verify_reg_tracked(rtx op)104038fd1498Szrj verify_reg_tracked (rtx op)
104138fd1498Szrj {
104238fd1498Szrj   return (verify_reg_in_set (op, &live_hard_regs)
104338fd1498Szrj 	  || verify_reg_in_set (op, &live_in_chains));
104438fd1498Szrj }
104538fd1498Szrj 
104638fd1498Szrj /* Called through note_stores.  DATA points to a rtx_code, either SET or
104738fd1498Szrj    CLOBBER, which tells us which kind of rtx to look at.  If we have a
104838fd1498Szrj    match, record the set register in live_hard_regs and in the hard_conflicts
104938fd1498Szrj    bitmap of open chains.  */
105038fd1498Szrj 
105138fd1498Szrj static void
note_sets_clobbers(rtx x,const_rtx set,void * data)105238fd1498Szrj note_sets_clobbers (rtx x, const_rtx set, void *data)
105338fd1498Szrj {
105438fd1498Szrj   enum rtx_code code = *(enum rtx_code *)data;
105538fd1498Szrj   struct du_head *chain;
105638fd1498Szrj 
105738fd1498Szrj   if (GET_CODE (x) == SUBREG)
105838fd1498Szrj     x = SUBREG_REG (x);
105938fd1498Szrj   if (!REG_P (x) || GET_CODE (set) != code)
106038fd1498Szrj     return;
106138fd1498Szrj   /* There must not be pseudos at this point.  */
106238fd1498Szrj   gcc_assert (HARD_REGISTER_P (x));
106338fd1498Szrj   add_to_hard_reg_set (&live_hard_regs, GET_MODE (x), REGNO (x));
106438fd1498Szrj   for (chain = open_chains; chain; chain = chain->next_chain)
106538fd1498Szrj     add_to_hard_reg_set (&chain->hard_conflicts, GET_MODE (x), REGNO (x));
106638fd1498Szrj }
106738fd1498Szrj 
106838fd1498Szrj static void
scan_rtx_reg(rtx_insn * insn,rtx * loc,enum reg_class cl,enum scan_actions action,enum op_type type)106938fd1498Szrj scan_rtx_reg (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions action,
107038fd1498Szrj 	      enum op_type type)
107138fd1498Szrj {
107238fd1498Szrj   struct du_head **p;
107338fd1498Szrj   rtx x = *loc;
107438fd1498Szrj   unsigned this_regno = REGNO (x);
107538fd1498Szrj   int this_nregs = REG_NREGS (x);
107638fd1498Szrj 
107738fd1498Szrj   if (action == mark_write)
107838fd1498Szrj     {
107938fd1498Szrj       if (type == OP_OUT)
108038fd1498Szrj 	{
108138fd1498Szrj 	  du_head_p c;
108238fd1498Szrj 	  rtx pat = PATTERN (insn);
108338fd1498Szrj 
108438fd1498Szrj 	  c = create_new_chain (this_regno, this_nregs, loc, insn, cl);
108538fd1498Szrj 
108638fd1498Szrj 	  /* We try to tie chains in a move instruction for
108738fd1498Szrj 	     a single output.  */
108838fd1498Szrj 	  if (recog_data.n_operands == 2
108938fd1498Szrj 	      && GET_CODE (pat) == SET
109038fd1498Szrj 	      && GET_CODE (SET_DEST (pat)) == REG
109138fd1498Szrj 	      && GET_CODE (SET_SRC (pat)) == REG
109238fd1498Szrj 	      && terminated_this_insn
109338fd1498Szrj 	      && terminated_this_insn->nregs
109438fd1498Szrj 		 == REG_NREGS (recog_data.operand[1]))
109538fd1498Szrj 	    {
109638fd1498Szrj 	      gcc_assert (terminated_this_insn->regno
109738fd1498Szrj 			  == REGNO (recog_data.operand[1]));
109838fd1498Szrj 
109938fd1498Szrj 	      c->tied_chain = terminated_this_insn;
110038fd1498Szrj 	      terminated_this_insn->tied_chain = c;
110138fd1498Szrj 
110238fd1498Szrj 	      if (dump_file)
110338fd1498Szrj 		fprintf (dump_file, "Tying chain %s (%d) with %s (%d)\n",
110438fd1498Szrj 			 reg_names[c->regno], c->id,
110538fd1498Szrj 			 reg_names[terminated_this_insn->regno],
110638fd1498Szrj 			 terminated_this_insn->id);
110738fd1498Szrj 	    }
110838fd1498Szrj 	}
110938fd1498Szrj 
111038fd1498Szrj       return;
111138fd1498Szrj     }
111238fd1498Szrj 
111338fd1498Szrj   if ((type == OP_OUT) != (action == terminate_write || action == mark_access))
111438fd1498Szrj     return;
111538fd1498Szrj 
111638fd1498Szrj   for (p = &open_chains; *p;)
111738fd1498Szrj     {
111838fd1498Szrj       struct du_head *head = *p;
111938fd1498Szrj       struct du_head *next = head->next_chain;
112038fd1498Szrj       int exact_match = (head->regno == this_regno
112138fd1498Szrj 			 && head->nregs == this_nregs);
112238fd1498Szrj       int superset = (this_regno <= head->regno
112338fd1498Szrj 		      && this_regno + this_nregs >= head->regno + head->nregs);
112438fd1498Szrj       int subset = (this_regno >= head->regno
112538fd1498Szrj 		      && this_regno + this_nregs <= head->regno + head->nregs);
112638fd1498Szrj 
112738fd1498Szrj       if (!bitmap_bit_p (&open_chains_set, head->id)
112838fd1498Szrj 	  || head->regno + head->nregs <= this_regno
112938fd1498Szrj 	  || this_regno + this_nregs <= head->regno)
113038fd1498Szrj 	{
113138fd1498Szrj 	  p = &head->next_chain;
113238fd1498Szrj 	  continue;
113338fd1498Szrj 	}
113438fd1498Szrj 
113538fd1498Szrj       if (action == mark_read || action == mark_access)
113638fd1498Szrj 	{
113738fd1498Szrj 	  /* ??? Class NO_REGS can happen if the md file makes use of
113838fd1498Szrj 	     EXTRA_CONSTRAINTS to match registers.  Which is arguably
113938fd1498Szrj 	     wrong, but there we are.  */
114038fd1498Szrj 
114138fd1498Szrj 	  if (cl == NO_REGS || (!exact_match && !DEBUG_INSN_P (insn)))
114238fd1498Szrj 	    {
114338fd1498Szrj 	      if (dump_file)
114438fd1498Szrj 		fprintf (dump_file,
114538fd1498Szrj 			 "Cannot rename chain %s (%d) at insn %d (%s)\n",
114638fd1498Szrj 			 reg_names[head->regno], head->id, INSN_UID (insn),
114738fd1498Szrj 			 scan_actions_name[(int) action]);
114838fd1498Szrj 	      head->cannot_rename = 1;
114938fd1498Szrj 	      if (superset)
115038fd1498Szrj 		{
115138fd1498Szrj 		  unsigned nregs = this_nregs;
115238fd1498Szrj 		  head->regno = this_regno;
115338fd1498Szrj 		  head->nregs = this_nregs;
115438fd1498Szrj 		  while (nregs-- > 0)
115538fd1498Szrj 		    SET_HARD_REG_BIT (live_in_chains, head->regno + nregs);
115638fd1498Szrj 		  if (dump_file)
115738fd1498Szrj 		    fprintf (dump_file,
115838fd1498Szrj 			     "Widening register in chain %s (%d) at insn %d\n",
115938fd1498Szrj 			     reg_names[head->regno], head->id, INSN_UID (insn));
116038fd1498Szrj 		}
116138fd1498Szrj 	      else if (!subset)
116238fd1498Szrj 		{
116338fd1498Szrj 		  fail_current_block = true;
116438fd1498Szrj 		  if (dump_file)
116538fd1498Szrj 		    fprintf (dump_file,
116638fd1498Szrj 			     "Failing basic block due to unhandled overlap\n");
116738fd1498Szrj 		}
116838fd1498Szrj 	    }
116938fd1498Szrj 	  else
117038fd1498Szrj 	    {
117138fd1498Szrj 	      struct du_chain *this_du;
117238fd1498Szrj 	      this_du = XOBNEW (&rename_obstack, struct du_chain);
117338fd1498Szrj 	      this_du->next_use = 0;
117438fd1498Szrj 	      this_du->loc = loc;
117538fd1498Szrj 	      this_du->insn = insn;
117638fd1498Szrj 	      this_du->cl = cl;
117738fd1498Szrj 	      if (head->first == NULL)
117838fd1498Szrj 		head->first = this_du;
117938fd1498Szrj 	      else
118038fd1498Szrj 		head->last->next_use = this_du;
118138fd1498Szrj 	      record_operand_use (head, this_du);
118238fd1498Szrj 	      head->last = this_du;
118338fd1498Szrj 	    }
118438fd1498Szrj 	  /* Avoid adding the same location in a DEBUG_INSN multiple times,
118538fd1498Szrj 	     which could happen with non-exact overlap.  */
118638fd1498Szrj 	  if (DEBUG_INSN_P (insn))
118738fd1498Szrj 	    return;
118838fd1498Szrj 	  /* Otherwise, find any other chains that do not match exactly;
118938fd1498Szrj 	     ensure they all get marked unrenamable.  */
119038fd1498Szrj 	  p = &head->next_chain;
119138fd1498Szrj 	  continue;
119238fd1498Szrj 	}
119338fd1498Szrj 
119438fd1498Szrj       /* Whether the terminated chain can be used for renaming
119538fd1498Szrj 	 depends on the action and this being an exact match.
119638fd1498Szrj 	 In either case, we remove this element from open_chains.  */
119738fd1498Szrj 
119838fd1498Szrj       if ((action == terminate_dead || action == terminate_write)
119938fd1498Szrj 	  && (superset || subset))
120038fd1498Szrj 	{
120138fd1498Szrj 	  unsigned nregs;
120238fd1498Szrj 
120338fd1498Szrj 	  if (subset && !superset)
120438fd1498Szrj 	    head->cannot_rename = 1;
120538fd1498Szrj 	  bitmap_clear_bit (&open_chains_set, head->id);
120638fd1498Szrj 
120738fd1498Szrj 	  nregs = head->nregs;
120838fd1498Szrj 	  while (nregs-- > 0)
120938fd1498Szrj 	    {
121038fd1498Szrj 	      CLEAR_HARD_REG_BIT (live_in_chains, head->regno + nregs);
121138fd1498Szrj 	      if (subset && !superset
121238fd1498Szrj 		  && (head->regno + nregs < this_regno
121338fd1498Szrj 		      || head->regno + nregs >= this_regno + this_nregs))
121438fd1498Szrj 		SET_HARD_REG_BIT (live_hard_regs, head->regno + nregs);
121538fd1498Szrj 	    }
121638fd1498Szrj 
121738fd1498Szrj 	  if (action == terminate_dead)
121838fd1498Szrj 	    terminated_this_insn = *p;
121938fd1498Szrj 	  *p = next;
122038fd1498Szrj 	  if (dump_file)
122138fd1498Szrj 	    fprintf (dump_file,
122238fd1498Szrj 		     "Closing chain %s (%d) at insn %d (%s%s)\n",
122338fd1498Szrj 		     reg_names[head->regno], head->id, INSN_UID (insn),
122438fd1498Szrj 		     scan_actions_name[(int) action],
122538fd1498Szrj 		     superset ? ", superset" : subset ? ", subset" : "");
122638fd1498Szrj 	}
122738fd1498Szrj       else if (action == terminate_dead || action == terminate_write)
122838fd1498Szrj 	{
122938fd1498Szrj 	  /* In this case, tracking liveness gets too hard.  Fail the
123038fd1498Szrj 	     entire basic block.  */
123138fd1498Szrj 	  if (dump_file)
123238fd1498Szrj 	    fprintf (dump_file,
123338fd1498Szrj 		     "Failing basic block due to unhandled overlap\n");
123438fd1498Szrj 	  fail_current_block = true;
123538fd1498Szrj 	  return;
123638fd1498Szrj 	}
123738fd1498Szrj       else
123838fd1498Szrj 	{
123938fd1498Szrj 	  head->cannot_rename = 1;
124038fd1498Szrj 	  if (dump_file)
124138fd1498Szrj 	    fprintf (dump_file,
124238fd1498Szrj 		     "Cannot rename chain %s (%d) at insn %d (%s)\n",
124338fd1498Szrj 		     reg_names[head->regno], head->id, INSN_UID (insn),
124438fd1498Szrj 		     scan_actions_name[(int) action]);
124538fd1498Szrj 	  p = &head->next_chain;
124638fd1498Szrj 	}
124738fd1498Szrj     }
124838fd1498Szrj }
124938fd1498Szrj 
125038fd1498Szrj /* A wrapper around base_reg_class which returns ALL_REGS if INSN is a
125138fd1498Szrj    DEBUG_INSN.  The arguments MODE, AS, CODE and INDEX_CODE are as for
125238fd1498Szrj    base_reg_class.  */
125338fd1498Szrj 
125438fd1498Szrj static reg_class
base_reg_class_for_rename(rtx_insn * insn,machine_mode mode,addr_space_t as,rtx_code code,rtx_code index_code)125538fd1498Szrj base_reg_class_for_rename (rtx_insn *insn, machine_mode mode, addr_space_t as,
125638fd1498Szrj 			   rtx_code code, rtx_code index_code)
125738fd1498Szrj {
125838fd1498Szrj   if (DEBUG_INSN_P (insn))
125938fd1498Szrj     return ALL_REGS;
126038fd1498Szrj   return base_reg_class (mode, as, code, index_code);
126138fd1498Szrj }
126238fd1498Szrj 
126338fd1498Szrj /* Adapted from find_reloads_address_1.  CL is INDEX_REG_CLASS or
126438fd1498Szrj    BASE_REG_CLASS depending on how the register is being considered.  */
126538fd1498Szrj 
126638fd1498Szrj static void
scan_rtx_address(rtx_insn * insn,rtx * loc,enum reg_class cl,enum scan_actions action,machine_mode mode,addr_space_t as)126738fd1498Szrj scan_rtx_address (rtx_insn *insn, rtx *loc, enum reg_class cl,
126838fd1498Szrj 		  enum scan_actions action, machine_mode mode,
126938fd1498Szrj 		  addr_space_t as)
127038fd1498Szrj {
127138fd1498Szrj   rtx x = *loc;
127238fd1498Szrj   RTX_CODE code = GET_CODE (x);
127338fd1498Szrj   const char *fmt;
127438fd1498Szrj   int i, j;
127538fd1498Szrj 
127638fd1498Szrj   if (action == mark_write || action == mark_access)
127738fd1498Szrj     return;
127838fd1498Szrj 
127938fd1498Szrj   switch (code)
128038fd1498Szrj     {
128138fd1498Szrj     case PLUS:
128238fd1498Szrj       {
128338fd1498Szrj 	rtx orig_op0 = XEXP (x, 0);
128438fd1498Szrj 	rtx orig_op1 = XEXP (x, 1);
128538fd1498Szrj 	RTX_CODE code0 = GET_CODE (orig_op0);
128638fd1498Szrj 	RTX_CODE code1 = GET_CODE (orig_op1);
128738fd1498Szrj 	rtx op0 = orig_op0;
128838fd1498Szrj 	rtx op1 = orig_op1;
128938fd1498Szrj 	rtx *locI = NULL;
129038fd1498Szrj 	rtx *locB = NULL;
129138fd1498Szrj 	enum rtx_code index_code = SCRATCH;
129238fd1498Szrj 
129338fd1498Szrj 	if (GET_CODE (op0) == SUBREG)
129438fd1498Szrj 	  {
129538fd1498Szrj 	    op0 = SUBREG_REG (op0);
129638fd1498Szrj 	    code0 = GET_CODE (op0);
129738fd1498Szrj 	  }
129838fd1498Szrj 
129938fd1498Szrj 	if (GET_CODE (op1) == SUBREG)
130038fd1498Szrj 	  {
130138fd1498Szrj 	    op1 = SUBREG_REG (op1);
130238fd1498Szrj 	    code1 = GET_CODE (op1);
130338fd1498Szrj 	  }
130438fd1498Szrj 
130538fd1498Szrj 	if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
130638fd1498Szrj 	    || code0 == ZERO_EXTEND || code1 == MEM)
130738fd1498Szrj 	  {
130838fd1498Szrj 	    locI = &XEXP (x, 0);
130938fd1498Szrj 	    locB = &XEXP (x, 1);
131038fd1498Szrj 	    index_code = GET_CODE (*locI);
131138fd1498Szrj 	  }
131238fd1498Szrj 	else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
131338fd1498Szrj 		 || code1 == ZERO_EXTEND || code0 == MEM)
131438fd1498Szrj 	  {
131538fd1498Szrj 	    locI = &XEXP (x, 1);
131638fd1498Szrj 	    locB = &XEXP (x, 0);
131738fd1498Szrj 	    index_code = GET_CODE (*locI);
131838fd1498Szrj 	  }
131938fd1498Szrj 	else if (code0 == CONST_INT || code0 == CONST
132038fd1498Szrj 		 || code0 == SYMBOL_REF || code0 == LABEL_REF)
132138fd1498Szrj 	  {
132238fd1498Szrj 	    locB = &XEXP (x, 1);
132338fd1498Szrj 	    index_code = GET_CODE (XEXP (x, 0));
132438fd1498Szrj 	  }
132538fd1498Szrj 	else if (code1 == CONST_INT || code1 == CONST
132638fd1498Szrj 		 || code1 == SYMBOL_REF || code1 == LABEL_REF)
132738fd1498Szrj 	  {
132838fd1498Szrj 	    locB = &XEXP (x, 0);
132938fd1498Szrj 	    index_code = GET_CODE (XEXP (x, 1));
133038fd1498Szrj 	  }
133138fd1498Szrj 	else if (code0 == REG && code1 == REG)
133238fd1498Szrj 	  {
133338fd1498Szrj 	    int index_op;
133438fd1498Szrj 	    unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
133538fd1498Szrj 
133638fd1498Szrj 	    if (REGNO_OK_FOR_INDEX_P (regno1)
133738fd1498Szrj 		&& regno_ok_for_base_p (regno0, mode, as, PLUS, REG))
133838fd1498Szrj 	      index_op = 1;
133938fd1498Szrj 	    else if (REGNO_OK_FOR_INDEX_P (regno0)
134038fd1498Szrj 		     && regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
134138fd1498Szrj 	      index_op = 0;
134238fd1498Szrj 	    else if (regno_ok_for_base_p (regno0, mode, as, PLUS, REG)
134338fd1498Szrj 		     || REGNO_OK_FOR_INDEX_P (regno1))
134438fd1498Szrj 	      index_op = 1;
134538fd1498Szrj 	    else if (regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
134638fd1498Szrj 	      index_op = 0;
134738fd1498Szrj 	    else
134838fd1498Szrj 	      index_op = 1;
134938fd1498Szrj 
135038fd1498Szrj 	    locI = &XEXP (x, index_op);
135138fd1498Szrj 	    locB = &XEXP (x, !index_op);
135238fd1498Szrj 	    index_code = GET_CODE (*locI);
135338fd1498Szrj 	  }
135438fd1498Szrj 	else if (code0 == REG)
135538fd1498Szrj 	  {
135638fd1498Szrj 	    locI = &XEXP (x, 0);
135738fd1498Szrj 	    locB = &XEXP (x, 1);
135838fd1498Szrj 	    index_code = GET_CODE (*locI);
135938fd1498Szrj 	  }
136038fd1498Szrj 	else if (code1 == REG)
136138fd1498Szrj 	  {
136238fd1498Szrj 	    locI = &XEXP (x, 1);
136338fd1498Szrj 	    locB = &XEXP (x, 0);
136438fd1498Szrj 	    index_code = GET_CODE (*locI);
136538fd1498Szrj 	  }
136638fd1498Szrj 
136738fd1498Szrj 	if (locI)
136838fd1498Szrj 	  {
136938fd1498Szrj 	    reg_class iclass = DEBUG_INSN_P (insn) ? ALL_REGS : INDEX_REG_CLASS;
137038fd1498Szrj 	    scan_rtx_address (insn, locI, iclass, action, mode, as);
137138fd1498Szrj 	  }
137238fd1498Szrj 	if (locB)
137338fd1498Szrj 	  {
137438fd1498Szrj 	    reg_class bclass = base_reg_class_for_rename (insn, mode, as, PLUS,
137538fd1498Szrj 							  index_code);
137638fd1498Szrj 	    scan_rtx_address (insn, locB, bclass, action, mode, as);
137738fd1498Szrj 	  }
137838fd1498Szrj 	return;
137938fd1498Szrj       }
138038fd1498Szrj 
138138fd1498Szrj     case POST_INC:
138238fd1498Szrj     case POST_DEC:
138338fd1498Szrj     case POST_MODIFY:
138438fd1498Szrj     case PRE_INC:
138538fd1498Szrj     case PRE_DEC:
138638fd1498Szrj     case PRE_MODIFY:
138738fd1498Szrj       /* If the target doesn't claim to handle autoinc, this must be
138838fd1498Szrj 	 something special, like a stack push.  Kill this chain.  */
138938fd1498Szrj       if (!AUTO_INC_DEC)
139038fd1498Szrj 	action = mark_all_read;
139138fd1498Szrj 
139238fd1498Szrj       break;
139338fd1498Szrj 
139438fd1498Szrj     case MEM:
139538fd1498Szrj       {
139638fd1498Szrj 	reg_class bclass = base_reg_class_for_rename (insn, GET_MODE (x),
139738fd1498Szrj 						      MEM_ADDR_SPACE (x),
139838fd1498Szrj 						      MEM, SCRATCH);
139938fd1498Szrj 	scan_rtx_address (insn, &XEXP (x, 0), bclass, action, GET_MODE (x),
140038fd1498Szrj 			  MEM_ADDR_SPACE (x));
140138fd1498Szrj       }
140238fd1498Szrj       return;
140338fd1498Szrj 
140438fd1498Szrj     case REG:
140538fd1498Szrj       scan_rtx_reg (insn, loc, cl, action, OP_IN);
140638fd1498Szrj       return;
140738fd1498Szrj 
140838fd1498Szrj     default:
140938fd1498Szrj       break;
141038fd1498Szrj     }
141138fd1498Szrj 
141238fd1498Szrj   fmt = GET_RTX_FORMAT (code);
141338fd1498Szrj   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
141438fd1498Szrj     {
141538fd1498Szrj       if (fmt[i] == 'e')
141638fd1498Szrj 	scan_rtx_address (insn, &XEXP (x, i), cl, action, mode, as);
141738fd1498Szrj       else if (fmt[i] == 'E')
141838fd1498Szrj 	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
141938fd1498Szrj 	  scan_rtx_address (insn, &XVECEXP (x, i, j), cl, action, mode, as);
142038fd1498Szrj     }
142138fd1498Szrj }
142238fd1498Szrj 
142338fd1498Szrj static void
scan_rtx(rtx_insn * insn,rtx * loc,enum reg_class cl,enum scan_actions action,enum op_type type)142438fd1498Szrj scan_rtx (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions action,
142538fd1498Szrj 	  enum op_type type)
142638fd1498Szrj {
142738fd1498Szrj   const char *fmt;
142838fd1498Szrj   rtx x = *loc;
142938fd1498Szrj   enum rtx_code code = GET_CODE (x);
143038fd1498Szrj   int i, j;
143138fd1498Szrj 
143238fd1498Szrj   code = GET_CODE (x);
143338fd1498Szrj   switch (code)
143438fd1498Szrj     {
143538fd1498Szrj     case CONST:
143638fd1498Szrj     CASE_CONST_ANY:
143738fd1498Szrj     case SYMBOL_REF:
143838fd1498Szrj     case LABEL_REF:
143938fd1498Szrj     case CC0:
144038fd1498Szrj     case PC:
144138fd1498Szrj       return;
144238fd1498Szrj 
144338fd1498Szrj     case REG:
144438fd1498Szrj       scan_rtx_reg (insn, loc, cl, action, type);
144538fd1498Szrj       return;
144638fd1498Szrj 
144738fd1498Szrj     case MEM:
144838fd1498Szrj       {
144938fd1498Szrj 	reg_class bclass = base_reg_class_for_rename (insn, GET_MODE (x),
145038fd1498Szrj 						      MEM_ADDR_SPACE (x),
145138fd1498Szrj 						      MEM, SCRATCH);
145238fd1498Szrj 
145338fd1498Szrj 	scan_rtx_address (insn, &XEXP (x, 0), bclass, action, GET_MODE (x),
145438fd1498Szrj 			  MEM_ADDR_SPACE (x));
145538fd1498Szrj       }
145638fd1498Szrj       return;
145738fd1498Szrj 
145838fd1498Szrj     case SET:
145938fd1498Szrj       scan_rtx (insn, &SET_SRC (x), cl, action, OP_IN);
146038fd1498Szrj       scan_rtx (insn, &SET_DEST (x), cl, action,
146138fd1498Szrj 		(GET_CODE (PATTERN (insn)) == COND_EXEC
146238fd1498Szrj 		 && verify_reg_tracked (SET_DEST (x))) ? OP_INOUT : OP_OUT);
146338fd1498Szrj       return;
146438fd1498Szrj 
146538fd1498Szrj     case STRICT_LOW_PART:
146638fd1498Szrj       scan_rtx (insn, &XEXP (x, 0), cl, action,
146738fd1498Szrj 		verify_reg_tracked (XEXP (x, 0)) ? OP_INOUT : OP_OUT);
146838fd1498Szrj       return;
146938fd1498Szrj 
147038fd1498Szrj     case ZERO_EXTRACT:
147138fd1498Szrj     case SIGN_EXTRACT:
147238fd1498Szrj       scan_rtx (insn, &XEXP (x, 0), cl, action,
147338fd1498Szrj 		(type == OP_IN ? OP_IN :
147438fd1498Szrj 		 verify_reg_tracked (XEXP (x, 0)) ? OP_INOUT : OP_OUT));
147538fd1498Szrj       scan_rtx (insn, &XEXP (x, 1), cl, action, OP_IN);
147638fd1498Szrj       scan_rtx (insn, &XEXP (x, 2), cl, action, OP_IN);
147738fd1498Szrj       return;
147838fd1498Szrj 
147938fd1498Szrj     case POST_INC:
148038fd1498Szrj     case PRE_INC:
148138fd1498Szrj     case POST_DEC:
148238fd1498Szrj     case PRE_DEC:
148338fd1498Szrj     case POST_MODIFY:
148438fd1498Szrj     case PRE_MODIFY:
148538fd1498Szrj       /* Should only happen inside MEM.  */
148638fd1498Szrj       gcc_unreachable ();
148738fd1498Szrj 
148838fd1498Szrj     case CLOBBER:
148938fd1498Szrj       scan_rtx (insn, &SET_DEST (x), cl, action,
149038fd1498Szrj 		(GET_CODE (PATTERN (insn)) == COND_EXEC
149138fd1498Szrj 		 && verify_reg_tracked (SET_DEST (x))) ? OP_INOUT : OP_OUT);
149238fd1498Szrj       return;
149338fd1498Szrj 
149438fd1498Szrj     case EXPR_LIST:
149538fd1498Szrj       scan_rtx (insn, &XEXP (x, 0), cl, action, type);
149638fd1498Szrj       if (XEXP (x, 1))
149738fd1498Szrj 	scan_rtx (insn, &XEXP (x, 1), cl, action, type);
149838fd1498Szrj       return;
149938fd1498Szrj 
150038fd1498Szrj     default:
150138fd1498Szrj       break;
150238fd1498Szrj     }
150338fd1498Szrj 
150438fd1498Szrj   fmt = GET_RTX_FORMAT (code);
150538fd1498Szrj   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
150638fd1498Szrj     {
150738fd1498Szrj       if (fmt[i] == 'e')
150838fd1498Szrj 	scan_rtx (insn, &XEXP (x, i), cl, action, type);
150938fd1498Szrj       else if (fmt[i] == 'E')
151038fd1498Szrj 	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
151138fd1498Szrj 	  scan_rtx (insn, &XVECEXP (x, i, j), cl, action, type);
151238fd1498Szrj     }
151338fd1498Szrj }
151438fd1498Szrj 
151538fd1498Szrj /* Hide operands of the current insn (of which there are N_OPS) by
151638fd1498Szrj    substituting cc0 for them.
151738fd1498Szrj    Previous values are stored in the OLD_OPERANDS and OLD_DUPS.
151838fd1498Szrj    For every bit set in DO_NOT_HIDE, we leave the operand alone.
151938fd1498Szrj    If INOUT_AND_EC_ONLY is set, we only do this for OP_INOUT type operands
152038fd1498Szrj    and earlyclobbers.  */
152138fd1498Szrj 
152238fd1498Szrj static void
hide_operands(int n_ops,rtx * old_operands,rtx * old_dups,unsigned HOST_WIDE_INT do_not_hide,bool inout_and_ec_only)152338fd1498Szrj hide_operands (int n_ops, rtx *old_operands, rtx *old_dups,
152438fd1498Szrj 	       unsigned HOST_WIDE_INT do_not_hide, bool inout_and_ec_only)
152538fd1498Szrj {
152638fd1498Szrj   int i;
152738fd1498Szrj   const operand_alternative *op_alt = which_op_alt ();
152838fd1498Szrj   for (i = 0; i < n_ops; i++)
152938fd1498Szrj     {
153038fd1498Szrj       old_operands[i] = recog_data.operand[i];
153138fd1498Szrj       /* Don't squash match_operator or match_parallel here, since
153238fd1498Szrj 	 we don't know that all of the contained registers are
153338fd1498Szrj 	 reachable by proper operands.  */
153438fd1498Szrj       if (recog_data.constraints[i][0] == '\0')
153538fd1498Szrj 	continue;
153638fd1498Szrj       if (do_not_hide & (1 << i))
153738fd1498Szrj 	continue;
153838fd1498Szrj       if (!inout_and_ec_only || recog_data.operand_type[i] == OP_INOUT
153938fd1498Szrj 	  || op_alt[i].earlyclobber)
154038fd1498Szrj 	*recog_data.operand_loc[i] = cc0_rtx;
154138fd1498Szrj     }
154238fd1498Szrj   for (i = 0; i < recog_data.n_dups; i++)
154338fd1498Szrj     {
154438fd1498Szrj       int opn = recog_data.dup_num[i];
154538fd1498Szrj       old_dups[i] = *recog_data.dup_loc[i];
154638fd1498Szrj       if (do_not_hide & (1 << opn))
154738fd1498Szrj 	continue;
154838fd1498Szrj       if (!inout_and_ec_only || recog_data.operand_type[opn] == OP_INOUT
154938fd1498Szrj 	  || op_alt[opn].earlyclobber)
155038fd1498Szrj 	*recog_data.dup_loc[i] = cc0_rtx;
155138fd1498Szrj     }
155238fd1498Szrj }
155338fd1498Szrj 
155438fd1498Szrj /* Undo the substitution performed by hide_operands.  INSN is the insn we
155538fd1498Szrj    are processing; the arguments are the same as in hide_operands.  */
155638fd1498Szrj 
155738fd1498Szrj static void
restore_operands(rtx_insn * insn,int n_ops,rtx * old_operands,rtx * old_dups)155838fd1498Szrj restore_operands (rtx_insn *insn, int n_ops, rtx *old_operands, rtx *old_dups)
155938fd1498Szrj {
156038fd1498Szrj   int i;
156138fd1498Szrj   for (i = 0; i < recog_data.n_dups; i++)
156238fd1498Szrj     *recog_data.dup_loc[i] = old_dups[i];
156338fd1498Szrj   for (i = 0; i < n_ops; i++)
156438fd1498Szrj     *recog_data.operand_loc[i] = old_operands[i];
156538fd1498Szrj   if (recog_data.n_dups)
156638fd1498Szrj     df_insn_rescan (insn);
156738fd1498Szrj }
156838fd1498Szrj 
156938fd1498Szrj /* For each output operand of INSN, call scan_rtx to create a new
157038fd1498Szrj    open chain.  Do this only for normal or earlyclobber outputs,
157138fd1498Szrj    depending on EARLYCLOBBER.  If INSN_INFO is nonnull, use it to
157238fd1498Szrj    record information about the operands in the insn.  */
157338fd1498Szrj 
157438fd1498Szrj static void
record_out_operands(rtx_insn * insn,bool earlyclobber,insn_rr_info * insn_info)157538fd1498Szrj record_out_operands (rtx_insn *insn, bool earlyclobber, insn_rr_info *insn_info)
157638fd1498Szrj {
157738fd1498Szrj   int n_ops = recog_data.n_operands;
157838fd1498Szrj   const operand_alternative *op_alt = which_op_alt ();
157938fd1498Szrj 
158038fd1498Szrj   int i;
158138fd1498Szrj 
158238fd1498Szrj   for (i = 0; i < n_ops + recog_data.n_dups; i++)
158338fd1498Szrj     {
158438fd1498Szrj       int opn = i < n_ops ? i : recog_data.dup_num[i - n_ops];
158538fd1498Szrj       rtx *loc = (i < n_ops
158638fd1498Szrj 		  ? recog_data.operand_loc[opn]
158738fd1498Szrj 		  : recog_data.dup_loc[i - n_ops]);
158838fd1498Szrj       rtx op = *loc;
158938fd1498Szrj       enum reg_class cl = alternative_class (op_alt, opn);
159038fd1498Szrj 
159138fd1498Szrj       struct du_head *prev_open;
159238fd1498Szrj 
159338fd1498Szrj       if (recog_data.operand_type[opn] != OP_OUT
159438fd1498Szrj 	  || op_alt[opn].earlyclobber != earlyclobber)
159538fd1498Szrj 	continue;
159638fd1498Szrj 
159738fd1498Szrj       if (insn_info)
159838fd1498Szrj 	cur_operand = insn_info->op_info + i;
159938fd1498Szrj 
160038fd1498Szrj       prev_open = open_chains;
160138fd1498Szrj       if (earlyclobber)
160238fd1498Szrj 	scan_rtx (insn, loc, cl, terminate_write, OP_OUT);
160338fd1498Szrj       scan_rtx (insn, loc, cl, mark_write, OP_OUT);
160438fd1498Szrj 
160538fd1498Szrj       /* ??? Many targets have output constraints on the SET_DEST
160638fd1498Szrj 	 of a call insn, which is stupid, since these are certainly
160738fd1498Szrj 	 ABI defined hard registers.  For these, and for asm operands
160838fd1498Szrj 	 that originally referenced hard registers, we must record that
160938fd1498Szrj 	 the chain cannot be renamed.  */
161038fd1498Szrj       if (CALL_P (insn)
161138fd1498Szrj 	  || (asm_noperands (PATTERN (insn)) > 0
161238fd1498Szrj 	      && REG_P (op)
161338fd1498Szrj 	      && REGNO (op) == ORIGINAL_REGNO (op)))
161438fd1498Szrj 	{
161538fd1498Szrj 	  if (prev_open != open_chains)
161638fd1498Szrj 	    open_chains->cannot_rename = 1;
161738fd1498Szrj 	}
161838fd1498Szrj     }
161938fd1498Szrj   cur_operand = NULL;
162038fd1498Szrj }
162138fd1498Szrj 
162238fd1498Szrj /* Build def/use chain.  */
162338fd1498Szrj 
162438fd1498Szrj static bool
build_def_use(basic_block bb)162538fd1498Szrj build_def_use (basic_block bb)
162638fd1498Szrj {
162738fd1498Szrj   rtx_insn *insn;
162838fd1498Szrj   unsigned HOST_WIDE_INT untracked_operands;
162938fd1498Szrj 
163038fd1498Szrj   fail_current_block = false;
163138fd1498Szrj 
163238fd1498Szrj   for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
163338fd1498Szrj     {
163438fd1498Szrj       if (NONDEBUG_INSN_P (insn))
163538fd1498Szrj 	{
163638fd1498Szrj 	  int n_ops;
163738fd1498Szrj 	  rtx note;
163838fd1498Szrj 	  rtx old_operands[MAX_RECOG_OPERANDS];
163938fd1498Szrj 	  rtx old_dups[MAX_DUP_OPERANDS];
164038fd1498Szrj 	  int i;
164138fd1498Szrj 	  int predicated;
164238fd1498Szrj 	  enum rtx_code set_code = SET;
164338fd1498Szrj 	  enum rtx_code clobber_code = CLOBBER;
164438fd1498Szrj 	  insn_rr_info *insn_info = NULL;
164538fd1498Szrj 	  terminated_this_insn = NULL;
164638fd1498Szrj 
164738fd1498Szrj 	  /* Process the insn, determining its effect on the def-use
164838fd1498Szrj 	     chains and live hard registers.  We perform the following
164938fd1498Szrj 	     steps with the register references in the insn, simulating
165038fd1498Szrj 	     its effect:
165138fd1498Szrj 	     (1) Deal with earlyclobber operands and CLOBBERs of non-operands
165238fd1498Szrj 	         by creating chains and marking hard regs live.
165338fd1498Szrj 	     (2) Any read outside an operand causes any chain it overlaps
165438fd1498Szrj 	         with to be marked unrenamable.
165538fd1498Szrj 	     (3) Any read inside an operand is added if there's already
165638fd1498Szrj 	         an open chain for it.
165738fd1498Szrj 	     (4) For any REG_DEAD note we find, close open chains that
165838fd1498Szrj 	         overlap it.
165938fd1498Szrj 	     (5) For any non-earlyclobber write we find, close open chains
166038fd1498Szrj 	         that overlap it.
166138fd1498Szrj 	     (6) For any non-earlyclobber write we find in an operand, make
166238fd1498Szrj 	         a new chain or mark the hard register as live.
166338fd1498Szrj 	     (7) For any REG_UNUSED, close any chains we just opened.
1664*58e805e6Szrj 	     (8) For any REG_CFA_RESTORE or REG_CFA_REGISTER, kill any chain
1665*58e805e6Szrj 	         containing its dest.
166638fd1498Szrj 
166738fd1498Szrj 	     We cannot deal with situations where we track a reg in one mode
166838fd1498Szrj 	     and see a reference in another mode; these will cause the chain
166938fd1498Szrj 	     to be marked unrenamable or even cause us to abort the entire
167038fd1498Szrj 	     basic block.  */
167138fd1498Szrj 
167238fd1498Szrj 	  extract_constrain_insn (insn);
167338fd1498Szrj 	  preprocess_constraints (insn);
167438fd1498Szrj 	  const operand_alternative *op_alt = which_op_alt ();
167538fd1498Szrj 	  n_ops = recog_data.n_operands;
167638fd1498Szrj 	  untracked_operands = 0;
167738fd1498Szrj 
167838fd1498Szrj 	  if (insn_rr.exists ())
167938fd1498Szrj 	    {
168038fd1498Szrj 	      insn_info = &insn_rr[INSN_UID (insn)];
168138fd1498Szrj 	      insn_info->op_info = XOBNEWVEC (&rename_obstack, operand_rr_info,
168238fd1498Szrj 					      recog_data.n_operands);
168338fd1498Szrj 	      memset (insn_info->op_info, 0,
168438fd1498Szrj 		      sizeof (operand_rr_info) * recog_data.n_operands);
168538fd1498Szrj 	    }
168638fd1498Szrj 
168738fd1498Szrj 	  /* Simplify the code below by promoting OP_OUT to OP_INOUT in
168838fd1498Szrj 	     predicated instructions, but only for register operands
168938fd1498Szrj 	     that are already tracked, so that we can create a chain
169038fd1498Szrj 	     when the first SET makes a register live.  */
169138fd1498Szrj 
169238fd1498Szrj 	  predicated = GET_CODE (PATTERN (insn)) == COND_EXEC;
169338fd1498Szrj 	  for (i = 0; i < n_ops; ++i)
169438fd1498Szrj 	    {
169538fd1498Szrj 	      rtx op = recog_data.operand[i];
169638fd1498Szrj 	      int matches = op_alt[i].matches;
169738fd1498Szrj 	      if (matches >= 0 || op_alt[i].matched >= 0
169838fd1498Szrj 	          || (predicated && recog_data.operand_type[i] == OP_OUT))
169938fd1498Szrj 		{
170038fd1498Szrj 		  recog_data.operand_type[i] = OP_INOUT;
170138fd1498Szrj 		  /* A special case to deal with instruction patterns that
170238fd1498Szrj 		     have matching operands with different modes.  If we're
170338fd1498Szrj 		     not already tracking such a reg, we won't start here,
170438fd1498Szrj 		     and we must instead make sure to make the operand visible
170538fd1498Szrj 		     to the machinery that tracks hard registers.  */
170638fd1498Szrj 		  machine_mode i_mode = recog_data.operand_mode[i];
170738fd1498Szrj 		  if (matches >= 0)
170838fd1498Szrj 		    {
170938fd1498Szrj 		      machine_mode matches_mode
171038fd1498Szrj 			= recog_data.operand_mode[matches];
171138fd1498Szrj 
171238fd1498Szrj 		      if (maybe_ne (GET_MODE_SIZE (i_mode),
171338fd1498Szrj 				    GET_MODE_SIZE (matches_mode))
171438fd1498Szrj 			  && !verify_reg_in_set (op, &live_in_chains))
171538fd1498Szrj 			{
171638fd1498Szrj 			  untracked_operands |= 1 << i;
171738fd1498Szrj 			  untracked_operands |= 1 << matches;
171838fd1498Szrj 			}
171938fd1498Szrj 		    }
172038fd1498Szrj 		}
172138fd1498Szrj #ifdef STACK_REGS
172238fd1498Szrj 	      if (regstack_completed
172338fd1498Szrj 		  && REG_P (op)
172438fd1498Szrj 		  && IN_RANGE (REGNO (op), FIRST_STACK_REG, LAST_STACK_REG))
172538fd1498Szrj 		untracked_operands |= 1 << i;
172638fd1498Szrj #endif
172738fd1498Szrj 	      /* If there's an in-out operand with a register that is not
172838fd1498Szrj 		 being tracked at all yet, open a chain.  */
172938fd1498Szrj 	      if (recog_data.operand_type[i] == OP_INOUT
173038fd1498Szrj 		  && !(untracked_operands & (1 << i))
173138fd1498Szrj 		  && REG_P (op)
173238fd1498Szrj 		  && !verify_reg_tracked (op))
173338fd1498Szrj 		create_new_chain (REGNO (op), REG_NREGS (op), NULL, NULL,
173438fd1498Szrj 				  NO_REGS);
173538fd1498Szrj 	    }
173638fd1498Szrj 
173738fd1498Szrj 	  if (fail_current_block)
173838fd1498Szrj 	    break;
173938fd1498Szrj 
174038fd1498Szrj 	  /* Step 1a: Mark hard registers that are clobbered in this insn,
174138fd1498Szrj 	     outside an operand, as live.  */
174238fd1498Szrj 	  hide_operands (n_ops, old_operands, old_dups, untracked_operands,
174338fd1498Szrj 			 false);
174438fd1498Szrj 	  note_stores (PATTERN (insn), note_sets_clobbers, &clobber_code);
174538fd1498Szrj 	  restore_operands (insn, n_ops, old_operands, old_dups);
174638fd1498Szrj 
174738fd1498Szrj 	  /* Step 1b: Begin new chains for earlyclobbered writes inside
174838fd1498Szrj 	     operands.  */
174938fd1498Szrj 	  record_out_operands (insn, true, insn_info);
175038fd1498Szrj 
175138fd1498Szrj 	  /* Step 2: Mark chains for which we have reads outside operands
175238fd1498Szrj 	     as unrenamable.
175338fd1498Szrj 	     We do this by munging all operands into CC0, and closing
175438fd1498Szrj 	     everything remaining.  */
175538fd1498Szrj 
175638fd1498Szrj 	  hide_operands (n_ops, old_operands, old_dups, untracked_operands,
175738fd1498Szrj 			 false);
175838fd1498Szrj 	  scan_rtx (insn, &PATTERN (insn), NO_REGS, mark_all_read, OP_IN);
175938fd1498Szrj 	  restore_operands (insn, n_ops, old_operands, old_dups);
176038fd1498Szrj 
176138fd1498Szrj 	  /* Step 2B: Can't rename function call argument registers.  */
176238fd1498Szrj 	  if (CALL_P (insn) && CALL_INSN_FUNCTION_USAGE (insn))
176338fd1498Szrj 	    scan_rtx (insn, &CALL_INSN_FUNCTION_USAGE (insn),
176438fd1498Szrj 		      NO_REGS, mark_all_read, OP_IN);
176538fd1498Szrj 
176638fd1498Szrj 	  /* Step 2C: Can't rename asm operands that were originally
176738fd1498Szrj 	     hard registers.  */
176838fd1498Szrj 	  if (asm_noperands (PATTERN (insn)) > 0)
176938fd1498Szrj 	    for (i = 0; i < n_ops; i++)
177038fd1498Szrj 	      {
177138fd1498Szrj 		rtx *loc = recog_data.operand_loc[i];
177238fd1498Szrj 		rtx op = *loc;
177338fd1498Szrj 
177438fd1498Szrj 		if (REG_P (op)
177538fd1498Szrj 		    && REGNO (op) == ORIGINAL_REGNO (op)
177638fd1498Szrj 		    && (recog_data.operand_type[i] == OP_IN
177738fd1498Szrj 			|| recog_data.operand_type[i] == OP_INOUT))
177838fd1498Szrj 		  scan_rtx (insn, loc, NO_REGS, mark_all_read, OP_IN);
177938fd1498Szrj 	      }
178038fd1498Szrj 
178138fd1498Szrj 	  /* Step 3: Append to chains for reads inside operands.  */
178238fd1498Szrj 	  for (i = 0; i < n_ops + recog_data.n_dups; i++)
178338fd1498Szrj 	    {
178438fd1498Szrj 	      int opn = i < n_ops ? i : recog_data.dup_num[i - n_ops];
178538fd1498Szrj 	      rtx *loc = (i < n_ops
178638fd1498Szrj 			  ? recog_data.operand_loc[opn]
178738fd1498Szrj 			  : recog_data.dup_loc[i - n_ops]);
178838fd1498Szrj 	      enum reg_class cl = alternative_class (op_alt, opn);
178938fd1498Szrj 	      enum op_type type = recog_data.operand_type[opn];
179038fd1498Szrj 
179138fd1498Szrj 	      /* Don't scan match_operand here, since we've no reg class
179238fd1498Szrj 		 information to pass down.  Any operands that we could
179338fd1498Szrj 		 substitute in will be represented elsewhere.  */
179438fd1498Szrj 	      if (recog_data.constraints[opn][0] == '\0'
179538fd1498Szrj 		  || untracked_operands & (1 << opn))
179638fd1498Szrj 		continue;
179738fd1498Szrj 
179838fd1498Szrj 	      if (insn_info)
179938fd1498Szrj 		cur_operand = i == opn ? insn_info->op_info + i : NULL;
180038fd1498Szrj 	      if (op_alt[opn].is_address)
180138fd1498Szrj 		scan_rtx_address (insn, loc, cl, mark_read,
180238fd1498Szrj 				  VOIDmode, ADDR_SPACE_GENERIC);
180338fd1498Szrj 	      else
180438fd1498Szrj 		scan_rtx (insn, loc, cl, mark_read, type);
180538fd1498Szrj 	    }
180638fd1498Szrj 	  cur_operand = NULL;
180738fd1498Szrj 
180838fd1498Szrj 	  /* Step 3B: Record updates for regs in REG_INC notes, and
180938fd1498Szrj 	     source regs in REG_FRAME_RELATED_EXPR notes.  */
181038fd1498Szrj 	  for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
181138fd1498Szrj 	    if (REG_NOTE_KIND (note) == REG_INC
181238fd1498Szrj 		|| REG_NOTE_KIND (note) == REG_FRAME_RELATED_EXPR)
181338fd1498Szrj 	      scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_read,
181438fd1498Szrj 			OP_INOUT);
181538fd1498Szrj 
181638fd1498Szrj 	  /* Step 4: Close chains for registers that die here, unless
181738fd1498Szrj 	     the register is mentioned in a REG_UNUSED note.  In that
181838fd1498Szrj 	     case we keep the chain open until step #7 below to ensure
181938fd1498Szrj 	     it conflicts with other output operands of this insn.
182038fd1498Szrj 	     See PR 52573.  Arguably the insn should not have both
182138fd1498Szrj 	     notes; it has proven difficult to fix that without
182238fd1498Szrj 	     other undesirable side effects.  */
182338fd1498Szrj 	  for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
182438fd1498Szrj 	    if (REG_NOTE_KIND (note) == REG_DEAD
182538fd1498Szrj 		&& !find_regno_note (insn, REG_UNUSED, REGNO (XEXP (note, 0))))
182638fd1498Szrj 	      {
182738fd1498Szrj 		remove_from_hard_reg_set (&live_hard_regs,
182838fd1498Szrj 					  GET_MODE (XEXP (note, 0)),
182938fd1498Szrj 					  REGNO (XEXP (note, 0)));
183038fd1498Szrj 		scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead,
183138fd1498Szrj 			  OP_IN);
183238fd1498Szrj 	      }
183338fd1498Szrj 
183438fd1498Szrj 	  /* Step 4B: If this is a call, any chain live at this point
183538fd1498Szrj 	     requires a caller-saved reg.  */
183638fd1498Szrj 	  if (CALL_P (insn))
183738fd1498Szrj 	    {
183838fd1498Szrj 	      struct du_head *p;
183938fd1498Szrj 	      for (p = open_chains; p; p = p->next_chain)
184038fd1498Szrj 		p->need_caller_save_reg = 1;
184138fd1498Szrj 	    }
184238fd1498Szrj 
184338fd1498Szrj 	  /* Step 5: Close open chains that overlap writes.  Similar to
184438fd1498Szrj 	     step 2, we hide in-out operands, since we do not want to
184538fd1498Szrj 	     close these chains.  We also hide earlyclobber operands,
184638fd1498Szrj 	     since we've opened chains for them in step 1, and earlier
184738fd1498Szrj 	     chains they would overlap with must have been closed at
184838fd1498Szrj 	     the previous insn at the latest, as such operands cannot
184938fd1498Szrj 	     possibly overlap with any input operands.  */
185038fd1498Szrj 
185138fd1498Szrj 	  hide_operands (n_ops, old_operands, old_dups, untracked_operands,
185238fd1498Szrj 			 true);
185338fd1498Szrj 	  scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_write, OP_IN);
185438fd1498Szrj 	  restore_operands (insn, n_ops, old_operands, old_dups);
185538fd1498Szrj 
185638fd1498Szrj 	  /* Step 6a: Mark hard registers that are set in this insn,
185738fd1498Szrj 	     outside an operand, as live.  */
185838fd1498Szrj 	  hide_operands (n_ops, old_operands, old_dups, untracked_operands,
185938fd1498Szrj 			 false);
186038fd1498Szrj 	  note_stores (PATTERN (insn), note_sets_clobbers, &set_code);
186138fd1498Szrj 	  restore_operands (insn, n_ops, old_operands, old_dups);
186238fd1498Szrj 
186338fd1498Szrj 	  /* Step 6b: Begin new chains for writes inside operands.  */
186438fd1498Szrj 	  record_out_operands (insn, false, insn_info);
186538fd1498Szrj 
186638fd1498Szrj 	  /* Step 6c: Record destination regs in REG_FRAME_RELATED_EXPR
186738fd1498Szrj 	     notes for update.  */
186838fd1498Szrj 	  for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
186938fd1498Szrj 	    if (REG_NOTE_KIND (note) == REG_FRAME_RELATED_EXPR)
187038fd1498Szrj 	      scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_access,
187138fd1498Szrj 			OP_INOUT);
187238fd1498Szrj 
187338fd1498Szrj 	  /* Step 7: Close chains for registers that were never
187438fd1498Szrj 	     really used here.  */
187538fd1498Szrj 	  for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
187638fd1498Szrj 	    if (REG_NOTE_KIND (note) == REG_UNUSED)
187738fd1498Szrj 	      {
187838fd1498Szrj 		remove_from_hard_reg_set (&live_hard_regs,
187938fd1498Szrj 					  GET_MODE (XEXP (note, 0)),
188038fd1498Szrj 					  REGNO (XEXP (note, 0)));
188138fd1498Szrj 		scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead,
188238fd1498Szrj 			  OP_IN);
188338fd1498Szrj 	      }
188438fd1498Szrj 
188538fd1498Szrj 	  /* Step 8: Kill the chains involving register restores.  Those
1886*58e805e6Szrj 	     should restore _that_ register.  Similar for REG_CFA_REGISTER.  */
188738fd1498Szrj 	  for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
1888*58e805e6Szrj 	    if (REG_NOTE_KIND (note) == REG_CFA_RESTORE
1889*58e805e6Szrj 		|| REG_NOTE_KIND (note) == REG_CFA_REGISTER)
1890*58e805e6Szrj 	      {
1891*58e805e6Szrj 		rtx *x = &XEXP (note, 0);
1892*58e805e6Szrj 		if (!*x)
1893*58e805e6Szrj 		  x = &PATTERN (insn);
1894*58e805e6Szrj 		if (GET_CODE (*x) == PARALLEL)
1895*58e805e6Szrj 		  x = &XVECEXP (*x, 0, 0);
1896*58e805e6Szrj 		if (GET_CODE (*x) == SET)
1897*58e805e6Szrj 		  x = &SET_DEST (*x);
1898*58e805e6Szrj 		scan_rtx (insn, x, NO_REGS, mark_all_read, OP_IN);
1899*58e805e6Szrj 	      }
190038fd1498Szrj 	}
190138fd1498Szrj       else if (DEBUG_BIND_INSN_P (insn)
190238fd1498Szrj 	       && !VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (insn)))
190338fd1498Szrj 	{
190438fd1498Szrj 	  scan_rtx (insn, &INSN_VAR_LOCATION_LOC (insn),
190538fd1498Szrj 		    ALL_REGS, mark_read, OP_IN);
190638fd1498Szrj 	}
190738fd1498Szrj       if (insn == BB_END (bb))
190838fd1498Szrj 	break;
190938fd1498Szrj     }
191038fd1498Szrj 
191138fd1498Szrj   if (fail_current_block)
191238fd1498Szrj     return false;
191338fd1498Szrj 
191438fd1498Szrj   return true;
191538fd1498Szrj }
191638fd1498Szrj 
191738fd1498Szrj /* Initialize the register renamer.  If INSN_INFO is true, ensure that
191838fd1498Szrj    insn_rr is nonnull.  */
191938fd1498Szrj void
regrename_init(bool insn_info)192038fd1498Szrj regrename_init (bool insn_info)
192138fd1498Szrj {
192238fd1498Szrj   gcc_obstack_init (&rename_obstack);
192338fd1498Szrj   insn_rr.create (0);
192438fd1498Szrj   if (insn_info)
192538fd1498Szrj     insn_rr.safe_grow_cleared (get_max_uid ());
192638fd1498Szrj }
192738fd1498Szrj 
192838fd1498Szrj /* Free all global data used by the register renamer.  */
192938fd1498Szrj void
regrename_finish(void)193038fd1498Szrj regrename_finish (void)
193138fd1498Szrj {
193238fd1498Szrj   insn_rr.release ();
193338fd1498Szrj   free_chain_data ();
193438fd1498Szrj   obstack_free (&rename_obstack, NULL);
193538fd1498Szrj }
193638fd1498Szrj 
193738fd1498Szrj /* Perform register renaming on the current function.  */
193838fd1498Szrj 
193938fd1498Szrj static unsigned int
regrename_optimize(void)194038fd1498Szrj regrename_optimize (void)
194138fd1498Szrj {
194238fd1498Szrj   df_set_flags (DF_LR_RUN_DCE);
194338fd1498Szrj   df_note_add_problem ();
194438fd1498Szrj   df_analyze ();
194538fd1498Szrj   df_set_flags (DF_DEFER_INSN_RESCAN);
194638fd1498Szrj 
194738fd1498Szrj   regrename_init (false);
194838fd1498Szrj 
194938fd1498Szrj   regrename_analyze (NULL);
195038fd1498Szrj 
195138fd1498Szrj   rename_chains ();
195238fd1498Szrj 
195338fd1498Szrj   regrename_finish ();
195438fd1498Szrj 
195538fd1498Szrj   return 0;
195638fd1498Szrj }
195738fd1498Szrj 
195838fd1498Szrj namespace {
195938fd1498Szrj 
196038fd1498Szrj const pass_data pass_data_regrename =
196138fd1498Szrj {
196238fd1498Szrj   RTL_PASS, /* type */
196338fd1498Szrj   "rnreg", /* name */
196438fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
196538fd1498Szrj   TV_RENAME_REGISTERS, /* tv_id */
196638fd1498Szrj   0, /* properties_required */
196738fd1498Szrj   0, /* properties_provided */
196838fd1498Szrj   0, /* properties_destroyed */
196938fd1498Szrj   0, /* todo_flags_start */
197038fd1498Szrj   TODO_df_finish, /* todo_flags_finish */
197138fd1498Szrj };
197238fd1498Szrj 
197338fd1498Szrj class pass_regrename : public rtl_opt_pass
197438fd1498Szrj {
197538fd1498Szrj public:
pass_regrename(gcc::context * ctxt)197638fd1498Szrj   pass_regrename (gcc::context *ctxt)
197738fd1498Szrj     : rtl_opt_pass (pass_data_regrename, ctxt)
197838fd1498Szrj   {}
197938fd1498Szrj 
198038fd1498Szrj   /* opt_pass methods: */
gate(function *)198138fd1498Szrj   virtual bool gate (function *)
198238fd1498Szrj     {
198338fd1498Szrj       return (optimize > 0 && (flag_rename_registers));
198438fd1498Szrj     }
198538fd1498Szrj 
execute(function *)198638fd1498Szrj   virtual unsigned int execute (function *) { return regrename_optimize (); }
198738fd1498Szrj 
198838fd1498Szrj }; // class pass_regrename
198938fd1498Szrj 
199038fd1498Szrj } // anon namespace
199138fd1498Szrj 
199238fd1498Szrj rtl_opt_pass *
make_pass_regrename(gcc::context * ctxt)199338fd1498Szrj make_pass_regrename (gcc::context *ctxt)
199438fd1498Szrj {
199538fd1498Szrj   return new pass_regrename (ctxt);
199638fd1498Szrj }
1997