/* Graph coloring register allocator
- Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
Contributed by Michael Matz <matz@suse.de>
and Daniel Berlin <dan@cgsoftware.com>.
static void push_list (struct dlist *, struct dlist **);
static void push_list_end (struct dlist *, struct dlist **);
static void free_dlist (struct dlist **);
-static void put_web_at_end (struct web *, enum node_type);
+static void put_web_at_end (struct web *, enum ra_node_type);
static void put_move (struct move *, enum move_type);
static void build_worklists (struct df *);
static void enable_move (struct web *);
static void add_worklist (struct web *);
static int ok (struct web *, struct web *);
static int conservative (struct web *, struct web *);
-static inline unsigned int simplify_p (enum node_type);
+static inline unsigned int simplify_p (enum ra_node_type);
static void combine (struct web *, struct web *);
static void coalesce (void);
static void freeze_moves (struct web *);
unsigned HOST_WIDE_INT, unsigned int);
static int comp_web_pairs (const void *, const void *);
static void sort_and_combine_web_pairs (int);
+static int ok_class (struct web *, struct web *);
static void aggressive_coalesce (void);
static void extended_coalesce_2 (void);
static void check_uncoalesced_moves (void);
Inline, because it's called with constant TYPE every time. */
inline void
-put_web (struct web *web, enum node_type type)
+put_web (struct web *web, enum ra_node_type type)
{
switch (type)
{
list. Additionally TYPE may not be SIMPLIFY. */
static void
-put_web_at_end (struct web *web, enum node_type type)
+put_web_at_end (struct web *web, enum ra_node_type type)
{
if (type == PRECOLORED)
type = INITIAL;
SIMPLIFY types. */
static inline unsigned int
-simplify_p (enum node_type type)
+simplify_p (enum ra_node_type type)
{
return type == SIMPLIFY || type == SIMPLIFY_SPILL || type == SIMPLIFY_FAT;
}
}
else if (target->type == PRECOLORED
|| TEST_BIT (sup_igraph, source->id * num_webs + target->id)
- || TEST_BIT (sup_igraph, target->id * num_webs + source->id))
+ || TEST_BIT (sup_igraph, target->id * num_webs + source->id)
+ || !ok_class (target, source))
{
remove_move (source, m);
remove_move (target, m);
free (sorted);
}
+/* Returns nonzero if source/target reg classes are ok for coalesce. */
+
+static int
+ok_class (struct web *target, struct web *source)
+{
+ /* Don't coalesce if preferred classes are different and at least one
+ of them has a size of 1. This was preventing things such as the
+ branch on count transformation (i.e. DoLoop) since the target, which
+ prefers the CTR, was being coalesced with a source which preferred
+ GENERAL_REGS. If only one web has a preferred class with 1 free reg
+ then set it as the preferred color of the other web. */
+ enum reg_class t_class, s_class;
+ t_class = reg_preferred_class (target->regno);
+ s_class = reg_preferred_class (source->regno);
+ if (t_class != s_class)
+ {
+ if (num_free_regs[t_class] == 1)
+ {
+ if (num_free_regs[s_class] != 1)
+ SET_HARD_REG_BIT (source->prefer_colors,
+ single_reg_in_regclass[t_class]);
+ return 0;
+ }
+ else if (num_free_regs[s_class] == 1)
+ {
+ SET_HARD_REG_BIT (target->prefer_colors,
+ single_reg_in_regclass[s_class]);
+ return 0;
+ }
+ }
+ return 1;
+}
+
/* Greedily coalesce all moves possible. Begin with the web pair
giving the most saving if coalesced. */
if (s != t
&& t->type != PRECOLORED
&& !TEST_BIT (sup_igraph, s->id * num_webs + t->id)
- && !TEST_BIT (sup_igraph, t->id * num_webs + s->id))
+ && !TEST_BIT (sup_igraph, t->id * num_webs + s->id)
+ && ok_class (t, s))
{
if ((s->type == PRECOLORED && ok (t, s))
|| s->type != PRECOLORED)
dest->id * num_webs + source->id)
&& !TEST_BIT (sup_igraph,
source->id * num_webs + dest->id)
+ && ok_class (dest, source)
&& hard_regs_intersect_p (&source->usable_regs,
&dest->usable_regs))
add_web_pair_cost (dest, source,
void
ra_colorize_graph (struct df *df)
{
- if (rtl_dump_file)
+ if (dump_file)
dump_igraph (df);
build_worklists (df);