conflict.c revision 117395
190075Sobrien/* Register conflict graph computation routines.
290075Sobrien   Copyright (C) 2000 Free Software Foundation, Inc.
390075Sobrien   Contributed by CodeSourcery, LLC
490075Sobrien
590075SobrienThis file is part of GCC.
690075Sobrien
790075SobrienGCC is free software; you can redistribute it and/or modify it under
890075Sobrienthe terms of the GNU General Public License as published by the Free
990075SobrienSoftware Foundation; either version 2, or (at your option) any later
1090075Sobrienversion.
1190075Sobrien
1290075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1390075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1490075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1590075Sobrienfor more details.
1690075Sobrien
1790075SobrienYou should have received a copy of the GNU General Public License
1890075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
1990075SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
2090075Sobrien02111-1307, USA.  */
2190075Sobrien
2290075Sobrien/* References:
2390075Sobrien
2490075Sobrien   Building an Optimizing Compiler
2590075Sobrien   Robert Morgan
2690075Sobrien   Butterworth-Heinemann, 1998 */
2790075Sobrien
2890075Sobrien#include "config.h"
2990075Sobrien#include "system.h"
3090075Sobrien#include "obstack.h"
3190075Sobrien#include "hashtab.h"
3290075Sobrien#include "rtl.h"
3390075Sobrien#include "hard-reg-set.h"
3490075Sobrien#include "basic-block.h"
3590075Sobrien
3690075Sobrien/* A register conflict graph is an undirected graph containing nodes
3790075Sobrien   for some or all of the regs used in a function.  Arcs represent
3890075Sobrien   conflicts, i.e. two nodes are connected by an arc if there is a
3990075Sobrien   point in the function at which the regs corresponding to the two
4090075Sobrien   nodes are both live.
4190075Sobrien
4290075Sobrien   The conflict graph is represented by the data structures described
4390075Sobrien   in Morgan section 11.3.1.  Nodes are not stored explicitly; only
4490075Sobrien   arcs are.  An arc stores the numbers of the regs it connects.
4590075Sobrien
4690075Sobrien   Arcs can be located by two methods:
4790075Sobrien
4890075Sobrien     - The two reg numbers for each arc are hashed into a single
4990075Sobrien       value, and the arc is placed in a hash table according to this
5090075Sobrien       value.  This permits quick determination of whether a specific
5190075Sobrien       conflict is present in the graph.
5290075Sobrien
5390075Sobrien     - Additionally, the arc data structures are threaded by a set of
5490075Sobrien       linked lists by single reg number.  Since each arc references
5590075Sobrien       two regs, there are two next pointers, one for the
5690075Sobrien       smaller-numbered reg and one for the larger-numbered reg.  This
5790075Sobrien       permits the quick enumeration of conflicts for a single
5890075Sobrien       register.
5990075Sobrien
6090075Sobrien   Arcs are allocated from an obstack.  */
6190075Sobrien
6290075Sobrien/* An arc in a conflict graph.  */
6390075Sobrien
6490075Sobrienstruct conflict_graph_arc_def
6590075Sobrien{
6690075Sobrien  /* The next element of the list of conflicts involving the
6790075Sobrien     smaller-numbered reg, as an index in the table of arcs of this
6890075Sobrien     graph.   Contains NULL if this is the tail.  */
6990075Sobrien  struct conflict_graph_arc_def *smaller_next;
7090075Sobrien
7190075Sobrien  /* The next element of the list of conflicts involving the
7290075Sobrien     larger-numbered reg, as an index in the table of arcs of this
7390075Sobrien     graph.  Contains NULL if this is the tail.  */
7490075Sobrien  struct conflict_graph_arc_def *larger_next;
7590075Sobrien
7690075Sobrien  /* The smaller-numbered reg involved in this conflict.  */
7790075Sobrien  int smaller;
7890075Sobrien
7990075Sobrien  /* The larger-numbered reg involved in this conflict.  */
8090075Sobrien  int larger;
8190075Sobrien};
8290075Sobrien
8390075Sobrientypedef struct conflict_graph_arc_def *conflict_graph_arc;
8490075Sobrientypedef const struct conflict_graph_arc_def *const_conflict_graph_arc;
8590075Sobrien
8690075Sobrien
8790075Sobrien/* A conflict graph.  */
8890075Sobrien
8990075Sobrienstruct conflict_graph_def
9090075Sobrien{
9190075Sobrien  /* A hash table of arcs.  Used to search for a specific conflict.  */
9290075Sobrien  htab_t arc_hash_table;
9390075Sobrien
9490075Sobrien  /* The number of regs this conflict graph handles.  */
9590075Sobrien  int num_regs;
9690075Sobrien
9790075Sobrien  /* For each reg, the arc at the head of a list that threads through
9890075Sobrien     all the arcs involving that reg.  An entry is NULL if no
9990075Sobrien     conflicts exist involving that reg.  */
10090075Sobrien  conflict_graph_arc *neighbor_heads;
10190075Sobrien
10290075Sobrien  /* Arcs are allocated from here.  */
10390075Sobrien  struct obstack arc_obstack;
10490075Sobrien};
10590075Sobrien
10690075Sobrien/* The initial capacity (number of conflict arcs) for newly-created
10790075Sobrien   conflict graphs.  */
10890075Sobrien#define INITIAL_ARC_CAPACITY 64
10990075Sobrien
11090075Sobrien
11190075Sobrien/* Computes the hash value of the conflict graph arc connecting regs
11290075Sobrien   R1 and R2.  R1 is assumed to be smaller or equal to R2.  */
11390075Sobrien#define CONFLICT_HASH_FN(R1, R2) ((R2) * ((R2) - 1) / 2 + (R1))
11490075Sobrien
115117395Skanstatic hashval_t arc_hash	PARAMS ((const void *));
11690075Sobrienstatic int arc_eq		PARAMS ((const void *, const void *));
11790075Sobrienstatic int print_conflict	PARAMS ((int, int, void *));
11890075Sobrienstatic void mark_reg		PARAMS ((rtx, rtx, void *));
11990075Sobrien
12090075Sobrien/* Callback function to compute the hash value of an arc.  Uses
12190075Sobrien   current_graph to locate the graph to which the arc belongs.  */
12290075Sobrien
123117395Skanstatic hashval_t
12490075Sobrienarc_hash (arcp)
12590075Sobrien     const void *arcp;
12690075Sobrien{
12790075Sobrien  const_conflict_graph_arc arc = (const_conflict_graph_arc) arcp;
12890075Sobrien
12990075Sobrien  return CONFLICT_HASH_FN (arc->smaller, arc->larger);
13090075Sobrien}
13190075Sobrien
13290075Sobrien/* Callback function to determine the equality of two arcs in the hash
13390075Sobrien   table.  */
13490075Sobrien
13590075Sobrienstatic int
13690075Sobrienarc_eq (arcp1, arcp2)
13790075Sobrien     const void *arcp1;
13890075Sobrien     const void *arcp2;
13990075Sobrien{
14090075Sobrien  const_conflict_graph_arc arc1 = (const_conflict_graph_arc) arcp1;
14190075Sobrien  const_conflict_graph_arc arc2 = (const_conflict_graph_arc) arcp2;
14290075Sobrien
14390075Sobrien  return arc1->smaller == arc2->smaller && arc1->larger == arc2->larger;
14490075Sobrien}
14590075Sobrien
14690075Sobrien/* Creates an empty conflict graph to hold conflicts among NUM_REGS
14790075Sobrien   registers.  */
14890075Sobrien
14990075Sobrienconflict_graph
15090075Sobrienconflict_graph_new (num_regs)
15190075Sobrien     int num_regs;
15290075Sobrien{
15390075Sobrien  conflict_graph graph
15490075Sobrien    = (conflict_graph) xmalloc (sizeof (struct conflict_graph_def));
15590075Sobrien  graph->num_regs = num_regs;
15690075Sobrien
15790075Sobrien  /* Set up the hash table.  No delete action is specified; memory
15890075Sobrien     management of arcs is through the obstack.  */
15990075Sobrien  graph->arc_hash_table
16090075Sobrien    = htab_create (INITIAL_ARC_CAPACITY, &arc_hash, &arc_eq, NULL);
16190075Sobrien
16290075Sobrien  /* Create an obstack for allocating arcs.  */
16390075Sobrien  obstack_init (&graph->arc_obstack);
16490075Sobrien
16590075Sobrien  /* Create and zero the lookup table by register number.  */
16690075Sobrien  graph->neighbor_heads
16790075Sobrien    = (conflict_graph_arc *) xmalloc (num_regs * sizeof (conflict_graph_arc));
16890075Sobrien
16990075Sobrien  memset (graph->neighbor_heads, 0, num_regs * sizeof (conflict_graph_arc));
17090075Sobrien  return graph;
17190075Sobrien}
17290075Sobrien
17390075Sobrien/* Deletes a conflict graph.  */
17490075Sobrien
17590075Sobrienvoid
17690075Sobrienconflict_graph_delete (graph)
17790075Sobrien     conflict_graph graph;
17890075Sobrien{
17990075Sobrien  obstack_free (&graph->arc_obstack, NULL);
18090075Sobrien  htab_delete (graph->arc_hash_table);
18190075Sobrien  free (graph->neighbor_heads);
18290075Sobrien  free (graph);
18390075Sobrien}
18490075Sobrien
18590075Sobrien/* Adds a conflict to GRAPH between regs REG1 and REG2, which must be
186117395Skan   distinct.  Returns nonzero, unless the conflict is already present
18790075Sobrien   in GRAPH, in which case it does nothing and returns zero.  */
18890075Sobrien
18990075Sobrienint
19090075Sobrienconflict_graph_add (graph, reg1, reg2)
19190075Sobrien     conflict_graph graph;
19290075Sobrien     int reg1;
19390075Sobrien     int reg2;
19490075Sobrien{
19590075Sobrien  int smaller = MIN (reg1, reg2);
19690075Sobrien  int larger = MAX (reg1, reg2);
19790075Sobrien  struct conflict_graph_arc_def dummy;
19890075Sobrien  conflict_graph_arc arc;
19990075Sobrien  void **slot;
20090075Sobrien
20190075Sobrien  /* A reg cannot conflict with itself.  */
20290075Sobrien  if (reg1 == reg2)
20390075Sobrien    abort ();
20490075Sobrien
20590075Sobrien  dummy.smaller = smaller;
20690075Sobrien  dummy.larger = larger;
20790075Sobrien  slot = htab_find_slot (graph->arc_hash_table, (void *) &dummy, INSERT);
20890075Sobrien
20990075Sobrien  /* If the conflict is already there, do nothing.  */
21090075Sobrien  if (*slot != NULL)
21190075Sobrien    return 0;
21290075Sobrien
21390075Sobrien  /* Allocate an arc.  */
21490075Sobrien  arc
21590075Sobrien    = (conflict_graph_arc)
21690075Sobrien      obstack_alloc (&graph->arc_obstack,
21790075Sobrien		     sizeof (struct conflict_graph_arc_def));
21890075Sobrien
21990075Sobrien  /* Record the reg numbers.  */
22090075Sobrien  arc->smaller = smaller;
22190075Sobrien  arc->larger = larger;
22290075Sobrien
22390075Sobrien  /* Link the conflict into into two lists, one for each reg.  */
22490075Sobrien  arc->smaller_next = graph->neighbor_heads[smaller];
22590075Sobrien  graph->neighbor_heads[smaller] = arc;
22690075Sobrien  arc->larger_next = graph->neighbor_heads[larger];
22790075Sobrien  graph->neighbor_heads[larger] = arc;
22890075Sobrien
22990075Sobrien  /* Put it in the hash table.  */
23090075Sobrien  *slot = (void *) arc;
23190075Sobrien
23290075Sobrien  return 1;
23390075Sobrien}
23490075Sobrien
235117395Skan/* Returns nonzero if a conflict exists in GRAPH between regs REG1
23690075Sobrien   and REG2.  */
23790075Sobrien
23890075Sobrienint
23990075Sobrienconflict_graph_conflict_p (graph, reg1, reg2)
24090075Sobrien     conflict_graph graph;
24190075Sobrien     int reg1;
24290075Sobrien     int reg2;
24390075Sobrien{
24490075Sobrien  /* Build an arc to search for.  */
24590075Sobrien  struct conflict_graph_arc_def arc;
24690075Sobrien  arc.smaller = MIN (reg1, reg2);
24790075Sobrien  arc.larger = MAX (reg1, reg2);
24890075Sobrien
24990075Sobrien  return htab_find (graph->arc_hash_table, (void *) &arc) != NULL;
25090075Sobrien}
25190075Sobrien
25290075Sobrien/* Calls ENUM_FN for each conflict in GRAPH involving REG.  EXTRA is
25390075Sobrien   passed back to ENUM_FN.  */
25490075Sobrien
25590075Sobrienvoid
25690075Sobrienconflict_graph_enum (graph, reg, enum_fn, extra)
25790075Sobrien     conflict_graph graph;
25890075Sobrien     int reg;
25990075Sobrien     conflict_graph_enum_fn enum_fn;
26090075Sobrien     void *extra;
26190075Sobrien{
26290075Sobrien  conflict_graph_arc arc = graph->neighbor_heads[reg];
26390075Sobrien  while (arc != NULL)
26490075Sobrien    {
26590075Sobrien      /* Invoke the callback.  */
26690075Sobrien      if ((*enum_fn) (arc->smaller, arc->larger, extra))
26790075Sobrien	/* Stop if requested.  */
26890075Sobrien	break;
26990075Sobrien
27090075Sobrien      /* Which next pointer to follow depends on whether REG is the
27190075Sobrien	 smaller or larger reg in this conflict.  */
27290075Sobrien      if (reg < arc->larger)
27390075Sobrien	arc = arc->smaller_next;
27490075Sobrien      else
27590075Sobrien	arc = arc->larger_next;
27690075Sobrien    }
27790075Sobrien}
27890075Sobrien
27990075Sobrien/* For each conflict between a register x and SRC in GRAPH, adds a
28090075Sobrien   conflict to GRAPH between x and TARGET.  */
28190075Sobrien
28290075Sobrienvoid
28390075Sobrienconflict_graph_merge_regs (graph, target, src)
28490075Sobrien     conflict_graph graph;
28590075Sobrien     int target;
28690075Sobrien     int src;
28790075Sobrien{
28890075Sobrien  conflict_graph_arc arc = graph->neighbor_heads[src];
28990075Sobrien
29090075Sobrien  if (target == src)
29190075Sobrien    return;
29290075Sobrien
29390075Sobrien  while (arc != NULL)
29490075Sobrien    {
29590075Sobrien      int other = arc->smaller;
29690075Sobrien
29790075Sobrien      if (other == src)
29890075Sobrien	other = arc->larger;
29990075Sobrien
30090075Sobrien      conflict_graph_add (graph, target, other);
30190075Sobrien
30290075Sobrien      /* Which next pointer to follow depends on whether REG is the
30390075Sobrien	 smaller or larger reg in this conflict.  */
30490075Sobrien      if (src < arc->larger)
30590075Sobrien	arc = arc->smaller_next;
30690075Sobrien      else
30790075Sobrien	arc = arc->larger_next;
30890075Sobrien    }
30990075Sobrien}
31090075Sobrien
31190075Sobrien/* Holds context information while a conflict graph is being traversed
31290075Sobrien   for printing.  */
31390075Sobrien
31490075Sobrienstruct print_context
31590075Sobrien{
31690075Sobrien  /* The file pointer to which we're printing.  */
31790075Sobrien  FILE *fp;
31890075Sobrien
31990075Sobrien  /* The reg whose conflicts we're printing.  */
32090075Sobrien  int reg;
32190075Sobrien
32290075Sobrien  /* Whether a conflict has already been printed for this reg.  */
32390075Sobrien  int started;
32490075Sobrien};
32590075Sobrien
32690075Sobrien/* Callback function when enumerating conflicts during printing.  */
32790075Sobrien
32890075Sobrienstatic int
32990075Sobrienprint_conflict (reg1, reg2, contextp)
33090075Sobrien     int reg1;
33190075Sobrien     int reg2;
33290075Sobrien     void *contextp;
33390075Sobrien{
33490075Sobrien  struct print_context *context = (struct print_context *) contextp;
33590075Sobrien  int reg;
33690075Sobrien
33790075Sobrien  /* If this is the first conflict printed for this reg, start a new
33890075Sobrien     line.  */
33990075Sobrien  if (! context->started)
34090075Sobrien    {
34190075Sobrien      fprintf (context->fp, " %d:", context->reg);
34290075Sobrien      context->started = 1;
34390075Sobrien    }
34490075Sobrien
34590075Sobrien  /* Figure out the reg whose conflicts we're printing.  The other reg
34690075Sobrien     is the interesting one.  */
34790075Sobrien  if (reg1 == context->reg)
34890075Sobrien    reg = reg2;
34990075Sobrien  else if (reg2 == context->reg)
35090075Sobrien    reg = reg1;
35190075Sobrien  else
35290075Sobrien    abort ();
35390075Sobrien
35490075Sobrien  /* Print the conflict.  */
35590075Sobrien  fprintf (context->fp, " %d", reg);
35690075Sobrien
35790075Sobrien  /* Continue enumerating.  */
35890075Sobrien  return 0;
35990075Sobrien}
36090075Sobrien
36190075Sobrien/* Prints the conflicts in GRAPH to FP.  */
36290075Sobrien
36390075Sobrienvoid
36490075Sobrienconflict_graph_print (graph, fp)
36590075Sobrien     conflict_graph graph;
36690075Sobrien     FILE *fp;
36790075Sobrien{
36890075Sobrien  int reg;
36990075Sobrien  struct print_context context;
37090075Sobrien
37190075Sobrien  context.fp = fp;
37290075Sobrien  fprintf (fp, "Conflicts:\n");
37390075Sobrien
37490075Sobrien  /* Loop over registers supported in this graph.  */
37590075Sobrien  for (reg = 0; reg < graph->num_regs; ++reg)
37690075Sobrien    {
37790075Sobrien      context.reg = reg;
37890075Sobrien      context.started = 0;
37990075Sobrien
38090075Sobrien      /* Scan the conflicts for reg, printing as we go.  A label for
38190075Sobrien	 this line will be printed the first time a conflict is
38290075Sobrien	 printed for the reg; we won't start a new line if this reg
38390075Sobrien	 has no conflicts.  */
38490075Sobrien      conflict_graph_enum (graph, reg, &print_conflict, &context);
38590075Sobrien
38690075Sobrien      /* If this reg does have conflicts, end the line.  */
38790075Sobrien      if (context.started)
38890075Sobrien	fputc ('\n', fp);
38990075Sobrien    }
39090075Sobrien}
39190075Sobrien
39290075Sobrien/* Callback function for note_stores.  */
39390075Sobrien
39490075Sobrienstatic void
39590075Sobrienmark_reg (reg, setter, data)
39690075Sobrien     rtx reg;
39790075Sobrien     rtx setter ATTRIBUTE_UNUSED;
39890075Sobrien     void *data;
39990075Sobrien{
40090075Sobrien  regset set = (regset) data;
40190075Sobrien
40290075Sobrien  if (GET_CODE (reg) == SUBREG)
40390075Sobrien    reg = SUBREG_REG (reg);
40490075Sobrien
40590075Sobrien  /* We're only interested in regs.  */
40690075Sobrien  if (GET_CODE (reg) != REG)
40790075Sobrien    return;
40890075Sobrien
40990075Sobrien  SET_REGNO_REG_SET (set, REGNO (reg));
41090075Sobrien}
41190075Sobrien
41290075Sobrien/* Allocates a conflict graph and computes conflicts over the current
41390075Sobrien   function for the registers set in REGS.  The caller is responsible
41490075Sobrien   for deallocating the return value.
41590075Sobrien
41690075Sobrien   Preconditions: the flow graph must be in SSA form, and life
41790075Sobrien   analysis (specifically, regs live at exit from each block) must be
41890075Sobrien   up-to-date.
41990075Sobrien
42090075Sobrien   This algorithm determines conflicts by walking the insns in each
42190075Sobrien   block backwards.  We maintain the set of live regs at each insn,
42290075Sobrien   starting with the regs live on exit from the block.  For each insn:
42390075Sobrien
42490075Sobrien     1. If a reg is set in this insns, it must be born here, since
42590075Sobrien        we're in SSA.  Therefore, it was not live before this insns,
42690075Sobrien	so remove it from the set of live regs.
42790075Sobrien
42890075Sobrien     2. For each reg born in this insn, record a conflict between it
42990075Sobrien	and every other reg live coming into this insn.  For each
43090075Sobrien	existing conflict, one of the two regs must be born while the
43190075Sobrien	other is alive.  See Morgan or elsewhere for a proof of this.
43290075Sobrien
43390075Sobrien     3. Regs clobbered by this insn must have been live coming into
43490075Sobrien        it, so record them as such.
43590075Sobrien
43690075Sobrien   The resulting conflict graph is not built for regs in REGS
43790075Sobrien   themselves; rather, partition P is used to obtain the canonical reg
43890075Sobrien   for each of these.  The nodes of the conflict graph are these
43990075Sobrien   canonical regs instead.  */
44090075Sobrien
44190075Sobrienconflict_graph
44290075Sobrienconflict_graph_compute (regs, p)
44390075Sobrien     regset regs;
44490075Sobrien     partition p;
44590075Sobrien{
44690075Sobrien  conflict_graph graph = conflict_graph_new (max_reg_num ());
44790075Sobrien  regset_head live_head;
44890075Sobrien  regset live = &live_head;
44990075Sobrien  regset_head born_head;
45090075Sobrien  regset born = &born_head;
451117395Skan  basic_block bb;
45290075Sobrien
45390075Sobrien  INIT_REG_SET (live);
45490075Sobrien  INIT_REG_SET (born);
45590075Sobrien
456117395Skan  FOR_EACH_BB_REVERSE (bb)
45790075Sobrien    {
45890075Sobrien      rtx insn;
45990075Sobrien      rtx head;
46090075Sobrien
46190075Sobrien      /* Start with the regs that are live on exit, limited to those
46290075Sobrien	 we're interested in.  */
46390075Sobrien      COPY_REG_SET (live, bb->global_live_at_end);
46490075Sobrien      AND_REG_SET (live, regs);
46590075Sobrien
46690075Sobrien      /* Walk the instruction stream backwards.  */
46790075Sobrien      head = bb->head;
46890075Sobrien      insn = bb->end;
46990075Sobrien      for (insn = bb->end; insn != head; insn = PREV_INSN (insn))
47090075Sobrien	{
47190075Sobrien	  int born_reg;
47290075Sobrien	  int live_reg;
47390075Sobrien	  rtx link;
47490075Sobrien
47590075Sobrien	  /* Are we interested in this insn? */
47690075Sobrien	  if (INSN_P (insn))
47790075Sobrien	    {
47890075Sobrien	      /* Determine which regs are set in this insn.  Since
47990075Sobrien  	         we're in SSA form, if a reg is set here it isn't set
48090075Sobrien  	         anywhere else, so this insn is where the reg is born.  */
48190075Sobrien	      CLEAR_REG_SET (born);
48290075Sobrien	      note_stores (PATTERN (insn), mark_reg, born);
48390075Sobrien	      AND_REG_SET (born, regs);
48490075Sobrien
48590075Sobrien	      /* Regs born here were not live before this insn.  */
48690075Sobrien	      AND_COMPL_REG_SET (live, born);
48790075Sobrien
48890075Sobrien	      /* For every reg born here, add a conflict with every other
48990075Sobrien  	         reg live coming into this insn.  */
49090075Sobrien	      EXECUTE_IF_SET_IN_REG_SET
49190075Sobrien		(born, FIRST_PSEUDO_REGISTER, born_reg,
49290075Sobrien		 {
49390075Sobrien		   EXECUTE_IF_SET_IN_REG_SET
49490075Sobrien		     (live, FIRST_PSEUDO_REGISTER, live_reg,
49590075Sobrien		      {
49690075Sobrien			/* Build the conflict graph in terms of canonical
49790075Sobrien			   regnos.  */
49890075Sobrien			int b = partition_find (p, born_reg);
49990075Sobrien			int l = partition_find (p, live_reg);
50090075Sobrien
50190075Sobrien			if (b != l)
50290075Sobrien			  conflict_graph_add (graph, b, l);
50390075Sobrien		      });
50490075Sobrien		 });
50590075Sobrien
50690075Sobrien	      /* Morgan's algorithm checks the operands of the insn
50790075Sobrien	         and adds them to the set of live regs.  Instead, we
50890075Sobrien	         use death information added by life analysis.  Regs
50990075Sobrien	         dead after this instruction were live before it.  */
51090075Sobrien	      for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
51190075Sobrien		if (REG_NOTE_KIND (link) == REG_DEAD)
51290075Sobrien		  {
51390075Sobrien		    unsigned int regno = REGNO (XEXP (link, 0));
51490075Sobrien
51590075Sobrien		    if (REGNO_REG_SET_P (regs, regno))
51690075Sobrien		      SET_REGNO_REG_SET (live, regno);
51790075Sobrien		  }
51890075Sobrien	    }
51990075Sobrien	}
52090075Sobrien    }
52190075Sobrien
52290075Sobrien  FREE_REG_SET (live);
52390075Sobrien  FREE_REG_SET (born);
52490075Sobrien
52590075Sobrien  return graph;
52690075Sobrien}
527