190075Sobrien/* Register renaming for the GNU compiler.
2169689Skan   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
3169689Skan   Free Software Foundation, Inc.
490075Sobrien
590075Sobrien   This file is part of GCC.
690075Sobrien
790075Sobrien   GCC is free software; you can redistribute it and/or modify it
890075Sobrien   under the terms of the GNU General Public License as published by
990075Sobrien   the Free Software Foundation; either version 2, or (at your option)
1090075Sobrien   any later version.
1190075Sobrien
1290075Sobrien   GCC is distributed in the hope that it will be useful, but WITHOUT
1390075Sobrien   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1490075Sobrien   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
1590075Sobrien   License for more details.
1690075Sobrien
1790075Sobrien   You should have received a copy of the GNU General Public License
1890075Sobrien   along with GCC; see the file COPYING.  If not, write to the Free
19169689Skan   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20169689Skan   02110-1301, USA.  */
2190075Sobrien
2290075Sobrien#include "config.h"
2390075Sobrien#include "system.h"
24132718Skan#include "coretypes.h"
25132718Skan#include "tm.h"
2690075Sobrien#include "rtl.h"
2790075Sobrien#include "tm_p.h"
2890075Sobrien#include "insn-config.h"
2990075Sobrien#include "regs.h"
30169689Skan#include "addresses.h"
3190075Sobrien#include "hard-reg-set.h"
3290075Sobrien#include "basic-block.h"
3390075Sobrien#include "reload.h"
3490075Sobrien#include "output.h"
3590075Sobrien#include "function.h"
3690075Sobrien#include "recog.h"
3790075Sobrien#include "flags.h"
3890075Sobrien#include "toplev.h"
3990075Sobrien#include "obstack.h"
40169689Skan#include "timevar.h"
41169689Skan#include "tree-pass.h"
4290075Sobrien
4390075Sobrienstruct du_chain
4490075Sobrien{
4590075Sobrien  struct du_chain *next_chain;
4690075Sobrien  struct du_chain *next_use;
4790075Sobrien
4890075Sobrien  rtx insn;
4990075Sobrien  rtx *loc;
50169689Skan  ENUM_BITFIELD(reg_class) cl : 16;
5190075Sobrien  unsigned int need_caller_save_reg:1;
5290075Sobrien  unsigned int earlyclobber:1;
5390075Sobrien};
5490075Sobrien
5590075Sobrienenum scan_actions
5690075Sobrien{
5790075Sobrien  terminate_all_read,
5890075Sobrien  terminate_overlapping_read,
5990075Sobrien  terminate_write,
6090075Sobrien  terminate_dead,
6190075Sobrien  mark_read,
62169689Skan  mark_write,
63169689Skan  /* mark_access is for marking the destination regs in
64169689Skan     REG_FRAME_RELATED_EXPR notes (as if they were read) so that the
65169689Skan     note is updated properly.  */
66169689Skan  mark_access
6790075Sobrien};
6890075Sobrien
6990075Sobrienstatic const char * const scan_actions_name[] =
7090075Sobrien{
7190075Sobrien  "terminate_all_read",
7290075Sobrien  "terminate_overlapping_read",
7390075Sobrien  "terminate_write",
7490075Sobrien  "terminate_dead",
7590075Sobrien  "mark_read",
76169689Skan  "mark_write",
77169689Skan  "mark_access"
7890075Sobrien};
7990075Sobrien
8090075Sobrienstatic struct obstack rename_obstack;
8190075Sobrien
82132718Skanstatic void do_replace (struct du_chain *, int);
83132718Skanstatic void scan_rtx_reg (rtx, rtx *, enum reg_class,
84132718Skan			  enum scan_actions, enum op_type, int);
85132718Skanstatic void scan_rtx_address (rtx, rtx *, enum reg_class,
86132718Skan			      enum scan_actions, enum machine_mode);
87132718Skanstatic void scan_rtx (rtx, rtx *, enum reg_class, enum scan_actions,
88132718Skan		      enum op_type, int);
89132718Skanstatic struct du_chain *build_def_use (basic_block);
90132718Skanstatic void dump_def_use_chain (struct du_chain *);
91132718Skanstatic void note_sets (rtx, rtx, void *);
92132718Skanstatic void clear_dead_regs (HARD_REG_SET *, enum machine_mode, rtx);
93132718Skanstatic void merge_overlapping_regs (basic_block, HARD_REG_SET *,
94132718Skan				    struct du_chain *);
9590075Sobrien
9690075Sobrien/* Called through note_stores from update_life.  Find sets of registers, and
9790075Sobrien   record them in *DATA (which is actually a HARD_REG_SET *).  */
9890075Sobrien
9990075Sobrienstatic void
100132718Skannote_sets (rtx x, rtx set ATTRIBUTE_UNUSED, void *data)
10190075Sobrien{
10290075Sobrien  HARD_REG_SET *pset = (HARD_REG_SET *) data;
10390075Sobrien  unsigned int regno;
10490075Sobrien  int nregs;
105146895Skan
106146895Skan  if (GET_CODE (x) == SUBREG)
107146895Skan    x = SUBREG_REG (x);
108169689Skan  if (!REG_P (x))
10990075Sobrien    return;
11090075Sobrien  regno = REGNO (x);
111169689Skan  nregs = hard_regno_nregs[regno][GET_MODE (x)];
11290075Sobrien
11390075Sobrien  /* There must not be pseudos at this point.  */
114169689Skan  gcc_assert (regno + nregs <= FIRST_PSEUDO_REGISTER);
11590075Sobrien
11690075Sobrien  while (nregs-- > 0)
11790075Sobrien    SET_HARD_REG_BIT (*pset, regno + nregs);
11890075Sobrien}
11990075Sobrien
12090075Sobrien/* Clear all registers from *PSET for which a note of kind KIND can be found
12190075Sobrien   in the list NOTES.  */
12290075Sobrien
12390075Sobrienstatic void
124132718Skanclear_dead_regs (HARD_REG_SET *pset, enum machine_mode kind, rtx notes)
12590075Sobrien{
12690075Sobrien  rtx note;
12790075Sobrien  for (note = notes; note; note = XEXP (note, 1))
12890075Sobrien    if (REG_NOTE_KIND (note) == kind && REG_P (XEXP (note, 0)))
12990075Sobrien      {
13090075Sobrien	rtx reg = XEXP (note, 0);
13190075Sobrien	unsigned int regno = REGNO (reg);
132169689Skan	int nregs = hard_regno_nregs[regno][GET_MODE (reg)];
13390075Sobrien
13490075Sobrien	/* There must not be pseudos at this point.  */
135169689Skan	gcc_assert (regno + nregs <= FIRST_PSEUDO_REGISTER);
13690075Sobrien
13790075Sobrien	while (nregs-- > 0)
13890075Sobrien	  CLEAR_HARD_REG_BIT (*pset, regno + nregs);
13990075Sobrien      }
14090075Sobrien}
14190075Sobrien
14290075Sobrien/* For a def-use chain CHAIN in basic block B, find which registers overlap
14390075Sobrien   its lifetime and set the corresponding bits in *PSET.  */
14490075Sobrien
14590075Sobrienstatic void
146132718Skanmerge_overlapping_regs (basic_block b, HARD_REG_SET *pset,
147132718Skan			struct du_chain *chain)
14890075Sobrien{
14990075Sobrien  struct du_chain *t = chain;
15090075Sobrien  rtx insn;
15190075Sobrien  HARD_REG_SET live;
15290075Sobrien
153169689Skan  REG_SET_TO_HARD_REG_SET (live, b->il.rtl->global_live_at_start);
154132718Skan  insn = BB_HEAD (b);
15590075Sobrien  while (t)
15690075Sobrien    {
15790075Sobrien      /* Search forward until the next reference to the register to be
15890075Sobrien	 renamed.  */
15990075Sobrien      while (insn != t->insn)
16090075Sobrien	{
16190075Sobrien	  if (INSN_P (insn))
16290075Sobrien	    {
16390075Sobrien	      clear_dead_regs (&live, REG_DEAD, REG_NOTES (insn));
16490075Sobrien	      note_stores (PATTERN (insn), note_sets, (void *) &live);
16590075Sobrien	      /* Only record currently live regs if we are inside the
16690075Sobrien		 reg's live range.  */
16790075Sobrien	      if (t != chain)
16890075Sobrien		IOR_HARD_REG_SET (*pset, live);
169117395Skan	      clear_dead_regs (&live, REG_UNUSED, REG_NOTES (insn));
17090075Sobrien	    }
17190075Sobrien	  insn = NEXT_INSN (insn);
17290075Sobrien	}
17390075Sobrien
17490075Sobrien      IOR_HARD_REG_SET (*pset, live);
17590075Sobrien
17690075Sobrien      /* For the last reference, also merge in all registers set in the
17790075Sobrien	 same insn.
17890075Sobrien	 @@@ We only have take earlyclobbered sets into account.  */
17990075Sobrien      if (! t->next_use)
18090075Sobrien	note_stores (PATTERN (insn), note_sets, (void *) pset);
18190075Sobrien
18290075Sobrien      t = t->next_use;
18390075Sobrien    }
18490075Sobrien}
18590075Sobrien
18690075Sobrien/* Perform register renaming on the current function.  */
18790075Sobrien
188169689Skanstatic void
189132718Skanregrename_optimize (void)
19090075Sobrien{
19190075Sobrien  int tick[FIRST_PSEUDO_REGISTER];
19290075Sobrien  int this_tick = 0;
193117395Skan  basic_block bb;
19490075Sobrien  char *first_obj;
19590075Sobrien
19690075Sobrien  memset (tick, 0, sizeof tick);
19790075Sobrien
19890075Sobrien  gcc_obstack_init (&rename_obstack);
199132718Skan  first_obj = obstack_alloc (&rename_obstack, 0);
20090075Sobrien
201117395Skan  FOR_EACH_BB (bb)
20290075Sobrien    {
20390075Sobrien      struct du_chain *all_chains = 0;
20490075Sobrien      HARD_REG_SET unavailable;
20590075Sobrien      HARD_REG_SET regs_seen;
20690075Sobrien
20790075Sobrien      CLEAR_HARD_REG_SET (unavailable);
20890075Sobrien
209169689Skan      if (dump_file)
210169689Skan	fprintf (dump_file, "\nBasic block %d:\n", bb->index);
21190075Sobrien
21290075Sobrien      all_chains = build_def_use (bb);
21390075Sobrien
214169689Skan      if (dump_file)
21590075Sobrien	dump_def_use_chain (all_chains);
21690075Sobrien
21790075Sobrien      CLEAR_HARD_REG_SET (unavailable);
21890075Sobrien      /* Don't clobber traceback for noreturn functions.  */
21990075Sobrien      if (frame_pointer_needed)
22090075Sobrien	{
22190075Sobrien	  int i;
222117395Skan
223169689Skan	  for (i = hard_regno_nregs[FRAME_POINTER_REGNUM][Pmode]; i--;)
22490075Sobrien	    SET_HARD_REG_BIT (unavailable, FRAME_POINTER_REGNUM + i);
225117395Skan
22690075Sobrien#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
227169689Skan	  for (i = hard_regno_nregs[HARD_FRAME_POINTER_REGNUM][Pmode]; i--;)
22890075Sobrien	    SET_HARD_REG_BIT (unavailable, HARD_FRAME_POINTER_REGNUM + i);
22990075Sobrien#endif
23090075Sobrien	}
23190075Sobrien
23290075Sobrien      CLEAR_HARD_REG_SET (regs_seen);
23390075Sobrien      while (all_chains)
23490075Sobrien	{
235132718Skan	  int new_reg, best_new_reg;
23690075Sobrien	  int n_uses;
23790075Sobrien	  struct du_chain *this = all_chains;
23890075Sobrien	  struct du_chain *tmp, *last;
23990075Sobrien	  HARD_REG_SET this_unavailable;
24090075Sobrien	  int reg = REGNO (*this->loc);
24190075Sobrien	  int i;
24290075Sobrien
24390075Sobrien	  all_chains = this->next_chain;
244117395Skan
245132718Skan	  best_new_reg = reg;
246132718Skan
24790075Sobrien#if 0 /* This just disables optimization opportunities.  */
24890075Sobrien	  /* Only rename once we've seen the reg more than once.  */
24990075Sobrien	  if (! TEST_HARD_REG_BIT (regs_seen, reg))
25090075Sobrien	    {
25190075Sobrien	      SET_HARD_REG_BIT (regs_seen, reg);
25290075Sobrien	      continue;
25390075Sobrien	    }
25490075Sobrien#endif
25590075Sobrien
25690075Sobrien	  if (fixed_regs[reg] || global_regs[reg]
25790075Sobrien#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
25890075Sobrien	      || (frame_pointer_needed && reg == HARD_FRAME_POINTER_REGNUM)
25990075Sobrien#else
26090075Sobrien	      || (frame_pointer_needed && reg == FRAME_POINTER_REGNUM)
26190075Sobrien#endif
26290075Sobrien	      )
26390075Sobrien	    continue;
26490075Sobrien
26590075Sobrien	  COPY_HARD_REG_SET (this_unavailable, unavailable);
26690075Sobrien
26790075Sobrien	  /* Find last entry on chain (which has the need_caller_save bit),
26890075Sobrien	     count number of uses, and narrow the set of registers we can
26990075Sobrien	     use for renaming.  */
27090075Sobrien	  n_uses = 0;
27190075Sobrien	  for (last = this; last->next_use; last = last->next_use)
27290075Sobrien	    {
27390075Sobrien	      n_uses++;
27490075Sobrien	      IOR_COMPL_HARD_REG_SET (this_unavailable,
275169689Skan				      reg_class_contents[last->cl]);
27690075Sobrien	    }
27790075Sobrien	  if (n_uses < 1)
27890075Sobrien	    continue;
27990075Sobrien
28090075Sobrien	  IOR_COMPL_HARD_REG_SET (this_unavailable,
281169689Skan				  reg_class_contents[last->cl]);
28290075Sobrien
28390075Sobrien	  if (this->need_caller_save_reg)
28490075Sobrien	    IOR_HARD_REG_SET (this_unavailable, call_used_reg_set);
28590075Sobrien
28690075Sobrien	  merge_overlapping_regs (bb, &this_unavailable, this);
28790075Sobrien
28890075Sobrien	  /* Now potential_regs is a reasonable approximation, let's
28990075Sobrien	     have a closer look at each register still in there.  */
29090075Sobrien	  for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++)
29190075Sobrien	    {
292169689Skan	      int nregs = hard_regno_nregs[new_reg][GET_MODE (*this->loc)];
29390075Sobrien
29490075Sobrien	      for (i = nregs - 1; i >= 0; --i)
29590075Sobrien	        if (TEST_HARD_REG_BIT (this_unavailable, new_reg + i)
29690075Sobrien		    || fixed_regs[new_reg + i]
29790075Sobrien		    || global_regs[new_reg + i]
29890075Sobrien		    /* Can't use regs which aren't saved by the prologue.  */
29990075Sobrien		    || (! regs_ever_live[new_reg + i]
30090075Sobrien			&& ! call_used_regs[new_reg + i])
30190075Sobrien#ifdef LEAF_REGISTERS
302117395Skan		    /* We can't use a non-leaf register if we're in a
30390075Sobrien		       leaf function.  */
304117395Skan		    || (current_function_is_leaf
30590075Sobrien			&& !LEAF_REGISTERS[new_reg + i])
30690075Sobrien#endif
30790075Sobrien#ifdef HARD_REGNO_RENAME_OK
30890075Sobrien		    || ! HARD_REGNO_RENAME_OK (reg + i, new_reg + i)
30990075Sobrien#endif
31090075Sobrien		    )
31190075Sobrien		  break;
31290075Sobrien	      if (i >= 0)
31390075Sobrien		continue;
31490075Sobrien
31590075Sobrien	      /* See whether it accepts all modes that occur in
31690075Sobrien		 definition and uses.  */
31790075Sobrien	      for (tmp = this; tmp; tmp = tmp->next_use)
31896263Sobrien		if (! HARD_REGNO_MODE_OK (new_reg, GET_MODE (*tmp->loc))
31996263Sobrien		    || (tmp->need_caller_save_reg
32096263Sobrien			&& ! (HARD_REGNO_CALL_PART_CLOBBERED
32196263Sobrien			      (reg, GET_MODE (*tmp->loc)))
32296263Sobrien			&& (HARD_REGNO_CALL_PART_CLOBBERED
32396263Sobrien			    (new_reg, GET_MODE (*tmp->loc)))))
32490075Sobrien		  break;
32590075Sobrien	      if (! tmp)
32690075Sobrien		{
327132718Skan		  if (tick[best_new_reg] > tick[new_reg])
32890075Sobrien		    best_new_reg = new_reg;
32990075Sobrien		}
33090075Sobrien	    }
33190075Sobrien
332169689Skan	  if (dump_file)
33390075Sobrien	    {
334169689Skan	      fprintf (dump_file, "Register %s in insn %d",
33590075Sobrien		       reg_names[reg], INSN_UID (last->insn));
33690075Sobrien	      if (last->need_caller_save_reg)
337169689Skan		fprintf (dump_file, " crosses a call");
338117395Skan	    }
33990075Sobrien
340132718Skan	  if (best_new_reg == reg)
34190075Sobrien	    {
342132718Skan	      tick[reg] = ++this_tick;
343169689Skan	      if (dump_file)
344169689Skan		fprintf (dump_file, "; no available better choice\n");
34590075Sobrien	      continue;
34690075Sobrien	    }
34790075Sobrien
34890075Sobrien	  do_replace (this, best_new_reg);
349132718Skan	  tick[best_new_reg] = ++this_tick;
350169689Skan	  regs_ever_live[best_new_reg] = 1;
35190075Sobrien
352169689Skan	  if (dump_file)
353169689Skan	    fprintf (dump_file, ", renamed as %s\n", reg_names[best_new_reg]);
35490075Sobrien	}
35590075Sobrien
35690075Sobrien      obstack_free (&rename_obstack, first_obj);
35790075Sobrien    }
35890075Sobrien
35990075Sobrien  obstack_free (&rename_obstack, NULL);
36090075Sobrien
361169689Skan  if (dump_file)
362169689Skan    fputc ('\n', dump_file);
36390075Sobrien
36490075Sobrien  count_or_remove_death_notes (NULL, 1);
36590075Sobrien  update_life_info (NULL, UPDATE_LIFE_LOCAL,
366169689Skan		    PROP_DEATH_NOTES);
36790075Sobrien}
36890075Sobrien
36990075Sobrienstatic void
370132718Skando_replace (struct du_chain *chain, int reg)
37190075Sobrien{
37290075Sobrien  while (chain)
37390075Sobrien    {
37490075Sobrien      unsigned int regno = ORIGINAL_REGNO (*chain->loc);
375132718Skan      struct reg_attrs * attr = REG_ATTRS (*chain->loc);
376132718Skan
37790075Sobrien      *chain->loc = gen_raw_REG (GET_MODE (*chain->loc), reg);
37890075Sobrien      if (regno >= FIRST_PSEUDO_REGISTER)
37990075Sobrien	ORIGINAL_REGNO (*chain->loc) = regno;
380132718Skan      REG_ATTRS (*chain->loc) = attr;
38190075Sobrien      chain = chain->next_use;
38290075Sobrien    }
38390075Sobrien}
38490075Sobrien
38590075Sobrien
38690075Sobrienstatic struct du_chain *open_chains;
38790075Sobrienstatic struct du_chain *closed_chains;
38890075Sobrien
38990075Sobrienstatic void
390169689Skanscan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl,
391132718Skan	      enum scan_actions action, enum op_type type, int earlyclobber)
39290075Sobrien{
39390075Sobrien  struct du_chain **p;
39490075Sobrien  rtx x = *loc;
39590075Sobrien  enum machine_mode mode = GET_MODE (x);
39690075Sobrien  int this_regno = REGNO (x);
397169689Skan  int this_nregs = hard_regno_nregs[this_regno][mode];
39890075Sobrien
39990075Sobrien  if (action == mark_write)
40090075Sobrien    {
40190075Sobrien      if (type == OP_OUT)
40290075Sobrien	{
403132718Skan	  struct du_chain *this
404132718Skan	    = obstack_alloc (&rename_obstack, sizeof (struct du_chain));
40590075Sobrien	  this->next_use = 0;
40690075Sobrien	  this->next_chain = open_chains;
40790075Sobrien	  this->loc = loc;
40890075Sobrien	  this->insn = insn;
409169689Skan	  this->cl = cl;
41090075Sobrien	  this->need_caller_save_reg = 0;
41190075Sobrien	  this->earlyclobber = earlyclobber;
41290075Sobrien	  open_chains = this;
41390075Sobrien	}
41490075Sobrien      return;
41590075Sobrien    }
41690075Sobrien
417169689Skan  if ((type == OP_OUT) != (action == terminate_write || action == mark_access))
41890075Sobrien    return;
41990075Sobrien
42090075Sobrien  for (p = &open_chains; *p;)
42190075Sobrien    {
42290075Sobrien      struct du_chain *this = *p;
42390075Sobrien
42490075Sobrien      /* Check if the chain has been terminated if it has then skip to
42590075Sobrien	 the next chain.
42690075Sobrien
42790075Sobrien	 This can happen when we've already appended the location to
42890075Sobrien	 the chain in Step 3, but are trying to hide in-out operands
42990075Sobrien	 from terminate_write in Step 5.  */
43090075Sobrien
43190075Sobrien      if (*this->loc == cc0_rtx)
43290075Sobrien	p = &this->next_chain;
43390075Sobrien      else
434117395Skan	{
43590075Sobrien	  int regno = REGNO (*this->loc);
436169689Skan	  int nregs = hard_regno_nregs[regno][GET_MODE (*this->loc)];
43790075Sobrien	  int exact_match = (regno == this_regno && nregs == this_nregs);
43890075Sobrien
43990075Sobrien	  if (regno + nregs <= this_regno
44090075Sobrien	      || this_regno + this_nregs <= regno)
44190075Sobrien	    {
44290075Sobrien	      p = &this->next_chain;
44390075Sobrien	      continue;
44490075Sobrien	    }
44590075Sobrien
446169689Skan	  if (action == mark_read || action == mark_access)
44790075Sobrien	    {
448169689Skan	      gcc_assert (exact_match);
44990075Sobrien
450117395Skan	      /* ??? Class NO_REGS can happen if the md file makes use of
45190075Sobrien		 EXTRA_CONSTRAINTS to match registers.  Which is arguably
45290075Sobrien		 wrong, but there we are.  Since we know not what this may
45390075Sobrien		 be replaced with, terminate the chain.  */
454169689Skan	      if (cl != NO_REGS)
45590075Sobrien		{
456132718Skan		  this = obstack_alloc (&rename_obstack, sizeof (struct du_chain));
45790075Sobrien		  this->next_use = 0;
45890075Sobrien		  this->next_chain = (*p)->next_chain;
45990075Sobrien		  this->loc = loc;
46090075Sobrien		  this->insn = insn;
461169689Skan		  this->cl = cl;
46290075Sobrien		  this->need_caller_save_reg = 0;
46390075Sobrien		  while (*p)
46490075Sobrien		    p = &(*p)->next_use;
46590075Sobrien		  *p = this;
46690075Sobrien		  return;
46790075Sobrien		}
46890075Sobrien	    }
46990075Sobrien
47090075Sobrien	  if (action != terminate_overlapping_read || ! exact_match)
47190075Sobrien	    {
47290075Sobrien	      struct du_chain *next = this->next_chain;
47390075Sobrien
47490075Sobrien	      /* Whether the terminated chain can be used for renaming
47590075Sobrien	         depends on the action and this being an exact match.
47690075Sobrien	         In either case, we remove this element from open_chains.  */
47790075Sobrien
47890075Sobrien	      if ((action == terminate_dead || action == terminate_write)
47990075Sobrien		  && exact_match)
48090075Sobrien		{
48190075Sobrien		  this->next_chain = closed_chains;
48290075Sobrien		  closed_chains = this;
483169689Skan		  if (dump_file)
484169689Skan		    fprintf (dump_file,
48590075Sobrien			     "Closing chain %s at insn %d (%s)\n",
48690075Sobrien			     reg_names[REGNO (*this->loc)], INSN_UID (insn),
48790075Sobrien			     scan_actions_name[(int) action]);
48890075Sobrien		}
48990075Sobrien	      else
49090075Sobrien		{
491169689Skan		  if (dump_file)
492169689Skan		    fprintf (dump_file,
49390075Sobrien			     "Discarding chain %s at insn %d (%s)\n",
49490075Sobrien			     reg_names[REGNO (*this->loc)], INSN_UID (insn),
49590075Sobrien			     scan_actions_name[(int) action]);
49690075Sobrien		}
49790075Sobrien	      *p = next;
49890075Sobrien	    }
49990075Sobrien	  else
50090075Sobrien	    p = &this->next_chain;
50190075Sobrien	}
50290075Sobrien    }
50390075Sobrien}
50490075Sobrien
505169689Skan/* Adapted from find_reloads_address_1.  CL is INDEX_REG_CLASS or
50690075Sobrien   BASE_REG_CLASS depending on how the register is being considered.  */
50790075Sobrien
50890075Sobrienstatic void
509169689Skanscan_rtx_address (rtx insn, rtx *loc, enum reg_class cl,
510132718Skan		  enum scan_actions action, enum machine_mode mode)
51190075Sobrien{
51290075Sobrien  rtx x = *loc;
51390075Sobrien  RTX_CODE code = GET_CODE (x);
51490075Sobrien  const char *fmt;
51590075Sobrien  int i, j;
51690075Sobrien
517169689Skan  if (action == mark_write || action == mark_access)
51890075Sobrien    return;
51990075Sobrien
52090075Sobrien  switch (code)
52190075Sobrien    {
52290075Sobrien    case PLUS:
52390075Sobrien      {
52490075Sobrien	rtx orig_op0 = XEXP (x, 0);
52590075Sobrien	rtx orig_op1 = XEXP (x, 1);
52690075Sobrien	RTX_CODE code0 = GET_CODE (orig_op0);
52790075Sobrien	RTX_CODE code1 = GET_CODE (orig_op1);
52890075Sobrien	rtx op0 = orig_op0;
52990075Sobrien	rtx op1 = orig_op1;
53090075Sobrien	rtx *locI = NULL;
53190075Sobrien	rtx *locB = NULL;
532169689Skan	enum rtx_code index_code = SCRATCH;
53390075Sobrien
53490075Sobrien	if (GET_CODE (op0) == SUBREG)
53590075Sobrien	  {
53690075Sobrien	    op0 = SUBREG_REG (op0);
53790075Sobrien	    code0 = GET_CODE (op0);
53890075Sobrien	  }
53990075Sobrien
54090075Sobrien	if (GET_CODE (op1) == SUBREG)
54190075Sobrien	  {
54290075Sobrien	    op1 = SUBREG_REG (op1);
54390075Sobrien	    code1 = GET_CODE (op1);
54490075Sobrien	  }
54590075Sobrien
54690075Sobrien	if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
54790075Sobrien	    || code0 == ZERO_EXTEND || code1 == MEM)
54890075Sobrien	  {
54990075Sobrien	    locI = &XEXP (x, 0);
55090075Sobrien	    locB = &XEXP (x, 1);
551169689Skan	    index_code = GET_CODE (*locI);
55290075Sobrien	  }
55390075Sobrien	else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
55490075Sobrien		 || code1 == ZERO_EXTEND || code0 == MEM)
55590075Sobrien	  {
55690075Sobrien	    locI = &XEXP (x, 1);
55790075Sobrien	    locB = &XEXP (x, 0);
558169689Skan	    index_code = GET_CODE (*locI);
55990075Sobrien	  }
56090075Sobrien	else if (code0 == CONST_INT || code0 == CONST
56190075Sobrien		 || code0 == SYMBOL_REF || code0 == LABEL_REF)
562169689Skan	  {
563169689Skan	    locB = &XEXP (x, 1);
564169689Skan	    index_code = GET_CODE (XEXP (x, 0));
565169689Skan	  }
56690075Sobrien	else if (code1 == CONST_INT || code1 == CONST
56790075Sobrien		 || code1 == SYMBOL_REF || code1 == LABEL_REF)
568169689Skan	  {
569169689Skan	    locB = &XEXP (x, 0);
570169689Skan	    index_code = GET_CODE (XEXP (x, 1));
571169689Skan	  }
57290075Sobrien	else if (code0 == REG && code1 == REG)
57390075Sobrien	  {
57490075Sobrien	    int index_op;
575169689Skan	    unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
57690075Sobrien
577169689Skan	    if (REGNO_OK_FOR_INDEX_P (regno0)
578169689Skan		&& regno_ok_for_base_p (regno1, mode, PLUS, REG))
57990075Sobrien	      index_op = 0;
580169689Skan	    else if (REGNO_OK_FOR_INDEX_P (regno1)
581169689Skan		     && regno_ok_for_base_p (regno0, mode, PLUS, REG))
58290075Sobrien	      index_op = 1;
583169689Skan	    else if (regno_ok_for_base_p (regno1, mode, PLUS, REG))
58490075Sobrien	      index_op = 0;
585169689Skan	    else if (regno_ok_for_base_p (regno0, mode, PLUS, REG))
58690075Sobrien	      index_op = 1;
587169689Skan	    else if (REGNO_OK_FOR_INDEX_P (regno1))
58890075Sobrien	      index_op = 1;
58990075Sobrien	    else
59090075Sobrien	      index_op = 0;
59190075Sobrien
59290075Sobrien	    locI = &XEXP (x, index_op);
59390075Sobrien	    locB = &XEXP (x, !index_op);
594169689Skan	    index_code = GET_CODE (*locI);
59590075Sobrien	  }
59690075Sobrien	else if (code0 == REG)
59790075Sobrien	  {
59890075Sobrien	    locI = &XEXP (x, 0);
59990075Sobrien	    locB = &XEXP (x, 1);
600169689Skan	    index_code = GET_CODE (*locI);
60190075Sobrien	  }
60290075Sobrien	else if (code1 == REG)
60390075Sobrien	  {
60490075Sobrien	    locI = &XEXP (x, 1);
60590075Sobrien	    locB = &XEXP (x, 0);
606169689Skan	    index_code = GET_CODE (*locI);
60790075Sobrien	  }
60890075Sobrien
60990075Sobrien	if (locI)
61090075Sobrien	  scan_rtx_address (insn, locI, INDEX_REG_CLASS, action, mode);
61190075Sobrien	if (locB)
612169689Skan	  scan_rtx_address (insn, locB, base_reg_class (mode, PLUS, index_code),
613169689Skan			    action, mode);
614169689Skan
61590075Sobrien	return;
61690075Sobrien      }
61790075Sobrien
61890075Sobrien    case POST_INC:
61990075Sobrien    case POST_DEC:
62090075Sobrien    case POST_MODIFY:
62190075Sobrien    case PRE_INC:
62290075Sobrien    case PRE_DEC:
62390075Sobrien    case PRE_MODIFY:
62490075Sobrien#ifndef AUTO_INC_DEC
62590075Sobrien      /* If the target doesn't claim to handle autoinc, this must be
62690075Sobrien	 something special, like a stack push.  Kill this chain.  */
62790075Sobrien      action = terminate_all_read;
62890075Sobrien#endif
62990075Sobrien      break;
63090075Sobrien
63190075Sobrien    case MEM:
63290075Sobrien      scan_rtx_address (insn, &XEXP (x, 0),
633169689Skan			base_reg_class (GET_MODE (x), MEM, SCRATCH), action,
63490075Sobrien			GET_MODE (x));
63590075Sobrien      return;
63690075Sobrien
63790075Sobrien    case REG:
638169689Skan      scan_rtx_reg (insn, loc, cl, action, OP_IN, 0);
63990075Sobrien      return;
64090075Sobrien
64190075Sobrien    default:
64290075Sobrien      break;
64390075Sobrien    }
64490075Sobrien
64590075Sobrien  fmt = GET_RTX_FORMAT (code);
64690075Sobrien  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
64790075Sobrien    {
64890075Sobrien      if (fmt[i] == 'e')
649169689Skan	scan_rtx_address (insn, &XEXP (x, i), cl, action, mode);
65090075Sobrien      else if (fmt[i] == 'E')
65190075Sobrien	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
652169689Skan	  scan_rtx_address (insn, &XVECEXP (x, i, j), cl, action, mode);
65390075Sobrien    }
65490075Sobrien}
65590075Sobrien
65690075Sobrienstatic void
657169689Skanscan_rtx (rtx insn, rtx *loc, enum reg_class cl,
658132718Skan	  enum scan_actions action, enum op_type type, int earlyclobber)
65990075Sobrien{
66090075Sobrien  const char *fmt;
66190075Sobrien  rtx x = *loc;
66290075Sobrien  enum rtx_code code = GET_CODE (x);
66390075Sobrien  int i, j;
66490075Sobrien
66590075Sobrien  code = GET_CODE (x);
66690075Sobrien  switch (code)
66790075Sobrien    {
66890075Sobrien    case CONST:
66990075Sobrien    case CONST_INT:
67090075Sobrien    case CONST_DOUBLE:
67196263Sobrien    case CONST_VECTOR:
67290075Sobrien    case SYMBOL_REF:
67390075Sobrien    case LABEL_REF:
67490075Sobrien    case CC0:
67590075Sobrien    case PC:
67690075Sobrien      return;
67790075Sobrien
67890075Sobrien    case REG:
679169689Skan      scan_rtx_reg (insn, loc, cl, action, type, earlyclobber);
68090075Sobrien      return;
68190075Sobrien
68290075Sobrien    case MEM:
68390075Sobrien      scan_rtx_address (insn, &XEXP (x, 0),
684169689Skan			base_reg_class (GET_MODE (x), MEM, SCRATCH), action,
68590075Sobrien			GET_MODE (x));
68690075Sobrien      return;
68790075Sobrien
68890075Sobrien    case SET:
689169689Skan      scan_rtx (insn, &SET_SRC (x), cl, action, OP_IN, 0);
690169689Skan      scan_rtx (insn, &SET_DEST (x), cl, action,
691161651Skan		GET_CODE (PATTERN (insn)) == COND_EXEC ? OP_INOUT : OP_OUT, 0);
69290075Sobrien      return;
69390075Sobrien
69490075Sobrien    case STRICT_LOW_PART:
695169689Skan      scan_rtx (insn, &XEXP (x, 0), cl, action, OP_INOUT, earlyclobber);
69690075Sobrien      return;
69790075Sobrien
69890075Sobrien    case ZERO_EXTRACT:
699117395Skan    case SIGN_EXTRACT:
700169689Skan      scan_rtx (insn, &XEXP (x, 0), cl, action,
70190075Sobrien		type == OP_IN ? OP_IN : OP_INOUT, earlyclobber);
702169689Skan      scan_rtx (insn, &XEXP (x, 1), cl, action, OP_IN, 0);
703169689Skan      scan_rtx (insn, &XEXP (x, 2), cl, action, OP_IN, 0);
70490075Sobrien      return;
70590075Sobrien
70690075Sobrien    case POST_INC:
70790075Sobrien    case PRE_INC:
70890075Sobrien    case POST_DEC:
70990075Sobrien    case PRE_DEC:
71090075Sobrien    case POST_MODIFY:
71190075Sobrien    case PRE_MODIFY:
71290075Sobrien      /* Should only happen inside MEM.  */
713169689Skan      gcc_unreachable ();
71490075Sobrien
71590075Sobrien    case CLOBBER:
716169689Skan      scan_rtx (insn, &SET_DEST (x), cl, action,
717169689Skan		GET_CODE (PATTERN (insn)) == COND_EXEC ? OP_INOUT : OP_OUT, 0);
71890075Sobrien      return;
71990075Sobrien
72090075Sobrien    case EXPR_LIST:
721169689Skan      scan_rtx (insn, &XEXP (x, 0), cl, action, type, 0);
72290075Sobrien      if (XEXP (x, 1))
723169689Skan	scan_rtx (insn, &XEXP (x, 1), cl, action, type, 0);
72490075Sobrien      return;
72590075Sobrien
72690075Sobrien    default:
72790075Sobrien      break;
72890075Sobrien    }
72990075Sobrien
73090075Sobrien  fmt = GET_RTX_FORMAT (code);
73190075Sobrien  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
73290075Sobrien    {
73390075Sobrien      if (fmt[i] == 'e')
734169689Skan	scan_rtx (insn, &XEXP (x, i), cl, action, type, 0);
73590075Sobrien      else if (fmt[i] == 'E')
73690075Sobrien	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
737169689Skan	  scan_rtx (insn, &XVECEXP (x, i, j), cl, action, type, 0);
73890075Sobrien    }
73990075Sobrien}
74090075Sobrien
741117395Skan/* Build def/use chain.  */
74290075Sobrien
74390075Sobrienstatic struct du_chain *
744132718Skanbuild_def_use (basic_block bb)
74590075Sobrien{
74690075Sobrien  rtx insn;
74790075Sobrien
74890075Sobrien  open_chains = closed_chains = NULL;
74990075Sobrien
750132718Skan  for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
75190075Sobrien    {
75290075Sobrien      if (INSN_P (insn))
75390075Sobrien	{
75490075Sobrien	  int n_ops;
75590075Sobrien	  rtx note;
75690075Sobrien	  rtx old_operands[MAX_RECOG_OPERANDS];
75790075Sobrien	  rtx old_dups[MAX_DUP_OPERANDS];
75896263Sobrien	  int i, icode;
75990075Sobrien	  int alt;
76090075Sobrien	  int predicated;
76190075Sobrien
76290075Sobrien	  /* Process the insn, determining its effect on the def-use
76390075Sobrien	     chains.  We perform the following steps with the register
76490075Sobrien	     references in the insn:
76590075Sobrien	     (1) Any read that overlaps an open chain, but doesn't exactly
76690075Sobrien	         match, causes that chain to be closed.  We can't deal
76790075Sobrien	         with overlaps yet.
76890075Sobrien	     (2) Any read outside an operand causes any chain it overlaps
76990075Sobrien	         with to be closed, since we can't replace it.
77090075Sobrien	     (3) Any read inside an operand is added if there's already
77190075Sobrien	         an open chain for it.
77290075Sobrien	     (4) For any REG_DEAD note we find, close open chains that
77390075Sobrien	         overlap it.
77490075Sobrien	     (5) For any write we find, close open chains that overlap it.
77590075Sobrien	     (6) For any write we find in an operand, make a new chain.
77690075Sobrien	     (7) For any REG_UNUSED, close any chains we just opened.  */
77790075Sobrien
77896263Sobrien	  icode = recog_memoized (insn);
77990075Sobrien	  extract_insn (insn);
780117395Skan	  if (! constrain_operands (1))
781117395Skan	    fatal_insn_not_found (insn);
78290075Sobrien	  preprocess_constraints ();
78390075Sobrien	  alt = which_alternative;
78490075Sobrien	  n_ops = recog_data.n_operands;
78590075Sobrien
78690075Sobrien	  /* Simplify the code below by rewriting things to reflect
78790075Sobrien	     matching constraints.  Also promote OP_OUT to OP_INOUT
78890075Sobrien	     in predicated instructions.  */
78990075Sobrien
79090075Sobrien	  predicated = GET_CODE (PATTERN (insn)) == COND_EXEC;
79190075Sobrien	  for (i = 0; i < n_ops; ++i)
79290075Sobrien	    {
79390075Sobrien	      int matches = recog_op_alt[i][alt].matches;
79490075Sobrien	      if (matches >= 0)
795169689Skan		recog_op_alt[i][alt].cl = recog_op_alt[matches][alt].cl;
79690075Sobrien	      if (matches >= 0 || recog_op_alt[i][alt].matched >= 0
79790075Sobrien	          || (predicated && recog_data.operand_type[i] == OP_OUT))
79890075Sobrien		recog_data.operand_type[i] = OP_INOUT;
79990075Sobrien	    }
80090075Sobrien
80190075Sobrien	  /* Step 1: Close chains for which we have overlapping reads.  */
80290075Sobrien	  for (i = 0; i < n_ops; i++)
80390075Sobrien	    scan_rtx (insn, recog_data.operand_loc[i],
80490075Sobrien		      NO_REGS, terminate_overlapping_read,
80590075Sobrien		      recog_data.operand_type[i], 0);
80690075Sobrien
80790075Sobrien	  /* Step 2: Close chains for which we have reads outside operands.
808117395Skan	     We do this by munging all operands into CC0, and closing
80990075Sobrien	     everything remaining.  */
81090075Sobrien
81190075Sobrien	  for (i = 0; i < n_ops; i++)
81290075Sobrien	    {
81390075Sobrien	      old_operands[i] = recog_data.operand[i];
81490075Sobrien	      /* Don't squash match_operator or match_parallel here, since
815117395Skan		 we don't know that all of the contained registers are
81690075Sobrien		 reachable by proper operands.  */
81790075Sobrien	      if (recog_data.constraints[i][0] == '\0')
81890075Sobrien		continue;
81990075Sobrien	      *recog_data.operand_loc[i] = cc0_rtx;
82090075Sobrien	    }
82190075Sobrien	  for (i = 0; i < recog_data.n_dups; i++)
82290075Sobrien	    {
82396263Sobrien	      int dup_num = recog_data.dup_num[i];
82496263Sobrien
82590075Sobrien	      old_dups[i] = *recog_data.dup_loc[i];
82690075Sobrien	      *recog_data.dup_loc[i] = cc0_rtx;
82796263Sobrien
82896263Sobrien	      /* For match_dup of match_operator or match_parallel, share
82996263Sobrien		 them, so that we don't miss changes in the dup.  */
83096263Sobrien	      if (icode >= 0
83196263Sobrien		  && insn_data[icode].operand[dup_num].eliminable == 0)
83296263Sobrien		old_dups[i] = recog_data.operand[dup_num];
83390075Sobrien	    }
83490075Sobrien
83590075Sobrien	  scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_all_read,
83690075Sobrien		    OP_IN, 0);
83790075Sobrien
83890075Sobrien	  for (i = 0; i < recog_data.n_dups; i++)
83990075Sobrien	    *recog_data.dup_loc[i] = old_dups[i];
84090075Sobrien	  for (i = 0; i < n_ops; i++)
84190075Sobrien	    *recog_data.operand_loc[i] = old_operands[i];
84290075Sobrien
84390075Sobrien	  /* Step 2B: Can't rename function call argument registers.  */
844169689Skan	  if (CALL_P (insn) && CALL_INSN_FUNCTION_USAGE (insn))
84590075Sobrien	    scan_rtx (insn, &CALL_INSN_FUNCTION_USAGE (insn),
84690075Sobrien		      NO_REGS, terminate_all_read, OP_IN, 0);
84790075Sobrien
84890075Sobrien	  /* Step 2C: Can't rename asm operands that were originally
84990075Sobrien	     hard registers.  */
85090075Sobrien	  if (asm_noperands (PATTERN (insn)) > 0)
85190075Sobrien	    for (i = 0; i < n_ops; i++)
85290075Sobrien	      {
85390075Sobrien		rtx *loc = recog_data.operand_loc[i];
85490075Sobrien		rtx op = *loc;
85590075Sobrien
856169689Skan		if (REG_P (op)
85790075Sobrien		    && REGNO (op) == ORIGINAL_REGNO (op)
85890075Sobrien		    && (recog_data.operand_type[i] == OP_IN
85990075Sobrien			|| recog_data.operand_type[i] == OP_INOUT))
86090075Sobrien		  scan_rtx (insn, loc, NO_REGS, terminate_all_read, OP_IN, 0);
86190075Sobrien	      }
86290075Sobrien
86390075Sobrien	  /* Step 3: Append to chains for reads inside operands.  */
86490075Sobrien	  for (i = 0; i < n_ops + recog_data.n_dups; i++)
86590075Sobrien	    {
86690075Sobrien	      int opn = i < n_ops ? i : recog_data.dup_num[i - n_ops];
86790075Sobrien	      rtx *loc = (i < n_ops
86890075Sobrien			  ? recog_data.operand_loc[opn]
86990075Sobrien			  : recog_data.dup_loc[i - n_ops]);
870169689Skan	      enum reg_class cl = recog_op_alt[opn][alt].cl;
87190075Sobrien	      enum op_type type = recog_data.operand_type[opn];
87290075Sobrien
87390075Sobrien	      /* Don't scan match_operand here, since we've no reg class
87490075Sobrien		 information to pass down.  Any operands that we could
87590075Sobrien		 substitute in will be represented elsewhere.  */
87690075Sobrien	      if (recog_data.constraints[opn][0] == '\0')
87790075Sobrien		continue;
87890075Sobrien
87990075Sobrien	      if (recog_op_alt[opn][alt].is_address)
880169689Skan		scan_rtx_address (insn, loc, cl, mark_read, VOIDmode);
88190075Sobrien	      else
882169689Skan		scan_rtx (insn, loc, cl, mark_read, type, 0);
88390075Sobrien	    }
88490075Sobrien
885169689Skan	  /* Step 3B: Record updates for regs in REG_INC notes, and
886169689Skan	     source regs in REG_FRAME_RELATED_EXPR notes.  */
88790075Sobrien	  for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
888169689Skan	    if (REG_NOTE_KIND (note) == REG_INC
889169689Skan		|| REG_NOTE_KIND (note) == REG_FRAME_RELATED_EXPR)
890169689Skan	      scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_read,
891169689Skan			OP_INOUT, 0);
89290075Sobrien
893169689Skan	  /* Step 4: Close chains for registers that die here.  */
894169689Skan	  for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
895169689Skan	    if (REG_NOTE_KIND (note) == REG_DEAD)
896169689Skan	      scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead,
897169689Skan			OP_IN, 0);
898169689Skan
89990075Sobrien	  /* Step 4B: If this is a call, any chain live at this point
90090075Sobrien	     requires a caller-saved reg.  */
901169689Skan	  if (CALL_P (insn))
90290075Sobrien	    {
90390075Sobrien	      struct du_chain *p;
90490075Sobrien	      for (p = open_chains; p; p = p->next_chain)
90590075Sobrien		p->need_caller_save_reg = 1;
90690075Sobrien	    }
90790075Sobrien
90890075Sobrien	  /* Step 5: Close open chains that overlap writes.  Similar to
90990075Sobrien	     step 2, we hide in-out operands, since we do not want to
91090075Sobrien	     close these chains.  */
91190075Sobrien
91290075Sobrien	  for (i = 0; i < n_ops; i++)
91390075Sobrien	    {
91490075Sobrien	      old_operands[i] = recog_data.operand[i];
91590075Sobrien	      if (recog_data.operand_type[i] == OP_INOUT)
91690075Sobrien		*recog_data.operand_loc[i] = cc0_rtx;
91790075Sobrien	    }
91890075Sobrien	  for (i = 0; i < recog_data.n_dups; i++)
91990075Sobrien	    {
92090075Sobrien	      int opn = recog_data.dup_num[i];
92190075Sobrien	      old_dups[i] = *recog_data.dup_loc[i];
92290075Sobrien	      if (recog_data.operand_type[opn] == OP_INOUT)
92390075Sobrien		*recog_data.dup_loc[i] = cc0_rtx;
92490075Sobrien	    }
92590075Sobrien
92690075Sobrien	  scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_write, OP_IN, 0);
92790075Sobrien
92890075Sobrien	  for (i = 0; i < recog_data.n_dups; i++)
92990075Sobrien	    *recog_data.dup_loc[i] = old_dups[i];
93090075Sobrien	  for (i = 0; i < n_ops; i++)
93190075Sobrien	    *recog_data.operand_loc[i] = old_operands[i];
93290075Sobrien
93390075Sobrien	  /* Step 6: Begin new chains for writes inside operands.  */
93490075Sobrien	  /* ??? Many targets have output constraints on the SET_DEST
93590075Sobrien	     of a call insn, which is stupid, since these are certainly
93690075Sobrien	     ABI defined hard registers.  Don't change calls at all.
93790075Sobrien	     Similarly take special care for asm statement that originally
93890075Sobrien	     referenced hard registers.  */
93990075Sobrien	  if (asm_noperands (PATTERN (insn)) > 0)
94090075Sobrien	    {
94190075Sobrien	      for (i = 0; i < n_ops; i++)
94290075Sobrien		if (recog_data.operand_type[i] == OP_OUT)
94390075Sobrien		  {
94490075Sobrien		    rtx *loc = recog_data.operand_loc[i];
94590075Sobrien		    rtx op = *loc;
946169689Skan		    enum reg_class cl = recog_op_alt[i][alt].cl;
94790075Sobrien
948169689Skan		    if (REG_P (op)
949117395Skan			&& REGNO (op) == ORIGINAL_REGNO (op))
95090075Sobrien		      continue;
95190075Sobrien
952169689Skan		    scan_rtx (insn, loc, cl, mark_write, OP_OUT,
95390075Sobrien			      recog_op_alt[i][alt].earlyclobber);
95490075Sobrien		  }
95590075Sobrien	    }
956169689Skan	  else if (!CALL_P (insn))
95790075Sobrien	    for (i = 0; i < n_ops + recog_data.n_dups; i++)
95890075Sobrien	      {
95990075Sobrien		int opn = i < n_ops ? i : recog_data.dup_num[i - n_ops];
96090075Sobrien		rtx *loc = (i < n_ops
96190075Sobrien			    ? recog_data.operand_loc[opn]
96290075Sobrien			    : recog_data.dup_loc[i - n_ops]);
963169689Skan		enum reg_class cl = recog_op_alt[opn][alt].cl;
96490075Sobrien
96590075Sobrien		if (recog_data.operand_type[opn] == OP_OUT)
966169689Skan		  scan_rtx (insn, loc, cl, mark_write, OP_OUT,
96790075Sobrien			    recog_op_alt[opn][alt].earlyclobber);
96890075Sobrien	      }
96990075Sobrien
970169689Skan	  /* Step 6B: Record destination regs in REG_FRAME_RELATED_EXPR
971169689Skan	     notes for update.  */
972169689Skan	  for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
973169689Skan	    if (REG_NOTE_KIND (note) == REG_FRAME_RELATED_EXPR)
974169689Skan	      scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_access,
975169689Skan			OP_INOUT, 0);
976169689Skan
97790075Sobrien	  /* Step 7: Close chains for registers that were never
97890075Sobrien	     really used here.  */
97990075Sobrien	  for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
98090075Sobrien	    if (REG_NOTE_KIND (note) == REG_UNUSED)
98190075Sobrien	      scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead,
98290075Sobrien			OP_IN, 0);
98390075Sobrien	}
984132718Skan      if (insn == BB_END (bb))
98590075Sobrien	break;
98690075Sobrien    }
98790075Sobrien
98890075Sobrien  /* Since we close every chain when we find a REG_DEAD note, anything that
98990075Sobrien     is still open lives past the basic block, so it can't be renamed.  */
99090075Sobrien  return closed_chains;
99190075Sobrien}
99290075Sobrien
993169689Skan/* Dump all def/use chains in CHAINS to DUMP_FILE.  They are
99490075Sobrien   printed in reverse order as that's how we build them.  */
99590075Sobrien
99690075Sobrienstatic void
997132718Skandump_def_use_chain (struct du_chain *chains)
99890075Sobrien{
99990075Sobrien  while (chains)
100090075Sobrien    {
100190075Sobrien      struct du_chain *this = chains;
100290075Sobrien      int r = REGNO (*this->loc);
1003169689Skan      int nregs = hard_regno_nregs[r][GET_MODE (*this->loc)];
1004169689Skan      fprintf (dump_file, "Register %s (%d):", reg_names[r], nregs);
100590075Sobrien      while (this)
100690075Sobrien	{
1007169689Skan	  fprintf (dump_file, " %d [%s]", INSN_UID (this->insn),
1008169689Skan		   reg_class_names[this->cl]);
100990075Sobrien	  this = this->next_use;
101090075Sobrien	}
1011169689Skan      fprintf (dump_file, "\n");
101290075Sobrien      chains = chains->next_chain;
101390075Sobrien    }
101490075Sobrien}
101590075Sobrien
101690075Sobrien/* The following code does forward propagation of hard register copies.
101790075Sobrien   The object is to eliminate as many dependencies as possible, so that
101890075Sobrien   we have the most scheduling freedom.  As a side effect, we also clean
1019117395Skan   up some silly register allocation decisions made by reload.  This
102090075Sobrien   code may be obsoleted by a new register allocator.  */
102190075Sobrien
102290075Sobrien/* For each register, we have a list of registers that contain the same
1023117395Skan   value.  The OLDEST_REGNO field points to the head of the list, and
102490075Sobrien   the NEXT_REGNO field runs through the list.  The MODE field indicates
102590075Sobrien   what mode the data is known to be in; this field is VOIDmode when the
102690075Sobrien   register is not known to contain valid data.  */
102790075Sobrien
102890075Sobrienstruct value_data_entry
102990075Sobrien{
103090075Sobrien  enum machine_mode mode;
103190075Sobrien  unsigned int oldest_regno;
103290075Sobrien  unsigned int next_regno;
103390075Sobrien};
103490075Sobrien
103590075Sobrienstruct value_data
103690075Sobrien{
103790075Sobrien  struct value_data_entry e[FIRST_PSEUDO_REGISTER];
103890075Sobrien  unsigned int max_value_regs;
103990075Sobrien};
104090075Sobrien
1041169689Skanstatic void kill_value_one_regno (unsigned, struct value_data *);
1042169689Skanstatic void kill_value_regno (unsigned, unsigned, struct value_data *);
1043132718Skanstatic void kill_value (rtx, struct value_data *);
1044132718Skanstatic void set_value_regno (unsigned, enum machine_mode, struct value_data *);
1045132718Skanstatic void init_value_data (struct value_data *);
1046132718Skanstatic void kill_clobbered_value (rtx, rtx, void *);
1047132718Skanstatic void kill_set_value (rtx, rtx, void *);
1048132718Skanstatic int kill_autoinc_value (rtx *, void *);
1049132718Skanstatic void copy_value (rtx, rtx, struct value_data *);
1050132718Skanstatic bool mode_change_ok (enum machine_mode, enum machine_mode,
1051132718Skan			    unsigned int);
1052132718Skanstatic rtx maybe_mode_change (enum machine_mode, enum machine_mode,
1053132718Skan			      enum machine_mode, unsigned int, unsigned int);
1054132718Skanstatic rtx find_oldest_value_reg (enum reg_class, rtx, struct value_data *);
1055132718Skanstatic bool replace_oldest_value_reg (rtx *, enum reg_class, rtx,
1056132718Skan				      struct value_data *);
1057132718Skanstatic bool replace_oldest_value_addr (rtx *, enum reg_class,
1058132718Skan				       enum machine_mode, rtx,
1059132718Skan				       struct value_data *);
1060132718Skanstatic bool replace_oldest_value_mem (rtx, rtx, struct value_data *);
1061132718Skanstatic bool copyprop_hardreg_forward_1 (basic_block, struct value_data *);
1062132718Skanextern void debug_value_data (struct value_data *);
106390075Sobrien#ifdef ENABLE_CHECKING
1064132718Skanstatic void validate_value_data (struct value_data *);
106590075Sobrien#endif
106690075Sobrien
1067169689Skan/* Kill register REGNO.  This involves removing it from any value
1068169689Skan   lists, and resetting the value mode to VOIDmode.  This is only a
1069169689Skan   helper function; it does not handle any hard registers overlapping
1070169689Skan   with REGNO.  */
107190075Sobrien
107290075Sobrienstatic void
1073169689Skankill_value_one_regno (unsigned int regno, struct value_data *vd)
107490075Sobrien{
107590075Sobrien  unsigned int i, next;
107690075Sobrien
107790075Sobrien  if (vd->e[regno].oldest_regno != regno)
107890075Sobrien    {
107990075Sobrien      for (i = vd->e[regno].oldest_regno;
108090075Sobrien	   vd->e[i].next_regno != regno;
108190075Sobrien	   i = vd->e[i].next_regno)
108290075Sobrien	continue;
108390075Sobrien      vd->e[i].next_regno = vd->e[regno].next_regno;
108490075Sobrien    }
108590075Sobrien  else if ((next = vd->e[regno].next_regno) != INVALID_REGNUM)
108690075Sobrien    {
108790075Sobrien      for (i = next; i != INVALID_REGNUM; i = vd->e[i].next_regno)
1088117395Skan	vd->e[i].oldest_regno = next;
108990075Sobrien    }
109090075Sobrien
109190075Sobrien  vd->e[regno].mode = VOIDmode;
109290075Sobrien  vd->e[regno].oldest_regno = regno;
109390075Sobrien  vd->e[regno].next_regno = INVALID_REGNUM;
109490075Sobrien
109590075Sobrien#ifdef ENABLE_CHECKING
109690075Sobrien  validate_value_data (vd);
109790075Sobrien#endif
109890075Sobrien}
109990075Sobrien
1100169689Skan/* Kill the value in register REGNO for NREGS, and any other registers
1101169689Skan   whose values overlap.  */
1102169689Skan
1103169689Skanstatic void
1104169689Skankill_value_regno (unsigned int regno, unsigned int nregs,
1105169689Skan		  struct value_data *vd)
1106169689Skan{
1107169689Skan  unsigned int j;
1108169689Skan
1109169689Skan  /* Kill the value we're told to kill.  */
1110169689Skan  for (j = 0; j < nregs; ++j)
1111169689Skan    kill_value_one_regno (regno + j, vd);
1112169689Skan
1113169689Skan  /* Kill everything that overlapped what we're told to kill.  */
1114169689Skan  if (regno < vd->max_value_regs)
1115169689Skan    j = 0;
1116169689Skan  else
1117169689Skan    j = regno - vd->max_value_regs;
1118169689Skan  for (; j < regno; ++j)
1119169689Skan    {
1120169689Skan      unsigned int i, n;
1121169689Skan      if (vd->e[j].mode == VOIDmode)
1122169689Skan	continue;
1123169689Skan      n = hard_regno_nregs[j][vd->e[j].mode];
1124169689Skan      if (j + n > regno)
1125169689Skan	for (i = 0; i < n; ++i)
1126169689Skan	  kill_value_one_regno (j + i, vd);
1127169689Skan    }
1128169689Skan}
1129169689Skan
1130169689Skan/* Kill X.  This is a convenience function wrapping kill_value_regno
113190075Sobrien   so that we mind the mode the register is in.  */
113290075Sobrien
113390075Sobrienstatic void
1134132718Skankill_value (rtx x, struct value_data *vd)
113590075Sobrien{
1136169689Skan  rtx orig_rtx = x;
113796263Sobrien
113896263Sobrien  if (GET_CODE (x) == SUBREG)
1139169689Skan    {
1140169689Skan      x = simplify_subreg (GET_MODE (x), SUBREG_REG (x),
1141169689Skan			   GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
1142169689Skan      if (x == NULL_RTX)
1143169689Skan	x = SUBREG_REG (orig_rtx);
1144169689Skan    }
114590075Sobrien  if (REG_P (x))
114690075Sobrien    {
114790075Sobrien      unsigned int regno = REGNO (x);
1148169689Skan      unsigned int n = hard_regno_nregs[regno][GET_MODE (x)];
114990075Sobrien
1150169689Skan      kill_value_regno (regno, n, vd);
115190075Sobrien    }
115290075Sobrien}
115390075Sobrien
115490075Sobrien/* Remember that REGNO is valid in MODE.  */
115590075Sobrien
115690075Sobrienstatic void
1157132718Skanset_value_regno (unsigned int regno, enum machine_mode mode,
1158132718Skan		 struct value_data *vd)
115990075Sobrien{
116090075Sobrien  unsigned int nregs;
116190075Sobrien
116290075Sobrien  vd->e[regno].mode = mode;
116390075Sobrien
1164169689Skan  nregs = hard_regno_nregs[regno][mode];
116590075Sobrien  if (nregs > vd->max_value_regs)
116690075Sobrien    vd->max_value_regs = nregs;
116790075Sobrien}
116890075Sobrien
116990075Sobrien/* Initialize VD such that there are no known relationships between regs.  */
117090075Sobrien
117190075Sobrienstatic void
1172132718Skaninit_value_data (struct value_data *vd)
117390075Sobrien{
117490075Sobrien  int i;
117590075Sobrien  for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
117690075Sobrien    {
117790075Sobrien      vd->e[i].mode = VOIDmode;
117890075Sobrien      vd->e[i].oldest_regno = i;
117990075Sobrien      vd->e[i].next_regno = INVALID_REGNUM;
118090075Sobrien    }
118190075Sobrien  vd->max_value_regs = 0;
118290075Sobrien}
118390075Sobrien
118490075Sobrien/* Called through note_stores.  If X is clobbered, kill its value.  */
118590075Sobrien
118690075Sobrienstatic void
1187132718Skankill_clobbered_value (rtx x, rtx set, void *data)
118890075Sobrien{
118990075Sobrien  struct value_data *vd = data;
119090075Sobrien  if (GET_CODE (set) == CLOBBER)
119190075Sobrien    kill_value (x, vd);
119290075Sobrien}
119390075Sobrien
1194117395Skan/* Called through note_stores.  If X is set, not clobbered, kill its
119590075Sobrien   current value and install it as the root of its own value list.  */
119690075Sobrien
119790075Sobrienstatic void
1198132718Skankill_set_value (rtx x, rtx set, void *data)
119990075Sobrien{
120090075Sobrien  struct value_data *vd = data;
120196263Sobrien  if (GET_CODE (set) != CLOBBER)
120290075Sobrien    {
120390075Sobrien      kill_value (x, vd);
120496263Sobrien      if (REG_P (x))
1205117395Skan	set_value_regno (REGNO (x), GET_MODE (x), vd);
120690075Sobrien    }
120790075Sobrien}
120890075Sobrien
120990075Sobrien/* Called through for_each_rtx.  Kill any register used as the base of an
121090075Sobrien   auto-increment expression, and install that register as the root of its
121190075Sobrien   own value list.  */
121290075Sobrien
121390075Sobrienstatic int
1214132718Skankill_autoinc_value (rtx *px, void *data)
121590075Sobrien{
121690075Sobrien  rtx x = *px;
121790075Sobrien  struct value_data *vd = data;
121890075Sobrien
1219169689Skan  if (GET_RTX_CLASS (GET_CODE (x)) == RTX_AUTOINC)
122090075Sobrien    {
122190075Sobrien      x = XEXP (x, 0);
122290075Sobrien      kill_value (x, vd);
122390075Sobrien      set_value_regno (REGNO (x), Pmode, vd);
122490075Sobrien      return -1;
122590075Sobrien    }
122690075Sobrien
122790075Sobrien  return 0;
122890075Sobrien}
122990075Sobrien
123090075Sobrien/* Assert that SRC has been copied to DEST.  Adjust the data structures
123190075Sobrien   to reflect that SRC contains an older copy of the shared value.  */
123290075Sobrien
123390075Sobrienstatic void
1234132718Skancopy_value (rtx dest, rtx src, struct value_data *vd)
123590075Sobrien{
123690075Sobrien  unsigned int dr = REGNO (dest);
123790075Sobrien  unsigned int sr = REGNO (src);
123890075Sobrien  unsigned int dn, sn;
123990075Sobrien  unsigned int i;
124090075Sobrien
124190075Sobrien  /* ??? At present, it's possible to see noop sets.  It'd be nice if
124290075Sobrien     this were cleaned up beforehand...  */
124390075Sobrien  if (sr == dr)
124490075Sobrien    return;
124590075Sobrien
124690075Sobrien  /* Do not propagate copies to the stack pointer, as that can leave
1247117395Skan     memory accesses with no scheduling dependency on the stack update.  */
124890075Sobrien  if (dr == STACK_POINTER_REGNUM)
124990075Sobrien    return;
125090075Sobrien
125190075Sobrien  /* Likewise with the frame pointer, if we're using one.  */
125290075Sobrien  if (frame_pointer_needed && dr == HARD_FRAME_POINTER_REGNUM)
125390075Sobrien    return;
125490075Sobrien
1255169689Skan  /* Do not propagate copies to fixed or global registers, patterns
1256169689Skan     can be relying to see particular fixed register or users can
1257169689Skan     expect the chosen global register in asm.  */
1258169689Skan  if (fixed_regs[dr] || global_regs[dr])
1259169689Skan    return;
1260169689Skan
126190075Sobrien  /* If SRC and DEST overlap, don't record anything.  */
1262169689Skan  dn = hard_regno_nregs[dr][GET_MODE (dest)];
1263169689Skan  sn = hard_regno_nregs[sr][GET_MODE (dest)];
126490075Sobrien  if ((dr > sr && dr < sr + sn)
126590075Sobrien      || (sr > dr && sr < dr + dn))
126690075Sobrien    return;
126790075Sobrien
126890075Sobrien  /* If SRC had no assigned mode (i.e. we didn't know it was live)
126990075Sobrien     assign it now and assume the value came from an input argument
127090075Sobrien     or somesuch.  */
127190075Sobrien  if (vd->e[sr].mode == VOIDmode)
127290075Sobrien    set_value_regno (sr, vd->e[dr].mode, vd);
127390075Sobrien
1274117395Skan  /* If we are narrowing the input to a smaller number of hard regs,
1275117395Skan     and it is in big endian, we are really extracting a high part.
1276117395Skan     Since we generally associate a low part of a value with the value itself,
1277117395Skan     we must not do the same for the high part.
1278117395Skan     Note we can still get low parts for the same mode combination through
1279117395Skan     a two-step copy involving differently sized hard regs.
1280117395Skan     Assume hard regs fr* are 32 bits bits each, while r* are 64 bits each:
1281117395Skan     (set (reg:DI r0) (reg:DI fr0))
1282117395Skan     (set (reg:SI fr2) (reg:SI r0))
1283117395Skan     loads the low part of (reg:DI fr0) - i.e. fr1 - into fr2, while:
1284117395Skan     (set (reg:SI fr2) (reg:SI fr0))
1285117395Skan     loads the high part of (reg:DI fr0) into fr2.
1286117395Skan
1287117395Skan     We can't properly represent the latter case in our tables, so don't
1288117395Skan     record anything then.  */
1289169689Skan  else if (sn < (unsigned int) hard_regno_nregs[sr][vd->e[sr].mode]
1290117395Skan	   && (GET_MODE_SIZE (vd->e[sr].mode) > UNITS_PER_WORD
1291117395Skan	       ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
1292117395Skan    return;
1293117395Skan
129490075Sobrien  /* If SRC had been assigned a mode narrower than the copy, we can't
129590075Sobrien     link DEST into the chain, because not all of the pieces of the
129690075Sobrien     copy came from oldest_regno.  */
1297169689Skan  else if (sn > (unsigned int) hard_regno_nregs[sr][vd->e[sr].mode])
129890075Sobrien    return;
129990075Sobrien
130090075Sobrien  /* Link DR at the end of the value chain used by SR.  */
130190075Sobrien
130290075Sobrien  vd->e[dr].oldest_regno = vd->e[sr].oldest_regno;
130390075Sobrien
130490075Sobrien  for (i = sr; vd->e[i].next_regno != INVALID_REGNUM; i = vd->e[i].next_regno)
130590075Sobrien    continue;
130690075Sobrien  vd->e[i].next_regno = dr;
130790075Sobrien
130890075Sobrien#ifdef ENABLE_CHECKING
130990075Sobrien  validate_value_data (vd);
131090075Sobrien#endif
131190075Sobrien}
131290075Sobrien
131390075Sobrien/* Return true if a mode change from ORIG to NEW is allowed for REGNO.  */
131490075Sobrien
131590075Sobrienstatic bool
1316132718Skanmode_change_ok (enum machine_mode orig_mode, enum machine_mode new_mode,
1317132718Skan		unsigned int regno ATTRIBUTE_UNUSED)
131890075Sobrien{
131990075Sobrien  if (GET_MODE_SIZE (orig_mode) < GET_MODE_SIZE (new_mode))
132090075Sobrien    return false;
132190075Sobrien
1322117395Skan#ifdef CANNOT_CHANGE_MODE_CLASS
1323117395Skan  return !REG_CANNOT_CHANGE_MODE_P (regno, orig_mode, new_mode);
132490075Sobrien#endif
132590075Sobrien
132690075Sobrien  return true;
132790075Sobrien}
132890075Sobrien
1329117395Skan/* Register REGNO was originally set in ORIG_MODE.  It - or a copy of it -
1330117395Skan   was copied in COPY_MODE to COPY_REGNO, and then COPY_REGNO was accessed
1331117395Skan   in NEW_MODE.
1332117395Skan   Return a NEW_MODE rtx for REGNO if that's OK, otherwise return NULL_RTX.  */
1333117395Skan
1334117395Skanstatic rtx
1335132718Skanmaybe_mode_change (enum machine_mode orig_mode, enum machine_mode copy_mode,
1336132718Skan		   enum machine_mode new_mode, unsigned int regno,
1337132718Skan		   unsigned int copy_regno ATTRIBUTE_UNUSED)
1338117395Skan{
1339117395Skan  if (orig_mode == new_mode)
1340117395Skan    return gen_rtx_raw_REG (new_mode, regno);
1341117395Skan  else if (mode_change_ok (orig_mode, new_mode, regno))
1342117395Skan    {
1343169689Skan      int copy_nregs = hard_regno_nregs[copy_regno][copy_mode];
1344169689Skan      int use_nregs = hard_regno_nregs[copy_regno][new_mode];
1345117395Skan      int copy_offset
1346117395Skan	= GET_MODE_SIZE (copy_mode) / copy_nregs * (copy_nregs - use_nregs);
1347117395Skan      int offset
1348117395Skan	= GET_MODE_SIZE (orig_mode) - GET_MODE_SIZE (new_mode) - copy_offset;
1349117395Skan      int byteoffset = offset % UNITS_PER_WORD;
1350117395Skan      int wordoffset = offset - byteoffset;
1351117395Skan
1352117395Skan      offset = ((WORDS_BIG_ENDIAN ? wordoffset : 0)
1353117395Skan		+ (BYTES_BIG_ENDIAN ? byteoffset : 0));
1354117395Skan      return gen_rtx_raw_REG (new_mode,
1355117395Skan			      regno + subreg_regno_offset (regno, orig_mode,
1356117395Skan							   offset,
1357117395Skan							   new_mode));
1358117395Skan    }
1359117395Skan  return NULL_RTX;
1360117395Skan}
1361117395Skan
136290075Sobrien/* Find the oldest copy of the value contained in REGNO that is in
1363169689Skan   register class CL and has mode MODE.  If found, return an rtx
136490075Sobrien   of that oldest register, otherwise return NULL.  */
136590075Sobrien
136690075Sobrienstatic rtx
1367169689Skanfind_oldest_value_reg (enum reg_class cl, rtx reg, struct value_data *vd)
136890075Sobrien{
136990075Sobrien  unsigned int regno = REGNO (reg);
137090075Sobrien  enum machine_mode mode = GET_MODE (reg);
137190075Sobrien  unsigned int i;
137290075Sobrien
137390075Sobrien  /* If we are accessing REG in some mode other that what we set it in,
137490075Sobrien     make sure that the replacement is valid.  In particular, consider
137590075Sobrien	(set (reg:DI r11) (...))
137690075Sobrien	(set (reg:SI r9) (reg:SI r11))
137790075Sobrien	(set (reg:SI r10) (...))
137890075Sobrien	(set (...) (reg:DI r9))
137990075Sobrien     Replacing r9 with r11 is invalid.  */
138090075Sobrien  if (mode != vd->e[regno].mode)
138190075Sobrien    {
1382169689Skan      if (hard_regno_nregs[regno][mode]
1383169689Skan	  > hard_regno_nregs[regno][vd->e[regno].mode])
138490075Sobrien	return NULL_RTX;
138590075Sobrien    }
138690075Sobrien
138790075Sobrien  for (i = vd->e[regno].oldest_regno; i != regno; i = vd->e[i].next_regno)
1388117395Skan    {
1389117395Skan      enum machine_mode oldmode = vd->e[i].mode;
1390117395Skan      rtx new;
1391132718Skan      unsigned int last;
1392117395Skan
1393169689Skan      for (last = i; last < i + hard_regno_nregs[i][mode]; last++)
1394169689Skan	if (!TEST_HARD_REG_BIT (reg_class_contents[cl], last))
1395132718Skan	  return NULL_RTX;
1396132718Skan
1397132718Skan      new = maybe_mode_change (oldmode, vd->e[regno].mode, mode, i, regno);
1398132718Skan      if (new)
1399132718Skan	{
1400132718Skan	  ORIGINAL_REGNO (new) = ORIGINAL_REGNO (reg);
1401132718Skan	  REG_ATTRS (new) = REG_ATTRS (reg);
1402132718Skan	  return new;
1403132718Skan	}
1404117395Skan    }
140590075Sobrien
140690075Sobrien  return NULL_RTX;
140790075Sobrien}
140890075Sobrien
140990075Sobrien/* If possible, replace the register at *LOC with the oldest register
1410169689Skan   in register class CL.  Return true if successfully replaced.  */
141190075Sobrien
141290075Sobrienstatic bool
1413169689Skanreplace_oldest_value_reg (rtx *loc, enum reg_class cl, rtx insn,
1414132718Skan			  struct value_data *vd)
141590075Sobrien{
1416169689Skan  rtx new = find_oldest_value_reg (cl, *loc, vd);
141790075Sobrien  if (new)
141890075Sobrien    {
1419169689Skan      if (dump_file)
1420169689Skan	fprintf (dump_file, "insn %u: replaced reg %u with %u\n",
142190075Sobrien		 INSN_UID (insn), REGNO (*loc), REGNO (new));
142290075Sobrien
1423169689Skan      validate_change (insn, loc, new, 1);
142490075Sobrien      return true;
142590075Sobrien    }
142690075Sobrien  return false;
142790075Sobrien}
142890075Sobrien
142990075Sobrien/* Similar to replace_oldest_value_reg, but *LOC contains an address.
1430169689Skan   Adapted from find_reloads_address_1.  CL is INDEX_REG_CLASS or
143190075Sobrien   BASE_REG_CLASS depending on how the register is being considered.  */
143290075Sobrien
143390075Sobrienstatic bool
1434169689Skanreplace_oldest_value_addr (rtx *loc, enum reg_class cl,
1435132718Skan			   enum machine_mode mode, rtx insn,
1436132718Skan			   struct value_data *vd)
143790075Sobrien{
143890075Sobrien  rtx x = *loc;
143990075Sobrien  RTX_CODE code = GET_CODE (x);
144090075Sobrien  const char *fmt;
144190075Sobrien  int i, j;
144290075Sobrien  bool changed = false;
144390075Sobrien
144490075Sobrien  switch (code)
144590075Sobrien    {
144690075Sobrien    case PLUS:
144790075Sobrien      {
144890075Sobrien	rtx orig_op0 = XEXP (x, 0);
144990075Sobrien	rtx orig_op1 = XEXP (x, 1);
145090075Sobrien	RTX_CODE code0 = GET_CODE (orig_op0);
145190075Sobrien	RTX_CODE code1 = GET_CODE (orig_op1);
145290075Sobrien	rtx op0 = orig_op0;
145390075Sobrien	rtx op1 = orig_op1;
145490075Sobrien	rtx *locI = NULL;
145590075Sobrien	rtx *locB = NULL;
1456169689Skan	enum rtx_code index_code = SCRATCH;
145790075Sobrien
145890075Sobrien	if (GET_CODE (op0) == SUBREG)
145990075Sobrien	  {
146090075Sobrien	    op0 = SUBREG_REG (op0);
146190075Sobrien	    code0 = GET_CODE (op0);
146290075Sobrien	  }
146390075Sobrien
146490075Sobrien	if (GET_CODE (op1) == SUBREG)
146590075Sobrien	  {
146690075Sobrien	    op1 = SUBREG_REG (op1);
146790075Sobrien	    code1 = GET_CODE (op1);
146890075Sobrien	  }
146990075Sobrien
147090075Sobrien	if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
147190075Sobrien	    || code0 == ZERO_EXTEND || code1 == MEM)
147290075Sobrien	  {
147390075Sobrien	    locI = &XEXP (x, 0);
147490075Sobrien	    locB = &XEXP (x, 1);
1475169689Skan	    index_code = GET_CODE (*locI);
147690075Sobrien	  }
147790075Sobrien	else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
147890075Sobrien		 || code1 == ZERO_EXTEND || code0 == MEM)
147990075Sobrien	  {
148090075Sobrien	    locI = &XEXP (x, 1);
148190075Sobrien	    locB = &XEXP (x, 0);
1482169689Skan	    index_code = GET_CODE (*locI);
148390075Sobrien	  }
148490075Sobrien	else if (code0 == CONST_INT || code0 == CONST
148590075Sobrien		 || code0 == SYMBOL_REF || code0 == LABEL_REF)
1486169689Skan	  {
1487169689Skan	    locB = &XEXP (x, 1);
1488169689Skan	    index_code = GET_CODE (XEXP (x, 0));
1489169689Skan	  }
149090075Sobrien	else if (code1 == CONST_INT || code1 == CONST
149190075Sobrien		 || code1 == SYMBOL_REF || code1 == LABEL_REF)
1492169689Skan	  {
1493169689Skan	    locB = &XEXP (x, 0);
1494169689Skan	    index_code = GET_CODE (XEXP (x, 1));
1495169689Skan	  }
149690075Sobrien	else if (code0 == REG && code1 == REG)
149790075Sobrien	  {
149890075Sobrien	    int index_op;
1499169689Skan	    unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
150090075Sobrien
1501169689Skan	    if (REGNO_OK_FOR_INDEX_P (regno0)
1502169689Skan		&& regno_ok_for_base_p (regno1, mode, PLUS, REG))
150390075Sobrien	      index_op = 0;
1504169689Skan	    else if (REGNO_OK_FOR_INDEX_P (regno1)
1505169689Skan		     && regno_ok_for_base_p (regno0, mode, PLUS, REG))
150690075Sobrien	      index_op = 1;
1507169689Skan	    else if (regno_ok_for_base_p (regno1, mode, PLUS, REG))
150890075Sobrien	      index_op = 0;
1509169689Skan	    else if (regno_ok_for_base_p (regno0, mode, PLUS, REG))
151090075Sobrien	      index_op = 1;
1511169689Skan	    else if (REGNO_OK_FOR_INDEX_P (regno1))
151290075Sobrien	      index_op = 1;
151390075Sobrien	    else
151490075Sobrien	      index_op = 0;
151590075Sobrien
151690075Sobrien	    locI = &XEXP (x, index_op);
151790075Sobrien	    locB = &XEXP (x, !index_op);
1518169689Skan	    index_code = GET_CODE (*locI);
151990075Sobrien	  }
152090075Sobrien	else if (code0 == REG)
152190075Sobrien	  {
152290075Sobrien	    locI = &XEXP (x, 0);
152390075Sobrien	    locB = &XEXP (x, 1);
1524169689Skan	    index_code = GET_CODE (*locI);
152590075Sobrien	  }
152690075Sobrien	else if (code1 == REG)
152790075Sobrien	  {
152890075Sobrien	    locI = &XEXP (x, 1);
152990075Sobrien	    locB = &XEXP (x, 0);
1530169689Skan	    index_code = GET_CODE (*locI);
153190075Sobrien	  }
153290075Sobrien
153390075Sobrien	if (locI)
153490075Sobrien	  changed |= replace_oldest_value_addr (locI, INDEX_REG_CLASS, mode,
1535117395Skan						insn, vd);
153690075Sobrien	if (locB)
153790075Sobrien	  changed |= replace_oldest_value_addr (locB,
1538169689Skan						base_reg_class (mode, PLUS,
1539169689Skan								index_code),
154090075Sobrien						mode, insn, vd);
154190075Sobrien	return changed;
154290075Sobrien      }
154390075Sobrien
154490075Sobrien    case POST_INC:
154590075Sobrien    case POST_DEC:
154690075Sobrien    case POST_MODIFY:
154790075Sobrien    case PRE_INC:
154890075Sobrien    case PRE_DEC:
154990075Sobrien    case PRE_MODIFY:
155090075Sobrien      return false;
155190075Sobrien
155290075Sobrien    case MEM:
155390075Sobrien      return replace_oldest_value_mem (x, insn, vd);
155490075Sobrien
155590075Sobrien    case REG:
1556169689Skan      return replace_oldest_value_reg (loc, cl, insn, vd);
155790075Sobrien
155890075Sobrien    default:
155990075Sobrien      break;
156090075Sobrien    }
156190075Sobrien
156290075Sobrien  fmt = GET_RTX_FORMAT (code);
156390075Sobrien  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
156490075Sobrien    {
156590075Sobrien      if (fmt[i] == 'e')
1566169689Skan	changed |= replace_oldest_value_addr (&XEXP (x, i), cl, mode,
156790075Sobrien					      insn, vd);
156890075Sobrien      else if (fmt[i] == 'E')
156990075Sobrien	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1570169689Skan	  changed |= replace_oldest_value_addr (&XVECEXP (x, i, j), cl,
1571117395Skan						mode, insn, vd);
157290075Sobrien    }
157390075Sobrien
157490075Sobrien  return changed;
157590075Sobrien}
157690075Sobrien
157790075Sobrien/* Similar to replace_oldest_value_reg, but X contains a memory.  */
157890075Sobrien
157990075Sobrienstatic bool
1580132718Skanreplace_oldest_value_mem (rtx x, rtx insn, struct value_data *vd)
158190075Sobrien{
158290075Sobrien  return replace_oldest_value_addr (&XEXP (x, 0),
1583169689Skan				    base_reg_class (GET_MODE (x), MEM,
1584169689Skan						    SCRATCH),
158590075Sobrien				    GET_MODE (x), insn, vd);
158690075Sobrien}
158790075Sobrien
158890075Sobrien/* Perform the forward copy propagation on basic block BB.  */
158990075Sobrien
159090075Sobrienstatic bool
1591132718Skancopyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
159290075Sobrien{
159390075Sobrien  bool changed = false;
159490075Sobrien  rtx insn;
159590075Sobrien
1596132718Skan  for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
159790075Sobrien    {
159890075Sobrien      int n_ops, i, alt, predicated;
1599169689Skan      bool is_asm, any_replacements;
160090075Sobrien      rtx set;
1601169689Skan      bool replaced[MAX_RECOG_OPERANDS];
160290075Sobrien
160390075Sobrien      if (! INSN_P (insn))
160490075Sobrien	{
1605132718Skan	  if (insn == BB_END (bb))
160690075Sobrien	    break;
160790075Sobrien	  else
160890075Sobrien	    continue;
160990075Sobrien	}
161090075Sobrien
161190075Sobrien      set = single_set (insn);
161290075Sobrien      extract_insn (insn);
1613117395Skan      if (! constrain_operands (1))
1614117395Skan	fatal_insn_not_found (insn);
161590075Sobrien      preprocess_constraints ();
161690075Sobrien      alt = which_alternative;
161790075Sobrien      n_ops = recog_data.n_operands;
161890075Sobrien      is_asm = asm_noperands (PATTERN (insn)) >= 0;
161990075Sobrien
162090075Sobrien      /* Simplify the code below by rewriting things to reflect
162190075Sobrien	 matching constraints.  Also promote OP_OUT to OP_INOUT
162290075Sobrien	 in predicated instructions.  */
162390075Sobrien
162490075Sobrien      predicated = GET_CODE (PATTERN (insn)) == COND_EXEC;
162590075Sobrien      for (i = 0; i < n_ops; ++i)
162690075Sobrien	{
162790075Sobrien	  int matches = recog_op_alt[i][alt].matches;
162890075Sobrien	  if (matches >= 0)
1629169689Skan	    recog_op_alt[i][alt].cl = recog_op_alt[matches][alt].cl;
163090075Sobrien	  if (matches >= 0 || recog_op_alt[i][alt].matched >= 0
163190075Sobrien	      || (predicated && recog_data.operand_type[i] == OP_OUT))
163290075Sobrien	    recog_data.operand_type[i] = OP_INOUT;
163390075Sobrien	}
163490075Sobrien
163590075Sobrien      /* For each earlyclobber operand, zap the value data.  */
163690075Sobrien      for (i = 0; i < n_ops; i++)
163790075Sobrien	if (recog_op_alt[i][alt].earlyclobber)
163890075Sobrien	  kill_value (recog_data.operand[i], vd);
163990075Sobrien
164090075Sobrien      /* Within asms, a clobber cannot overlap inputs or outputs.
164190075Sobrien	 I wouldn't think this were true for regular insns, but
164290075Sobrien	 scan_rtx treats them like that...  */
164390075Sobrien      note_stores (PATTERN (insn), kill_clobbered_value, vd);
164490075Sobrien
164590075Sobrien      /* Kill all auto-incremented values.  */
164690075Sobrien      /* ??? REG_INC is useless, since stack pushes aren't done that way.  */
164790075Sobrien      for_each_rtx (&PATTERN (insn), kill_autoinc_value, vd);
164890075Sobrien
164990075Sobrien      /* Kill all early-clobbered operands.  */
165090075Sobrien      for (i = 0; i < n_ops; i++)
165190075Sobrien	if (recog_op_alt[i][alt].earlyclobber)
165290075Sobrien	  kill_value (recog_data.operand[i], vd);
165390075Sobrien
165490075Sobrien      /* Special-case plain move instructions, since we may well
165590075Sobrien	 be able to do the move from a different register class.  */
165690075Sobrien      if (set && REG_P (SET_SRC (set)))
165790075Sobrien	{
165890075Sobrien	  rtx src = SET_SRC (set);
165990075Sobrien	  unsigned int regno = REGNO (src);
166090075Sobrien	  enum machine_mode mode = GET_MODE (src);
166190075Sobrien	  unsigned int i;
166290075Sobrien	  rtx new;
166390075Sobrien
166490075Sobrien	  /* If we are accessing SRC in some mode other that what we
166590075Sobrien	     set it in, make sure that the replacement is valid.  */
166690075Sobrien	  if (mode != vd->e[regno].mode)
166790075Sobrien	    {
1668169689Skan	      if (hard_regno_nregs[regno][mode]
1669169689Skan		  > hard_regno_nregs[regno][vd->e[regno].mode])
167090075Sobrien		goto no_move_special_case;
167190075Sobrien	    }
167290075Sobrien
167390075Sobrien	  /* If the destination is also a register, try to find a source
167490075Sobrien	     register in the same class.  */
167590075Sobrien	  if (REG_P (SET_DEST (set)))
167690075Sobrien	    {
167790075Sobrien	      new = find_oldest_value_reg (REGNO_REG_CLASS (regno), src, vd);
167890075Sobrien	      if (new && validate_change (insn, &SET_SRC (set), new, 0))
167990075Sobrien		{
1680169689Skan		  if (dump_file)
1681169689Skan		    fprintf (dump_file,
168290075Sobrien			     "insn %u: replaced reg %u with %u\n",
168390075Sobrien			     INSN_UID (insn), regno, REGNO (new));
1684117395Skan		  changed = true;
168590075Sobrien		  goto did_replacement;
168690075Sobrien		}
168790075Sobrien	    }
168890075Sobrien
168990075Sobrien	  /* Otherwise, try all valid registers and see if its valid.  */
169090075Sobrien	  for (i = vd->e[regno].oldest_regno; i != regno;
169190075Sobrien	       i = vd->e[i].next_regno)
1692117395Skan	    {
1693117395Skan	      new = maybe_mode_change (vd->e[i].mode, vd->e[regno].mode,
1694117395Skan				       mode, i, regno);
1695117395Skan	      if (new != NULL_RTX)
1696117395Skan		{
1697117395Skan		  if (validate_change (insn, &SET_SRC (set), new, 0))
1698117395Skan		    {
1699117395Skan		      ORIGINAL_REGNO (new) = ORIGINAL_REGNO (src);
1700132718Skan		      REG_ATTRS (new) = REG_ATTRS (src);
1701169689Skan		      if (dump_file)
1702169689Skan			fprintf (dump_file,
1703117395Skan				 "insn %u: replaced reg %u with %u\n",
1704117395Skan				 INSN_UID (insn), regno, REGNO (new));
1705117395Skan		      changed = true;
1706117395Skan		      goto did_replacement;
1707117395Skan		    }
1708117395Skan		}
1709117395Skan	    }
171090075Sobrien	}
171190075Sobrien      no_move_special_case:
171290075Sobrien
1713169689Skan      any_replacements = false;
1714169689Skan
171590075Sobrien      /* For each input operand, replace a hard register with the
171690075Sobrien	 eldest live copy that's in an appropriate register class.  */
171790075Sobrien      for (i = 0; i < n_ops; i++)
171890075Sobrien	{
1719169689Skan	  replaced[i] = false;
172090075Sobrien
172190075Sobrien	  /* Don't scan match_operand here, since we've no reg class
172290075Sobrien	     information to pass down.  Any operands that we could
172390075Sobrien	     substitute in will be represented elsewhere.  */
172490075Sobrien	  if (recog_data.constraints[i][0] == '\0')
172590075Sobrien	    continue;
172690075Sobrien
172790075Sobrien	  /* Don't replace in asms intentionally referencing hard regs.  */
1728169689Skan	  if (is_asm && REG_P (recog_data.operand[i])
172990075Sobrien	      && (REGNO (recog_data.operand[i])
173090075Sobrien		  == ORIGINAL_REGNO (recog_data.operand[i])))
173190075Sobrien	    continue;
173290075Sobrien
173390075Sobrien	  if (recog_data.operand_type[i] == OP_IN)
173490075Sobrien	    {
173590075Sobrien	      if (recog_op_alt[i][alt].is_address)
1736169689Skan		replaced[i]
173790075Sobrien		  = replace_oldest_value_addr (recog_data.operand_loc[i],
1738169689Skan					       recog_op_alt[i][alt].cl,
173990075Sobrien					       VOIDmode, insn, vd);
174090075Sobrien	      else if (REG_P (recog_data.operand[i]))
1741169689Skan		replaced[i]
174290075Sobrien		  = replace_oldest_value_reg (recog_data.operand_loc[i],
1743169689Skan					      recog_op_alt[i][alt].cl,
174490075Sobrien					      insn, vd);
1745169689Skan	      else if (MEM_P (recog_data.operand[i]))
1746169689Skan		replaced[i] = replace_oldest_value_mem (recog_data.operand[i],
1747169689Skan							insn, vd);
174890075Sobrien	    }
1749169689Skan	  else if (MEM_P (recog_data.operand[i]))
1750169689Skan	    replaced[i] = replace_oldest_value_mem (recog_data.operand[i],
1751169689Skan						    insn, vd);
175290075Sobrien
175390075Sobrien	  /* If we performed any replacement, update match_dups.  */
1754169689Skan	  if (replaced[i])
175590075Sobrien	    {
175690075Sobrien	      int j;
175790075Sobrien	      rtx new;
175890075Sobrien
175990075Sobrien	      new = *recog_data.operand_loc[i];
176090075Sobrien	      recog_data.operand[i] = new;
176190075Sobrien	      for (j = 0; j < recog_data.n_dups; j++)
176290075Sobrien		if (recog_data.dup_num[j] == i)
1763169689Skan		  validate_change (insn, recog_data.dup_loc[j], new, 1);
1764169689Skan
1765169689Skan	      any_replacements = true;
176690075Sobrien	    }
176790075Sobrien	}
176890075Sobrien
1769169689Skan      if (any_replacements)
1770169689Skan	{
1771169689Skan	  if (! apply_change_group ())
1772169689Skan	    {
1773169689Skan	      for (i = 0; i < n_ops; i++)
1774169689Skan		if (replaced[i])
1775169689Skan		  {
1776169689Skan		    rtx old = *recog_data.operand_loc[i];
1777169689Skan		    recog_data.operand[i] = old;
1778169689Skan		  }
1779169689Skan
1780169689Skan	      if (dump_file)
1781169689Skan		fprintf (dump_file,
1782169689Skan			 "insn %u: reg replacements not verified\n",
1783169689Skan			 INSN_UID (insn));
1784169689Skan	    }
1785169689Skan	  else
1786169689Skan	    changed = true;
1787169689Skan	}
1788169689Skan
178990075Sobrien    did_replacement:
179090075Sobrien      /* Clobber call-clobbered registers.  */
1791169689Skan      if (CALL_P (insn))
179290075Sobrien	for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
179390075Sobrien	  if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
1794169689Skan	    kill_value_regno (i, 1, vd);
179590075Sobrien
179690075Sobrien      /* Notice stores.  */
179790075Sobrien      note_stores (PATTERN (insn), kill_set_value, vd);
179890075Sobrien
179990075Sobrien      /* Notice copies.  */
180090075Sobrien      if (set && REG_P (SET_DEST (set)) && REG_P (SET_SRC (set)))
180190075Sobrien	copy_value (SET_DEST (set), SET_SRC (set), vd);
180290075Sobrien
1803132718Skan      if (insn == BB_END (bb))
180490075Sobrien	break;
180590075Sobrien    }
180690075Sobrien
180790075Sobrien  return changed;
180890075Sobrien}
180990075Sobrien
181090075Sobrien/* Main entry point for the forward copy propagation optimization.  */
181190075Sobrien
1812169689Skanstatic void
1813132718Skancopyprop_hardreg_forward (void)
181490075Sobrien{
181590075Sobrien  struct value_data *all_vd;
181690075Sobrien  bool need_refresh;
1817169689Skan  basic_block bb;
1818169689Skan  sbitmap visited;
181990075Sobrien
182090075Sobrien  need_refresh = false;
182190075Sobrien
1822169689Skan  all_vd = XNEWVEC (struct value_data, last_basic_block);
182390075Sobrien
1824169689Skan  visited = sbitmap_alloc (last_basic_block);
1825169689Skan  sbitmap_zero (visited);
1826169689Skan
1827117395Skan  FOR_EACH_BB (bb)
182890075Sobrien    {
1829169689Skan      SET_BIT (visited, bb->index);
1830169689Skan
183190075Sobrien      /* If a block has a single predecessor, that we've already
183290075Sobrien	 processed, begin with the value data that was live at
183390075Sobrien	 the end of the predecessor block.  */
1834132718Skan      /* ??? Ought to use more intelligent queuing of blocks.  */
1835169689Skan      if (single_pred_p (bb)
1836169689Skan	  && TEST_BIT (visited, single_pred (bb)->index)
1837169689Skan	  && ! (single_pred_edge (bb)->flags & (EDGE_ABNORMAL_CALL | EDGE_EH)))
1838169689Skan	all_vd[bb->index] = all_vd[single_pred (bb)->index];
183990075Sobrien      else
1840117395Skan	init_value_data (all_vd + bb->index);
184190075Sobrien
1842117395Skan      if (copyprop_hardreg_forward_1 (bb, all_vd + bb->index))
184390075Sobrien	need_refresh = true;
184490075Sobrien    }
184590075Sobrien
1846169689Skan  sbitmap_free (visited);
1847169689Skan
184890075Sobrien  if (need_refresh)
184990075Sobrien    {
1850169689Skan      if (dump_file)
1851169689Skan	fputs ("\n\n", dump_file);
185290075Sobrien
185390075Sobrien      /* ??? Irritatingly, delete_noop_moves does not take a set of blocks
185490075Sobrien	 to scan, so we have to do a life update with no initial set of
185590075Sobrien	 blocks Just In Case.  */
1856169689Skan      delete_noop_moves ();
185790075Sobrien      update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
185890075Sobrien			PROP_DEATH_NOTES
185990075Sobrien			| PROP_SCAN_DEAD_CODE
186090075Sobrien			| PROP_KILL_DEAD_CODE);
186190075Sobrien    }
186290075Sobrien
186390075Sobrien  free (all_vd);
186490075Sobrien}
186590075Sobrien
186690075Sobrien/* Dump the value chain data to stderr.  */
186790075Sobrien
186890075Sobrienvoid
1869132718Skandebug_value_data (struct value_data *vd)
187090075Sobrien{
187190075Sobrien  HARD_REG_SET set;
187290075Sobrien  unsigned int i, j;
187390075Sobrien
187490075Sobrien  CLEAR_HARD_REG_SET (set);
187590075Sobrien
187690075Sobrien  for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
187790075Sobrien    if (vd->e[i].oldest_regno == i)
187890075Sobrien      {
187990075Sobrien	if (vd->e[i].mode == VOIDmode)
188090075Sobrien	  {
188190075Sobrien	    if (vd->e[i].next_regno != INVALID_REGNUM)
188290075Sobrien	      fprintf (stderr, "[%u] Bad next_regno for empty chain (%u)\n",
188390075Sobrien		       i, vd->e[i].next_regno);
188490075Sobrien	    continue;
188590075Sobrien	  }
188690075Sobrien
188790075Sobrien	SET_HARD_REG_BIT (set, i);
188890075Sobrien	fprintf (stderr, "[%u %s] ", i, GET_MODE_NAME (vd->e[i].mode));
188990075Sobrien
189090075Sobrien	for (j = vd->e[i].next_regno;
189190075Sobrien	     j != INVALID_REGNUM;
189290075Sobrien	     j = vd->e[j].next_regno)
189390075Sobrien	  {
189490075Sobrien	    if (TEST_HARD_REG_BIT (set, j))
189590075Sobrien	      {
189690075Sobrien		fprintf (stderr, "[%u] Loop in regno chain\n", j);
189790075Sobrien		return;
189890075Sobrien	      }
189990075Sobrien
190090075Sobrien	    if (vd->e[j].oldest_regno != i)
190190075Sobrien	      {
190290075Sobrien		fprintf (stderr, "[%u] Bad oldest_regno (%u)\n",
190390075Sobrien			 j, vd->e[j].oldest_regno);
190490075Sobrien		return;
190590075Sobrien	      }
190690075Sobrien	    SET_HARD_REG_BIT (set, j);
190790075Sobrien	    fprintf (stderr, "[%u %s] ", j, GET_MODE_NAME (vd->e[j].mode));
190890075Sobrien	  }
190990075Sobrien	fputc ('\n', stderr);
191090075Sobrien      }
191190075Sobrien
191290075Sobrien  for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
191390075Sobrien    if (! TEST_HARD_REG_BIT (set, i)
191490075Sobrien	&& (vd->e[i].mode != VOIDmode
191590075Sobrien	    || vd->e[i].oldest_regno != i
191690075Sobrien	    || vd->e[i].next_regno != INVALID_REGNUM))
191790075Sobrien      fprintf (stderr, "[%u] Non-empty reg in chain (%s %u %i)\n",
191890075Sobrien	       i, GET_MODE_NAME (vd->e[i].mode), vd->e[i].oldest_regno,
191990075Sobrien	       vd->e[i].next_regno);
192090075Sobrien}
192190075Sobrien
192290075Sobrien#ifdef ENABLE_CHECKING
192390075Sobrienstatic void
1924132718Skanvalidate_value_data (struct value_data *vd)
192590075Sobrien{
192690075Sobrien  HARD_REG_SET set;
192790075Sobrien  unsigned int i, j;
192890075Sobrien
192990075Sobrien  CLEAR_HARD_REG_SET (set);
193090075Sobrien
193190075Sobrien  for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
193290075Sobrien    if (vd->e[i].oldest_regno == i)
193390075Sobrien      {
193490075Sobrien	if (vd->e[i].mode == VOIDmode)
193590075Sobrien	  {
193690075Sobrien	    if (vd->e[i].next_regno != INVALID_REGNUM)
193790075Sobrien	      internal_error ("validate_value_data: [%u] Bad next_regno for empty chain (%u)",
193890075Sobrien			      i, vd->e[i].next_regno);
193990075Sobrien	    continue;
194090075Sobrien	  }
194190075Sobrien
194290075Sobrien	SET_HARD_REG_BIT (set, i);
194390075Sobrien
194490075Sobrien	for (j = vd->e[i].next_regno;
194590075Sobrien	     j != INVALID_REGNUM;
194690075Sobrien	     j = vd->e[j].next_regno)
194790075Sobrien	  {
194890075Sobrien	    if (TEST_HARD_REG_BIT (set, j))
194990075Sobrien	      internal_error ("validate_value_data: Loop in regno chain (%u)",
195090075Sobrien			      j);
195190075Sobrien	    if (vd->e[j].oldest_regno != i)
195290075Sobrien	      internal_error ("validate_value_data: [%u] Bad oldest_regno (%u)",
195390075Sobrien			      j, vd->e[j].oldest_regno);
195490075Sobrien
195590075Sobrien	    SET_HARD_REG_BIT (set, j);
195690075Sobrien	  }
195790075Sobrien      }
195890075Sobrien
195990075Sobrien  for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
196090075Sobrien    if (! TEST_HARD_REG_BIT (set, i)
196190075Sobrien	&& (vd->e[i].mode != VOIDmode
196290075Sobrien	    || vd->e[i].oldest_regno != i
196390075Sobrien	    || vd->e[i].next_regno != INVALID_REGNUM))
196490075Sobrien      internal_error ("validate_value_data: [%u] Non-empty reg in chain (%s %u %i)",
196590075Sobrien		      i, GET_MODE_NAME (vd->e[i].mode), vd->e[i].oldest_regno,
196690075Sobrien		      vd->e[i].next_regno);
196790075Sobrien}
196890075Sobrien#endif
1969169689Skan
1970169689Skanstatic bool
1971169689Skangate_handle_regrename (void)
1972169689Skan{
1973169689Skan  return (optimize > 0 && (flag_rename_registers || flag_cprop_registers));
1974169689Skan}
1975169689Skan
1976169689Skan
1977169689Skan/* Run the regrename and cprop passes.  */
1978169689Skanstatic unsigned int
1979169689Skanrest_of_handle_regrename (void)
1980169689Skan{
1981169689Skan  if (flag_rename_registers)
1982169689Skan    regrename_optimize ();
1983169689Skan  if (flag_cprop_registers)
1984169689Skan    copyprop_hardreg_forward ();
1985169689Skan  return 0;
1986169689Skan}
1987169689Skan
1988169689Skanstruct tree_opt_pass pass_regrename =
1989169689Skan{
1990169689Skan  "rnreg",                              /* name */
1991169689Skan  gate_handle_regrename,                /* gate */
1992169689Skan  rest_of_handle_regrename,             /* execute */
1993169689Skan  NULL,                                 /* sub */
1994169689Skan  NULL,                                 /* next */
1995169689Skan  0,                                    /* static_pass_number */
1996169689Skan  TV_RENAME_REGISTERS,                  /* tv_id */
1997169689Skan  0,                                    /* properties_required */
1998169689Skan  0,                                    /* properties_provided */
1999169689Skan  0,                                    /* properties_destroyed */
2000169689Skan  0,                                    /* todo_flags_start */
2001169689Skan  TODO_dump_func,                       /* todo_flags_finish */
2002169689Skan  'n'                                   /* letter */
2003169689Skan};
2004169689Skan
2005