This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: big slowdown in egcs-1.1.2->gcc-2.95 on alpha
- To: lucier at math dot purdue dot edu (Brad Lucier)
- Subject: Re: big slowdown in egcs-1.1.2->gcc-2.95 on alpha
- From: Joern Rennecke <amylaar at cygnus dot co dot uk>
- Date: Fri, 5 Nov 1999 18:40:37 +0000 (GMT)
- Cc: lucier at math dot purdue dot edu, amylaar at cygnus dot co dot uk, rth at cygnus dot com, gcc at gcc dot gnu dot org, gcc-bugs at gcc dot gnu dot org, staff at math dot purdue dot edu, hosking at cs dot purdue dot edu, wilker at math dot purdue dot edu, bernds at cygnus dot com, gcc-patches at gcc dot gnu dot org
> and the top functions were
>
> 19.82 67.88 67.88 1599926669 0.00 0.00 bitmap_bit_p
> 15.83 122.07 54.19 3 18063.15 41030.16 build_insn_chain
> 14.52 171.77 49.71 2789 17.82 17.82 find_reg
> 13.64 218.49 46.72 194464 0.24 0.24 record_one_conflict
> 3.14 229.26 10.76 26627 0.40 0.40 record_conflicts
> 2.94 239.32 10.06 30909 0.33 0.33 delete_from_jump_chain
> ...
> 0.51 277.15 1.74 2 869.63 870.11 prune_preferences
>
> So, even though global-alloc is still the biggest time sink, your patch
> makes a *big* difference. (I don't believe the times reported in each
> pass of the compiler are reliable when it is profiled with -pg.)
Well, since it worked for one place that looks for set bits in allocno sets,
let's see if it works in the two other ones:
Fri Nov 5 18:33:39 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
* global.c (EXECUTE_IF_SET_IN_ALLOCNO_SET): New macro.
(EXECUTE_IF_CONFLICT): Likewise.
(ALLOCNO_LIVE_P): Avoid signed division.
(SET_ALLOCNO_LIVE, CLEAR_ALLOCNO_LIVE): Likewise.
(prune_preferences, find_reg): Use EXECUTE_IF_CONFLICT.
(record_one_conflict): Use EXECUTE_IF_SET_IN_ALLOCNO_SET.
Index: global.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/global.c,v
retrieving revision 1.40
diff -p -r1.40 global.c
*** global.c 1999/11/05 08:31:48 1.40
--- global.c 1999/11/05 18:31:06
*************** static int allocno_row_words;
*** 139,144 ****
--- 139,172 ----
&= ~ ((INT_TYPE) 1 << ((J) % INT_BITS)))
/* END CYGNUS LOCAL */
+ /* For any allocno set in ALLOCNO_SET, set OUT_ALLOCNO to that allocno,
+ and execute CODE. */
+ #define EXECUTE_IF_SET_IN_ALLOCNO_SET(ALLOCNO_SET, ALLOCNO, CODE) \
+ do { \
+ int i_; \
+ int allocno_; \
+ INT_TYPE *p_ = (ALLOCNO_SET); \
+ \
+ for (i_ = allocno_row_words - 1, allocno_ = 0; i_ >= 0; \
+ i_--, allocno_ += INT_BITS) \
+ { \
+ unsigned INT_TYPE word_ = (unsigned INT_TYPE) *p_++; \
+ \
+ for ((ALLOCNO) = allocno_; word_; word_ >>= 1, (ALLOCNO)++) \
+ { \
+ if (word_ & 1) \
+ CODE; \
+ } \
+ } \
+ } while (0)
+
+ /* For any allocno that conflicts with IN_ALLOCNO, set OUT_ALLOCNO to
+ the conflicting allocno, and execute CODE. This macro assumes that
+ mirror_conflicts has been run. */
+ #define EXECUTE_IF_CONFLICT(IN_ALLOCNO, OUT_ALLOCNO, CODE)\
+ EXECUTE_IF_SET_IN_ALLOCNO_SET (conflicts + (IN_ALLOCNO) * allocno_row_words,\
+ OUT_ALLOCNO, CODE)
+
/* Set of hard regs currently live (during scan of all insns). */
static HARD_REG_SET hard_regs_live;
*************** static INT_TYPE *allocnos_live;
*** 217,231 ****
/* Test, set or clear bit number I in allocnos_live,
a bit vector indexed by allocno. */
-
- #define ALLOCNO_LIVE_P(I) \
- (allocnos_live[(I) / INT_BITS] & ((INT_TYPE) 1 << ((I) % INT_BITS)))
-
- #define SET_ALLOCNO_LIVE(I) \
- (allocnos_live[(I) / INT_BITS] |= ((INT_TYPE) 1 << ((I) % INT_BITS)))
! #define CLEAR_ALLOCNO_LIVE(I) \
! (allocnos_live[(I) / INT_BITS] &= ~((INT_TYPE) 1 << ((I) % INT_BITS)))
/* This is turned off because it doesn't work right for DImode.
(And it is only used for DImode, so the other cases are worthless.)
--- 245,262 ----
/* Test, set or clear bit number I in allocnos_live,
a bit vector indexed by allocno. */
! #define ALLOCNO_LIVE_P(I) \
! (allocnos_live[(unsigned)(I) / INT_BITS] \
! & ((INT_TYPE) 1 << ((unsigned)(I) % INT_BITS)))
!
! #define SET_ALLOCNO_LIVE(I) \
! (allocnos_live[(unsigned)(I) / INT_BITS] \
! |= ((INT_TYPE) 1 << ((unsigned)(I) % INT_BITS)))
!
! #define CLEAR_ALLOCNO_LIVE(I) \
! (allocnos_live[(unsigned)(I) / INT_BITS] \
! &= ~((INT_TYPE) 1 << ((unsigned)(I) % INT_BITS)))
/* This is turned off because it doesn't work right for DImode.
(And it is only used for DImode, so the other cases are worthless.)
*************** expand_preferences ()
*** 860,866 ****
static void
prune_preferences ()
{
! int i, j;
int allocno;
int *allocno_to_order = (int *) xmalloc (max_allocno * sizeof (int));
--- 891,897 ----
static void
prune_preferences ()
{
! int i;
int allocno;
int *allocno_to_order = (int *) xmalloc (max_allocno * sizeof (int));
*************** prune_preferences ()
*** 899,931 ****
we want to give the lower-priority allocno the first chance for
these registers). */
HARD_REG_SET temp, temp2;
! INT_TYPE *p;
! int allocno2, allocno3;
allocno = allocno_order[i];
- p = conflicts + allocno * allocno_row_words;
CLEAR_HARD_REG_SET (temp);
CLEAR_HARD_REG_SET (temp2);
! for (j = allocno_row_words - 1, allocno2 = 0; j >= 0;
! j--, allocno2 += INT_BITS)
{
! unsigned INT_TYPE word = (unsigned INT_TYPE) *p++;
!
! for (allocno3 = allocno2; word; word >>= 1, allocno3++)
{
! if ((word & 1) && allocno_to_order[allocno3] > i)
! {
! if (allocno_size[allocno3] <= allocno_size[allocno])
! IOR_HARD_REG_SET (temp,
! hard_reg_full_preferences[allocno3]);
! else
! IOR_HARD_REG_SET (temp2,
! hard_reg_full_preferences[allocno3]);
! }
}
! }
AND_COMPL_HARD_REG_SET (temp, hard_reg_full_preferences[allocno]);
IOR_HARD_REG_SET (temp, temp2);
--- 930,952 ----
we want to give the lower-priority allocno the first chance for
these registers). */
HARD_REG_SET temp, temp2;
! int allocno2;
allocno = allocno_order[i];
CLEAR_HARD_REG_SET (temp);
CLEAR_HARD_REG_SET (temp2);
! EXECUTE_IF_CONFLICT (allocno, allocno2,
{
! if (allocno_to_order[allocno2] > i)
{
! if (allocno_size[allocno2] <= allocno_size[allocno])
! IOR_HARD_REG_SET (temp, hard_reg_full_preferences[allocno2]);
! else
! IOR_HARD_REG_SET (temp2, hard_reg_full_preferences[allocno2]);
}
! });
AND_COMPL_HARD_REG_SET (temp, hard_reg_full_preferences[allocno]);
IOR_HARD_REG_SET (temp, temp2);
*************** find_reg (allocno, losers, alt_regs_p, a
*** 1246,1256 ****
/* For each other pseudo-reg conflicting with this one,
mark it as conflicting with the hard regs this one occupies. */
lim = allocno;
! for (j = 0; j < max_allocno; j++)
! if (CONFLICTP (j, lim))
! {
! IOR_HARD_REG_SET (hard_reg_conflicts[j], this_reg);
! }
}
}
--- 1267,1276 ----
/* For each other pseudo-reg conflicting with this one,
mark it as conflicting with the hard regs this one occupies. */
lim = allocno;
! EXECUTE_IF_CONFLICT (lim, j,
! {
! IOR_HARD_REG_SET (hard_reg_conflicts[j], this_reg);
! });
}
}
*************** record_one_conflict (regno)
*** 1303,1313 ****
if (regno < FIRST_PSEUDO_REGISTER)
/* When a hard register becomes live,
record conflicts with live pseudo regs. */
! for (j = 0; j < max_allocno; j++)
{
! if (ALLOCNO_LIVE_P (j))
! SET_HARD_REG_BIT (hard_reg_conflicts[j], regno);
! }
else
/* When a pseudo-register becomes live,
record conflicts first with hard regs,
--- 1323,1332 ----
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, j,
{
! SET_HARD_REG_BIT (hard_reg_conflicts[j], regno);
! });
else
/* When a pseudo-register becomes live,
record conflicts first with hard regs,