Hi Jeff, > The second thought is to initialize all of cse_reg_info entries at the > beginning of cse_main. Set aside a bitmap with as many bits as > max_regs. Whenever we use one of these accessor macros for register > k, set a bit k saying "cse_reg_info_table[k] is in use." This way, > when we are done with a basic block, we can walk the bitmap and > reinitialize those that are used. Again, a good optimizer should be > able to eliminate most of these bit sets, but a non-pure/const > function call will block the cleanup opportunities. Of course, this > bitmap walk is far more expensive than cse_reg_info_timestamp++.
I just tried this. It comes very close to the current timestamp approach but loses by 0.3% or so in compile time. I'm attaching a patch for completeness. Kazu Hirata Index: cse.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/cse.c,v retrieving revision 1.343 diff -c -d -p -r1.343 cse.c *** cse.c 21 Feb 2005 02:02:19 -0000 1.343 --- cse.c 21 Feb 2005 19:41:04 -0000 *************** struct cse_reg_info *** 328,346 **** /* A table of cse_reg_info indexed by register numbers. */ struct cse_reg_info *cse_reg_info_table; ! /* The size of the above table. */ ! static unsigned int cse_reg_info_table_size; ! ! /* The index of the first entry that has not been initialized. */ ! static unsigned int cse_reg_info_table_first_uninitialized; ! ! /* The timestamp at the beginning of the current run of ! cse_basic_block. We increment this variable at the beginning of ! the current run of cse_basic_block. The timestamp field of a ! cse_reg_info entry matches the value of this variable if and only ! if the entry has been initialized during the current run of ! cse_basic_block. */ ! static unsigned int cse_reg_info_timestamp; /* A HARD_REG_SET containing all the hard registers for which there is currently a REG expression in the hash table. Note the difference --- 328,334 ---- /* A table of cse_reg_info indexed by register numbers. */ struct cse_reg_info *cse_reg_info_table; ! static sbitmap cse_reg_info_init_bitmap; /* A HARD_REG_SET containing all the hard registers for which there is currently a REG expression in the hash table. Note the difference *************** notreg_cost (rtx x, enum rtx_code outer) *** 841,908 **** static void init_cse_reg_info (unsigned int nregs) { ! /* Do we need to grow the table? */ ! if (nregs > cse_reg_info_table_size) ! { ! unsigned int new_size; ! ! if (cse_reg_info_table_size < 2048) ! { ! /* Compute a new size that is a power of 2 and no smaller ! than the large of NREGS and 64. */ ! new_size = (cse_reg_info_table_size ! ? cse_reg_info_table_size : 64); ! ! while (new_size < nregs) ! new_size *= 2; ! } ! else ! { ! /* If we need a big table, allocate just enough to hold ! NREGS registers. */ ! new_size = nregs; ! } ! /* Reallocate the table with NEW_SIZE entries. */ ! if (cse_reg_info_table) ! free (cse_reg_info_table); ! cse_reg_info_table = xmalloc (sizeof (struct cse_reg_info) ! * new_size); ! cse_reg_info_table_size = new_size; ! cse_reg_info_table_first_uninitialized = 0; ! } ! /* Do we have all of the first NREGS entries initialized? */ ! if (cse_reg_info_table_first_uninitialized < nregs) { ! unsigned int old_timestamp = cse_reg_info_timestamp - 1; ! unsigned int i; ! ! /* Put the old timestamp on newly allocated entries so that they ! will all be considered out of date. We do not touch those ! entries beyond the first NREGS entries to be nice to the ! virtual memory. */ ! for (i = cse_reg_info_table_first_uninitialized; i < nregs; i++) ! cse_reg_info_table[i].timestamp = old_timestamp; ! ! cse_reg_info_table_first_uninitialized = nregs; } } ! /* Given REGNO, initialize the cse_reg_info entry for REGNO. */ static void ! get_cse_reg_info_1 (unsigned int regno) { ! /* Set TIMESTAMP field to CSE_REG_INFO_TIMESTAMP so that this ! entry will be considered to have been initialized. */ ! cse_reg_info_table[regno].timestamp = cse_reg_info_timestamp; ! ! /* Initialize the rest of the entry. */ ! cse_reg_info_table[regno].reg_tick = 1; ! cse_reg_info_table[regno].reg_in_table = -1; ! cse_reg_info_table[regno].subreg_ticked = -1; ! cse_reg_info_table[regno].reg_qty = -regno - 1; } /* Find a cse_reg_info entry for REGNO. */ --- 829,857 ---- static void init_cse_reg_info (unsigned int nregs) { ! unsigned int i; ! cse_reg_info_table = xmalloc (sizeof (struct cse_reg_info) * nregs); ! for (i = 0; i < nregs; i++) { ! cse_reg_info_table[i].reg_tick = 1; ! cse_reg_info_table[i].reg_in_table = -1; ! cse_reg_info_table[i].subreg_ticked = -1; ! cse_reg_info_table[i].reg_qty = -i - 1; } + + cse_reg_info_init_bitmap = sbitmap_alloc (nregs); + sbitmap_zero (cse_reg_info_init_bitmap); } ! /* Free CSE_REG_INFO_TABLE. */ static void ! fini_cse_reg_info (void) { ! free (cse_reg_info_table); ! sbitmap_free (cse_reg_info_init_bitmap); } /* Find a cse_reg_info entry for REGNO. */ *************** get_cse_reg_info_1 (unsigned int regno) *** 910,923 **** static inline struct cse_reg_info * get_cse_reg_info (unsigned int regno) { ! struct cse_reg_info *p = &cse_reg_info_table[regno]; ! ! /* If this entry has not been initialized, go ahead and initialize ! it. */ ! if (p->timestamp != cse_reg_info_timestamp) ! get_cse_reg_info_1 (regno); ! ! return p; } /* Clear the hash table and initialize each register with its own quantity, --- 859,866 ---- static inline struct cse_reg_info * get_cse_reg_info (unsigned int regno) { ! SET_BIT (cse_reg_info_init_bitmap, regno); ! return &cse_reg_info_table[regno]; } /* Clear the hash table and initialize each register with its own quantity, *************** new_basic_block (void) *** 930,937 **** next_qty = 0; ! /* Invalidate cse_reg_info_table. */ ! cse_reg_info_timestamp++; /* Clear out hash table state for this pass. */ CLEAR_HARD_REG_SET (hard_regs_in_table); --- 873,887 ---- next_qty = 0; ! /* Initialize those entries that have been used in the previous run. */ ! EXECUTE_IF_SET_IN_SBITMAP (cse_reg_info_init_bitmap, 0, i, ! { ! cse_reg_info_table[i].reg_tick = 1; ! cse_reg_info_table[i].reg_in_table = -1; ! cse_reg_info_table[i].subreg_ticked = -1; ! cse_reg_info_table[i].reg_qty = -i - 1; ! RESET_BIT (cse_reg_info_init_bitmap, i); ! }); /* Clear out hash table state for this pass. */ CLEAR_HARD_REG_SET (hard_regs_in_table); *************** cse_main (rtx f, int nregs, FILE *file) *** 6814,6819 **** --- 6764,6770 ---- free (reg_eqv_table); free (val.path); rtl_hooks = general_rtl_hooks; + fini_cse_reg_info (); return cse_jumps_altered || recorded_label_ref; }