From: Pat Haugen Date: Thu, 29 Jul 2004 14:49:22 +0000 (+0000) Subject: ra.h (single_reg_in_regclass): Declare. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=727d709b73dbf2bcb675e33d8fab34e2b2218133;p=gcc.git ra.h (single_reg_in_regclass): Declare. 2004-07-29 Pat Haugen * ra.h (single_reg_in_regclass): Declare. * ra.c (single_reg_in_regclass): Define. (first_hard_reg): New. (init_ra): Initialize single_reg_in_regclass. * ra-colorize.c (ok_class): New. (coalesce, aggressive_coalesce, extended_coalesce_2): Use it. From-SVN: r85300 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a71b8a2c992..896e6b07850 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2004-07-29 Pat Haugen + + * ra.h (single_reg_in_regclass): Declare. + * ra.c (single_reg_in_regclass): Define. + (first_hard_reg): New. + (init_ra): Initialize single_reg_in_regclass. + * ra-colorize.c (ok_class): New. + (coalesce, aggressive_coalesce, extended_coalesce_2): Use it. + 2004-07-29 Nathan Sidwell * gcov-io.h: Allow zero tag as EOF indicator. diff --git a/gcc/ra-colorize.c b/gcc/ra-colorize.c index 3d248fa40ea..e3118a0cdac 100644 --- a/gcc/ra-colorize.c +++ b/gcc/ra-colorize.c @@ -92,6 +92,7 @@ static void add_web_pair_cost (struct web *, 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); @@ -841,7 +842,8 @@ coalesce (void) } 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); @@ -2464,6 +2466,39 @@ sort_and_combine_web_pairs (int for_move) 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. */ @@ -2487,7 +2522,8 @@ aggressive_coalesce (void) 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) @@ -2557,6 +2593,7 @@ extended_coalesce_2 (void) 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, diff --git a/gcc/ra.c b/gcc/ra.c index acc1be57e33..c1098e4c5fc 100644 --- a/gcc/ra.c +++ b/gcc/ra.c @@ -84,6 +84,7 @@ * use the constraints from asms */ +static int first_hard_reg (HARD_REG_SET); static struct obstack ra_obstack; static void create_insn_info (struct df *); static void free_insn_info (void); @@ -147,6 +148,7 @@ int orig_max_uid; HARD_REG_SET never_use_colors; HARD_REG_SET usable_regs[N_REG_CLASSES]; unsigned int num_free_regs[N_REG_CLASSES]; +int single_reg_in_regclass[N_REG_CLASSES]; HARD_REG_SET hardregs_for_mode[NUM_MACHINE_MODES]; HARD_REG_SET invalid_mode_change_regs; unsigned char byte2bitcount[256]; @@ -212,6 +214,19 @@ hard_regs_count (HARD_REG_SET rs) return count; } +/* Returns the first hardreg in HARD_REG_SET RS. Assumes there is at + least one reg in the set. */ + +static int +first_hard_reg (HARD_REG_SET rs) +{ + int c; + for (c = 0; c < FIRST_PSEUDO_REGISTER && !TEST_HARD_REG_BIT (rs, c); c++) + if (c == FIRST_PSEUDO_REGISTER) + abort(); + return c; +} + /* Basically like emit_move_insn (i.e. validifies constants and such), but also handle MODE_CC moves (but then the operands must already be basically valid. */ @@ -515,6 +530,10 @@ init_ra (void) size = hard_regs_count (rs); num_free_regs[i] = size; COPY_HARD_REG_SET (usable_regs[i], rs); + if (size == 1) + single_reg_in_regclass[i] = first_hard_reg (rs); + else + single_reg_in_regclass[i] = -1; } /* Setup hardregs_for_mode[]. diff --git a/gcc/ra.h b/gcc/ra.h index 2e2fa408989..9bcc6f54c6a 100644 --- a/gcc/ra.h +++ b/gcc/ra.h @@ -503,6 +503,9 @@ extern HARD_REG_SET never_use_colors; extern HARD_REG_SET usable_regs[N_REG_CLASSES]; /* For each class C the count of hardregs in usable_regs[C]. */ extern unsigned int num_free_regs[N_REG_CLASSES]; +/* For each class C which has num_free_regs[C]==1, the color of the + single register in that class, -1 otherwise. */ +extern int single_reg_in_regclass[N_REG_CLASSES]; /* For each mode M the hardregs, which are MODE_OK for M, and have enough space behind them to hold an M value. Additionally if reg R is OK for mode M, but it needs two hardregs, then R+1 will