1 /* Register conflict graph computation routines.
2 Copyright (C) 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
3 Contributed by CodeSourcery, LLC
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
24 Building an Optimizing Compiler
26 Butterworth-Heinemann, 1998 */
30 #include "coretypes.h"
35 #include "hard-reg-set.h"
36 #include "basic-block.h"
38 /* A register conflict graph is an undirected graph containing nodes
39 for some or all of the regs used in a function. Arcs represent
40 conflicts, i.e. two nodes are connected by an arc if there is a
41 point in the function at which the regs corresponding to the two
44 The conflict graph is represented by the data structures described
45 in Morgan section 11.3.1. Nodes are not stored explicitly; only
46 arcs are. An arc stores the numbers of the regs it connects.
48 Arcs can be located by two methods:
50 - The two reg numbers for each arc are hashed into a single
51 value, and the arc is placed in a hash table according to this
52 value. This permits quick determination of whether a specific
53 conflict is present in the graph.
55 - Additionally, the arc data structures are threaded by a set of
56 linked lists by single reg number. Since each arc references
57 two regs, there are two next pointers, one for the
58 smaller-numbered reg and one for the larger-numbered reg. This
59 permits the quick enumeration of conflicts for a single
62 Arcs are allocated from an obstack. */
64 /* An arc in a conflict graph. */
66 struct conflict_graph_arc_def
68 /* The next element of the list of conflicts involving the
69 smaller-numbered reg, as an index in the table of arcs of this
70 graph. Contains NULL if this is the tail. */
71 struct conflict_graph_arc_def
*smaller_next
;
73 /* The next element of the list of conflicts involving the
74 larger-numbered reg, as an index in the table of arcs of this
75 graph. Contains NULL if this is the tail. */
76 struct conflict_graph_arc_def
*larger_next
;
78 /* The smaller-numbered reg involved in this conflict. */
81 /* The larger-numbered reg involved in this conflict. */
85 typedef struct conflict_graph_arc_def
*conflict_graph_arc
;
86 typedef const struct conflict_graph_arc_def
*const_conflict_graph_arc
;
89 /* A conflict graph. */
91 struct conflict_graph_def
93 /* A hash table of arcs. Used to search for a specific conflict. */
94 htab_t arc_hash_table
;
96 /* The number of regs this conflict graph handles. */
99 /* For each reg, the arc at the head of a list that threads through
100 all the arcs involving that reg. An entry is NULL if no
101 conflicts exist involving that reg. */
102 conflict_graph_arc
*neighbor_heads
;
104 /* Arcs are allocated from here. */
105 struct obstack arc_obstack
;
108 /* The initial capacity (number of conflict arcs) for newly-created
110 #define INITIAL_ARC_CAPACITY 64
113 /* Computes the hash value of the conflict graph arc connecting regs
114 R1 and R2. R1 is assumed to be smaller or equal to R2. */
115 #define CONFLICT_HASH_FN(R1, R2) ((R2) * ((R2) - 1) / 2 + (R1))
117 static hashval_t
arc_hash (const void *);
118 static int arc_eq (const void *, const void *);
119 static int print_conflict (int, int, void *);
121 /* Callback function to compute the hash value of an arc. Uses
122 current_graph to locate the graph to which the arc belongs. */
125 arc_hash (const void *arcp
)
127 const_conflict_graph_arc arc
= (const_conflict_graph_arc
) arcp
;
129 return CONFLICT_HASH_FN (arc
->smaller
, arc
->larger
);
132 /* Callback function to determine the equality of two arcs in the hash
136 arc_eq (const void *arcp1
, const void *arcp2
)
138 const_conflict_graph_arc arc1
= (const_conflict_graph_arc
) arcp1
;
139 const_conflict_graph_arc arc2
= (const_conflict_graph_arc
) arcp2
;
141 return arc1
->smaller
== arc2
->smaller
&& arc1
->larger
== arc2
->larger
;
144 /* Creates an empty conflict graph to hold conflicts among NUM_REGS
148 conflict_graph_new (int num_regs
)
150 conflict_graph graph
= xmalloc (sizeof (struct conflict_graph_def
));
151 graph
->num_regs
= num_regs
;
153 /* Set up the hash table. No delete action is specified; memory
154 management of arcs is through the obstack. */
155 graph
->arc_hash_table
156 = htab_create (INITIAL_ARC_CAPACITY
, &arc_hash
, &arc_eq
, NULL
);
158 /* Create an obstack for allocating arcs. */
159 obstack_init (&graph
->arc_obstack
);
161 /* Create and zero the lookup table by register number. */
162 graph
->neighbor_heads
= xcalloc (num_regs
, sizeof (conflict_graph_arc
));
167 /* Deletes a conflict graph. */
170 conflict_graph_delete (conflict_graph graph
)
172 obstack_free (&graph
->arc_obstack
, NULL
);
173 htab_delete (graph
->arc_hash_table
);
174 free (graph
->neighbor_heads
);
178 /* Adds a conflict to GRAPH between regs REG1 and REG2, which must be
179 distinct. Returns nonzero, unless the conflict is already present
180 in GRAPH, in which case it does nothing and returns zero. */
183 conflict_graph_add (conflict_graph graph
, int reg1
, int reg2
)
185 int smaller
= MIN (reg1
, reg2
);
186 int larger
= MAX (reg1
, reg2
);
187 struct conflict_graph_arc_def dummy
;
188 conflict_graph_arc arc
;
191 /* A reg cannot conflict with itself. */
192 gcc_assert (reg1
!= reg2
);
194 dummy
.smaller
= smaller
;
195 dummy
.larger
= larger
;
196 slot
= htab_find_slot (graph
->arc_hash_table
, (void *) &dummy
, INSERT
);
198 /* If the conflict is already there, do nothing. */
202 /* Allocate an arc. */
204 = obstack_alloc (&graph
->arc_obstack
,
205 sizeof (struct conflict_graph_arc_def
));
207 /* Record the reg numbers. */
208 arc
->smaller
= smaller
;
209 arc
->larger
= larger
;
211 /* Link the conflict into two lists, one for each reg. */
212 arc
->smaller_next
= graph
->neighbor_heads
[smaller
];
213 graph
->neighbor_heads
[smaller
] = arc
;
214 arc
->larger_next
= graph
->neighbor_heads
[larger
];
215 graph
->neighbor_heads
[larger
] = arc
;
217 /* Put it in the hash table. */
218 *slot
= (void *) arc
;
223 /* Returns nonzero if a conflict exists in GRAPH between regs REG1
227 conflict_graph_conflict_p (conflict_graph graph
, int reg1
, int reg2
)
229 /* Build an arc to search for. */
230 struct conflict_graph_arc_def arc
;
231 arc
.smaller
= MIN (reg1
, reg2
);
232 arc
.larger
= MAX (reg1
, reg2
);
234 return htab_find (graph
->arc_hash_table
, (void *) &arc
) != NULL
;
237 /* Calls ENUM_FN for each conflict in GRAPH involving REG. EXTRA is
238 passed back to ENUM_FN. */
241 conflict_graph_enum (conflict_graph graph
, int reg
,
242 conflict_graph_enum_fn enum_fn
, void *extra
)
244 conflict_graph_arc arc
= graph
->neighbor_heads
[reg
];
247 /* Invoke the callback. */
248 if ((*enum_fn
) (arc
->smaller
, arc
->larger
, extra
))
249 /* Stop if requested. */
252 /* Which next pointer to follow depends on whether REG is the
253 smaller or larger reg in this conflict. */
254 if (reg
< arc
->larger
)
255 arc
= arc
->smaller_next
;
257 arc
= arc
->larger_next
;
261 /* For each conflict between a register x and SRC in GRAPH, adds a
262 conflict to GRAPH between x and TARGET. */
265 conflict_graph_merge_regs (conflict_graph graph
, int target
, int src
)
267 conflict_graph_arc arc
= graph
->neighbor_heads
[src
];
274 int other
= arc
->smaller
;
279 conflict_graph_add (graph
, target
, other
);
281 /* Which next pointer to follow depends on whether REG is the
282 smaller or larger reg in this conflict. */
283 if (src
< arc
->larger
)
284 arc
= arc
->smaller_next
;
286 arc
= arc
->larger_next
;
290 /* Holds context information while a conflict graph is being traversed
295 /* The file pointer to which we're printing. */
298 /* The reg whose conflicts we're printing. */
301 /* Whether a conflict has already been printed for this reg. */
305 /* Callback function when enumerating conflicts during printing. */
308 print_conflict (int reg1
, int reg2
, void *contextp
)
310 struct print_context
*context
= (struct print_context
*) contextp
;
313 /* If this is the first conflict printed for this reg, start a new
315 if (! context
->started
)
317 fprintf (context
->fp
, " %d:", context
->reg
);
318 context
->started
= 1;
321 /* Figure out the reg whose conflicts we're printing. The other reg
322 is the interesting one. */
323 if (reg1
== context
->reg
)
327 gcc_assert (reg2
== context
->reg
);
331 /* Print the conflict. */
332 fprintf (context
->fp
, " %d", reg
);
334 /* Continue enumerating. */
338 /* Prints the conflicts in GRAPH to FP. */
341 conflict_graph_print (conflict_graph graph
, FILE *fp
)
344 struct print_context context
;
347 fprintf (fp
, "Conflicts:\n");
349 /* Loop over registers supported in this graph. */
350 for (reg
= 0; reg
< graph
->num_regs
; ++reg
)
355 /* Scan the conflicts for reg, printing as we go. A label for
356 this line will be printed the first time a conflict is
357 printed for the reg; we won't start a new line if this reg
359 conflict_graph_enum (graph
, reg
, &print_conflict
, &context
);
361 /* If this reg does have conflicts, end the line. */