aboutsummaryrefslogtreecommitdiff
path: root/gcc/ra-conflict.c
diff options
context:
space:
mode:
authorPeter Bergner <bergner@vnet.ibm.com>2007-10-05 12:55:18 -0500
committerPeter Bergner <bergner@gcc.gnu.org>2007-10-05 12:55:18 -0500
commitb4da855a9e7a57ea89694006b33f35231b777bbf (patch)
tree2e03ef60b9463aa8d6f1cf89bba364c677a542ef /gcc/ra-conflict.c
parent6aa12f4ffb5d7156e36ccceece6b8a8a83ae520f (diff)
downloadgcc-b4da855a9e7a57ea89694006b33f35231b777bbf.zip
gcc-b4da855a9e7a57ea89694006b33f35231b777bbf.tar.gz
gcc-b4da855a9e7a57ea89694006b33f35231b777bbf.tar.bz2
ra-conflict.c: Include "sparseset.h".
* ra-conflict.c: Include "sparseset.h". (conflicts): Change to HOST_WIDEST_FAST_INT. (allocnos_live): Redefine variable as a sparseset. (SET_ALLOCNO_LIVE, CLEAR_ALLOCNO_LIVE, GET_ALLOCNO_LIVE): Delete macros. (allocno_row_words): Removed global variable. (partial_bitnum, max_bitnum, adjacency_pool, adjacency): New variables. (CONFLICT_BITNUM, CONFLICT_BITNUM_FAST): New defines. (conflict_p, set_conflict_p, set_conflicts_p): New functions. (record_one_conflict_between_regnos): Cache allocno values and reuse. Use set_conflict_p. (record_one_conflict): Update uses of allocnos_live to use the sparseset routines. Use set_conflicts_p. (mark_reg_store): Likewise. (set_reg_in_live): Likewise. (global_conflicts): Update uses of allocnos_live. Use the new adjacency list to visit an allocno's neighbors rather than iterating over all possible allocnos. Call set_conflicts_p to setup conflicts rather than adding them manually. * global.c: Comments updated. (CONFLICTP): Delete define. (regno_compare): New function. Add prototype. (global_alloc): Sort the allocno to regno mapping according to which basic blocks the regnos are referenced in. Modify the conflict bit matrix to a compressed triangular bitmatrix. Only allocate the conflict bit matrix and adjacency lists if we are actually going to allocate something. (expand_preferences): Use conflict_p. Update uses of allocnos_live. (prune_preferences): Use the FOR_EACH_CONFLICT macro to visit an allocno's neighbors rather than iterating over all possible allocnos. (mirror_conflicts): Removed function. (dump_conflicts): Iterate over regnos rather than allocnos so that all dump output will be sorted by regno number. Use the FOR_EACH_CONFLICT macro. * ra.h: Comments updated. (conflicts): Update prototype to HOST_WIDEST_FAST_INT. (partial_bitnum, max_bitnum, adjacency, adjacency_pool): Add prototypes. (ADJACENCY_VEC_LENGTH, FOR_EACH_CONFLICT): New defines. (adjacency_list_d, adjacency_iterator_d): New types. (add_neighbor, adjacency_iter_init, adjacency_iter_done, adjacency_iter_next, regno_basic_block): New static inline functions. (EXECUTE_IF_SET_IN_ALLOCNO_SET): Removed define. (conflict_p): Add function prototype. * sparseset.h, sparseset.c: New files. * Makefile.in (OBJS-common): Add sparseset.o. (sparseset.o): New rule. From-SVN: r129037
Diffstat (limited to 'gcc/ra-conflict.c')
-rw-r--r--gcc/ra-conflict.c240
1 files changed, 174 insertions, 66 deletions
diff --git a/gcc/ra-conflict.c b/gcc/ra-conflict.c
index cd983ba..27a9fcc 100644
--- a/gcc/ra-conflict.c
+++ b/gcc/ra-conflict.c
@@ -41,63 +41,174 @@ along with GCC; see the file COPYING3. If not see
#include "vecprim.h"
#include "ra.h"
#include "sbitmap.h"
-
-/* Test, set or clear bit number I in allocnos_live,
- a bit vector indexed by allocno. */
-
-#define SET_ALLOCNO_LIVE(A, I) \
- ((A)[(unsigned) (I) / HOST_BITS_PER_WIDE_INT] \
- |= ((HOST_WIDE_INT) 1 << ((unsigned) (I) % HOST_BITS_PER_WIDE_INT)))
-
-#define CLEAR_ALLOCNO_LIVE(A, I) \
- ((A)[(unsigned) (I) / HOST_BITS_PER_WIDE_INT] \
- &= ~((HOST_WIDE_INT) 1 << ((unsigned) (I) % HOST_BITS_PER_WIDE_INT)))
-
-#define GET_ALLOCNO_LIVE(A, I) \
- ((A)[(unsigned) (I) / HOST_BITS_PER_WIDE_INT] \
- & ((HOST_WIDE_INT) 1 << ((unsigned) (I) % HOST_BITS_PER_WIDE_INT)))
+#include "sparseset.h"
/* Externs defined in regs.h. */
int max_allocno;
struct allocno *allocno;
-HOST_WIDE_INT *conflicts;
-int allocno_row_words;
+HOST_WIDEST_FAST_INT *conflicts;
int *reg_allocno;
+int *partial_bitnum;
+int max_bitnum;
+alloc_pool adjacency_pool;
+adjacency_t **adjacency;
typedef struct df_ref * df_ref_t;
DEF_VEC_P(df_ref_t);
DEF_VEC_ALLOC_P(df_ref_t,heap);
+/* Macros to determine the bit number within the triangular bit matrix for
+ the two allocnos Low and HIGH, with LOW strictly less than HIGH. */
+
+#define CONFLICT_BITNUM(I, J) \
+ (((I) < (J)) ? (partial_bitnum[I] + (J)) : (partial_bitnum[J] + (I)))
+
+#define CONFLICT_BITNUM_FAST(I, I_PARTIAL_BITNUM, J) \
+ (((I) < (J)) ? ((I_PARTIAL_BITNUM) + (J)) : (partial_bitnum[J] + (I)))
+
+bool
+conflict_p (int allocno1, int allocno2)
+{
+ int bitnum;
+ HOST_WIDEST_FAST_INT word, mask;
+
+#ifdef ENABLE_CHECKING
+ int blk1, blk2;
+
+ gcc_assert (allocno1 >= 0 && allocno1 < max_allocno);
+ gcc_assert (allocno2 >= 0 && allocno2 < max_allocno);
+
+ blk1 = regno_basic_block (allocno[allocno1].reg);
+ blk2 = regno_basic_block (allocno[allocno2].reg);
+ gcc_assert (blk1 == 0 || blk2 == 0 || blk1 == blk2);
+#endif
+
+ if (allocno1 == allocno2)
+ /* By definition, an allocno does not conflict with itself. */
+ return 0;
+
+ bitnum = CONFLICT_BITNUM (allocno1, allocno2);
+
+#ifdef ENABLE_CHECKING
+ gcc_assert (bitnum >= 0 && bitnum < max_bitnum);
+#endif
+
+ word = conflicts[bitnum / HOST_BITS_PER_WIDEST_FAST_INT];
+ mask = (HOST_WIDEST_FAST_INT) 1 << (bitnum % HOST_BITS_PER_WIDEST_FAST_INT);
+ return (word & mask) != 0;
+}
+
+/* Add conflict edges between ALLOCNO1 and ALLOCNO2. */
+
+static void
+set_conflict (int allocno1, int allocno2)
+{
+ int bitnum, index;
+ HOST_WIDEST_FAST_INT word, mask;
+
+#ifdef ENABLE_CHECKING
+ int blk1, blk2;
+
+ gcc_assert (allocno1 >= 0 && allocno1 < max_allocno);
+ gcc_assert (allocno2 >= 0 && allocno2 < max_allocno);
+
+ blk1 = regno_basic_block (allocno[allocno1].reg);
+ blk2 = regno_basic_block (allocno[allocno2].reg);
+ gcc_assert (blk1 == 0 || blk2 == 0 || blk1 == blk2);
+#endif
+
+ /* By definition, an allocno does not conflict with itself. */
+ if (allocno1 == allocno2)
+ return;
+
+ bitnum = CONFLICT_BITNUM (allocno1, allocno2);
+
+#ifdef ENABLE_CHECKING
+ gcc_assert (bitnum >= 0 && bitnum < max_bitnum);
+#endif
+
+ index = bitnum / HOST_BITS_PER_WIDEST_FAST_INT;
+ word = conflicts[index];
+ mask = (HOST_WIDEST_FAST_INT) 1 << (bitnum % HOST_BITS_PER_WIDEST_FAST_INT);
+
+ if ((word & mask) == 0)
+ {
+ conflicts[index] = word | mask;
+ add_neighbor (allocno1, allocno2);
+ add_neighbor (allocno2, allocno1);
+ }
+}
+
+/* Add conflict edges between ALLOCNO1 and all allocnos currently live. */
+
+static void
+set_conflicts (int allocno1, sparseset live)
+{
+ int i;
+ int bitnum, index;
+ HOST_WIDEST_FAST_INT word, mask;
+ int partial_bitnum_allocno1;
+
+#ifdef ENABLE_CHECKING
+ gcc_assert (allocno1 >= 0 && allocno1 < max_allocno);
+#endif
+
+ partial_bitnum_allocno1 = partial_bitnum[allocno1];
+
+ EXECUTE_IF_SET_IN_SPARSESET (live, i)
+ {
+ /* By definition, an allocno does not conflict with itself. */
+ if (allocno1 == i)
+ continue;
+
+#ifdef ENABLE_CHECKING
+ gcc_assert (i >= 0 && i < max_allocno);
+#endif
+
+ bitnum = CONFLICT_BITNUM_FAST (allocno1, partial_bitnum_allocno1, i);
+
+#ifdef ENABLE_CHECKING
+ gcc_assert (bitnum >= 0 && bitnum < max_bitnum);
+#endif
+
+ index = bitnum / HOST_BITS_PER_WIDEST_FAST_INT;
+ word = conflicts[index];
+ mask = (HOST_WIDEST_FAST_INT) 1 << (bitnum % HOST_BITS_PER_WIDEST_FAST_INT);
+
+ if ((word & mask) == 0)
+ {
+ conflicts[index] = word | mask;
+ add_neighbor (allocno1, i);
+ add_neighbor (i, allocno1);
+ }
+ }
+}
+
+
/* Add a conflict between R1 and R2. */
static void
record_one_conflict_between_regnos (enum machine_mode mode1, int r1,
enum machine_mode mode2, int r2)
{
+ int allocno1 = reg_allocno[r1];
+ int allocno2 = reg_allocno[r2];
+
if (dump_file)
fprintf (dump_file, " rocbr adding %d<=>%d\n", r1, r2);
- if (reg_allocno[r1] >= 0 && reg_allocno[r2] >= 0)
- {
- int tr1 = reg_allocno[r1];
- int tr2 = reg_allocno[r2];
- int ialloc_prod = tr1 * allocno_row_words;
- SET_ALLOCNO_LIVE ((&conflicts[ialloc_prod]), tr2);
- }
- else if (reg_allocno[r1] >= 0)
+ if (allocno1 >= 0 && allocno2 >= 0)
+ set_conflict (allocno1, allocno2);
+ else if (allocno1 >= 0)
{
- int tr1 = reg_allocno[r1];
-
if (r2 < FIRST_PSEUDO_REGISTER)
- add_to_hard_reg_set (&allocno[tr1].hard_reg_conflicts, mode2, r2);
+ add_to_hard_reg_set (&allocno[allocno1].hard_reg_conflicts, mode2, r2);
}
- else if (reg_allocno[r2] >= 0)
+ else if (allocno2 >= 0)
{
- int tr2 = reg_allocno[r2];
-
if (r1 < FIRST_PSEUDO_REGISTER)
- add_to_hard_reg_set (&allocno[tr2].hard_reg_conflicts, mode1, r1);
+ add_to_hard_reg_set (&allocno[allocno2].hard_reg_conflicts, mode1, r1);
}
/* Now, recursively handle the reg_renumber cases. */
@@ -115,7 +226,7 @@ record_one_conflict_between_regnos (enum machine_mode mode1, int r1,
before calling here. */
static void
-record_one_conflict (HOST_WIDE_INT *allocnos_live,
+record_one_conflict (sparseset allocnos_live,
HARD_REG_SET *hard_regs_live, int regno)
{
int i;
@@ -123,18 +234,17 @@ record_one_conflict (HOST_WIDE_INT *allocnos_live,
if (regno < FIRST_PSEUDO_REGISTER)
/* When a hard register becomes live, record conflicts with live
pseudo regs. */
- EXECUTE_IF_SET_IN_ALLOCNO_SET (allocnos_live, i,
+ EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i)
{
SET_HARD_REG_BIT (allocno[i].hard_reg_conflicts, regno);
if (dump_file)
fprintf (dump_file, " roc adding %d<=>%d\n", allocno[i].reg, regno);
- });
+ }
else
/* When a pseudo-register becomes live, record conflicts first
with hard regs, then with other pseudo regs. */
{
int ialloc = reg_allocno[regno];
- int ialloc_prod = ialloc * allocno_row_words;
if (dump_file)
{
@@ -144,18 +254,16 @@ record_one_conflict (HOST_WIDE_INT *allocnos_live,
&& !TEST_HARD_REG_BIT (allocno[ialloc].hard_reg_conflicts, i))
fprintf (dump_file, "%d ", i);
- EXECUTE_IF_SET_IN_ALLOCNO_SET (allocnos_live, i,
+ EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i)
{
- if (!GET_ALLOCNO_LIVE (&conflicts[ialloc_prod], i))
+ if (!conflict_p (ialloc, i))
fprintf (dump_file, "%d ", allocno[i].reg);
- });
+ }
fprintf (dump_file, ")\n");
}
IOR_HARD_REG_SET (allocno[ialloc].hard_reg_conflicts, *hard_regs_live);
-
- for (i = allocno_row_words - 1; i >= 0; i--)
- conflicts[ialloc_prod + i] |= allocnos_live[i];
+ set_conflicts (ialloc, allocnos_live);
}
}
@@ -168,7 +276,7 @@ record_one_conflict (HOST_WIDE_INT *allocnos_live,
nothing. */
static void
-mark_reg_store (HOST_WIDE_INT *allocnos_live,
+mark_reg_store (sparseset allocnos_live,
HARD_REG_SET *hard_regs_live,
struct df_ref *ref)
{
@@ -340,7 +448,7 @@ ra_init_live_subregs (bool init_value,
set not live even if REG is a subreg. */
inline static void
-clear_reg_in_live (HOST_WIDE_INT *allocnos_live,
+clear_reg_in_live (sparseset allocnos_live,
sbitmap *live_subregs,
int *live_subregs_used,
HARD_REG_SET *hard_regs_live,
@@ -359,7 +467,7 @@ clear_reg_in_live (HOST_WIDE_INT *allocnos_live,
unsigned int start = SUBREG_BYTE (reg);
unsigned int last = start + GET_MODE_SIZE (GET_MODE (reg));
- ra_init_live_subregs (GET_ALLOCNO_LIVE (allocnos_live, allocnum) != 0,
+ ra_init_live_subregs (sparseset_bit_p (allocnos_live, allocnum),
live_subregs, live_subregs_used, allocnum, reg);
/* Ignore the paradoxical bits. */
@@ -375,19 +483,19 @@ clear_reg_in_live (HOST_WIDE_INT *allocnos_live,
if (sbitmap_empty_p (live_subregs[allocnum]))
{
live_subregs_used[allocnum] = 0;
- CLEAR_ALLOCNO_LIVE (allocnos_live, allocnum);
+ sparseset_clear_bit (allocnos_live, allocnum);
}
else
/* Set the allocnos live here because that bit has to be
true to get us to look at the live_subregs fields. */
- SET_ALLOCNO_LIVE (allocnos_live, allocnum);
+ sparseset_set_bit (allocnos_live, allocnum);
}
else
{
/* Resetting the live_subregs_used is effectively saying do not use the
subregs because we are writing the whole pseudo. */
live_subregs_used[allocnum] = 0;
- CLEAR_ALLOCNO_LIVE (allocnos_live, allocnum);
+ sparseset_clear_bit (allocnos_live, allocnum);
}
}
@@ -423,7 +531,7 @@ clear_reg_in_live (HOST_WIDE_INT *allocnos_live,
set live even if REG is a subreg. */
inline static void
-set_reg_in_live (HOST_WIDE_INT *allocnos_live,
+set_reg_in_live (sparseset allocnos_live,
sbitmap *live_subregs,
int *live_subregs_used,
HARD_REG_SET *hard_regs_live,
@@ -441,7 +549,7 @@ set_reg_in_live (HOST_WIDE_INT *allocnos_live,
unsigned int start = SUBREG_BYTE (reg);
unsigned int last = start + GET_MODE_SIZE (GET_MODE (reg));
- ra_init_live_subregs (GET_ALLOCNO_LIVE (allocnos_live, allocnum) != 0,
+ ra_init_live_subregs (sparseset_bit_p (allocnos_live, allocnum),
live_subregs, live_subregs_used, allocnum, reg);
/* Ignore the paradoxical bits. */
@@ -459,7 +567,7 @@ set_reg_in_live (HOST_WIDE_INT *allocnos_live,
subregs because we are writing the whole pseudo. */
live_subregs_used[allocnum] = 0;
- SET_ALLOCNO_LIVE (allocnos_live, allocnum);
+ sparseset_set_bit (allocnos_live, allocnum);
}
if (regno >= FIRST_PSEUDO_REGISTER)
@@ -630,7 +738,7 @@ global_conflicts (void)
HARD_REG_SET hard_regs_live;
HARD_REG_SET renumbers_live;
- HOST_WIDE_INT *allocnos_live;
+ sparseset allocnos_live;
bitmap live = BITMAP_ALLOC (NULL);
VEC (df_ref_t, heap) *clobbers = NULL;
VEC (df_ref_t, heap) *dying_regs = NULL;
@@ -654,7 +762,7 @@ global_conflicts (void)
fprintf (dump_file, "\n");
}
- allocnos_live = XNEWVEC (HOST_WIDE_INT, allocno_row_words);
+ allocnos_live = sparseset_alloc (max_allocno);
FOR_EACH_BB (bb)
{
@@ -663,7 +771,7 @@ global_conflicts (void)
bitmap_copy (live, DF_LIVE_OUT (bb));
df_simulate_artificial_refs_at_end (bb, live);
- memset (allocnos_live, 0, allocno_row_words * sizeof (HOST_WIDE_INT));
+ sparseset_clear (allocnos_live);
memset (live_subregs_used, 0, max_allocno * sizeof (int));
CLEAR_HARD_REG_SET (hard_regs_live);
CLEAR_HARD_REG_SET (renumbers_live);
@@ -720,11 +828,11 @@ global_conflicts (void)
fprintf (dump_file, "%d ", i);
fprintf (dump_file, "] pseudos [");
- EXECUTE_IF_SET_IN_ALLOCNO_SET (allocnos_live, i,
+ EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i)
{
dump_ref (dump_file, " ", "", regno_reg_rtx[allocno[i].reg],
allocno[i].reg, live_subregs, live_subregs_used);
- });
+ }
fprintf (dump_file, "]\n");
}
@@ -803,7 +911,7 @@ global_conflicts (void)
cannot not want to kill the renumbers from the other
pseudos. */
CLEAR_HARD_REG_SET (renumbers_live);
- EXECUTE_IF_SET_IN_ALLOCNO_SET (allocnos_live, i,
+ EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i)
{
unsigned int regno = allocno[i].reg;
int renumber = reg_renumber[regno];
@@ -811,7 +919,7 @@ global_conflicts (void)
if (renumber >= 0 && renumber < FIRST_PSEUDO_REGISTER)
set_renumbers_live (&renumbers_live, live_subregs, live_subregs_used,
i, renumber);
- });
+ }
/* Add the uses to the live sets. Keep track of the regs
that are dying inside the insn, this set will be useful
@@ -850,7 +958,7 @@ global_conflicts (void)
unsigned int start = SUBREG_BYTE (reg);
unsigned int last = start + GET_MODE_SIZE (GET_MODE (reg));
- ra_init_live_subregs (GET_ALLOCNO_LIVE (allocnos_live, allocnum) != 0,
+ ra_init_live_subregs (sparseset_bit_p (allocnos_live, allocnum),
live_subregs, live_subregs_used, allocnum, reg);
/* Ignore the paradoxical bits. */
@@ -870,13 +978,13 @@ global_conflicts (void)
start++;
}
- SET_ALLOCNO_LIVE (allocnos_live, allocnum);
+ sparseset_set_bit (allocnos_live, allocnum);
if (renumber >= 0 && renumber < FIRST_PSEUDO_REGISTER)
set_renumbers_live (&renumbers_live, live_subregs, live_subregs_used,
allocnum, renumber);
}
- else if (GET_ALLOCNO_LIVE (allocnos_live, allocnum) == 0)
+ else if (!sparseset_bit_p (allocnos_live, allocnum))
{
if (dump_file)
fprintf (dump_file, " dying pseudo\n");
@@ -885,7 +993,7 @@ global_conflicts (void)
effectively saying do not use the subregs
because we are reading the whole pseudo. */
live_subregs_used[allocnum] = 0;
- SET_ALLOCNO_LIVE (allocnos_live, allocnum);
+ sparseset_set_bit (allocnos_live, allocnum);
if (renumber >= 0 && renumber < FIRST_PSEUDO_REGISTER)
set_renumbers_live (&renumbers_live, live_subregs, live_subregs_used,
allocnum, renumber);
@@ -1087,10 +1195,10 @@ global_conflicts (void)
because caller-save, fixup_abnormal_edges and possibly the table
driven EH machinery are not quite ready to handle such regs live
across such edges. */
- EXECUTE_IF_SET_IN_ALLOCNO_SET (allocnos_live, i,
- {
- allocno[i].no_stack_reg = 1;
- });
+ EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i)
+ {
+ allocno[i].no_stack_reg = 1;
+ }
for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
record_one_conflict (allocnos_live, &hard_regs_live, i);