Re: [patch][cprop.c] Clean up hash table building

2011-03-31 Thread Richard Guenther
On Thu, Mar 31, 2011 at 12:39 AM, Steven Bosscher stevenb@gmail.com wrote:
 Hi,

 This is the first cleanup for cprop.c. These cleanups are only
 possible now, thanks to splitting the CPROP code out from gcse.c

 The first change is to not treat unfolded conditions as constant in
 gcse_constant_p(). This never happens because:
 - during hash table building any such condition should have been
 simplified by any prior pass
 - during cprop the expression table is not updated because the
 patterns are unshared

 This causes no changes in code generation for all cc1-i files on
 x86_64-unknown-linux-gnu. I could add an assert to make sure this kind
 of condition really never happens, but IMHO it's not worth it and the
 bug would be elsewhere anyway.

 The second change is to remove oprs_available_p(). After the
 gcse_constant_p() cleanup, we do not have to traverse the whole
 pattern of a SET candidate for CPROP, because we know that SET_DEST is
 a REG and SET_SRC is a REG or a shareable constant. Therefore a simple
 check to see if the registers involved were set in the block is
 sufficient, and a regset can be used instead of the last_set table.
 See reg_available_p().

 The third change is to compute_hash_table_work(), which now traverses
 the insns in each basic block just once (instead of twice), in reverse
 order to record all registers set between BB_END and the current insn.
 This change allows further simplify hash_scan_set() which now doesn't
 have to look at INSN+1 anymore (saving another half insns stream
 traversal by avoiding next_nonnote_nondebug_insn()).

 Bootstrapped and tested on x86_64-unknown-linux-gnu. OK?

Ok.

Thanks,
Richard.

 Ciao!
 Steven



[patch][cprop.c] Clean up hash table building

2011-03-30 Thread Steven Bosscher
Hi,

This is the first cleanup for cprop.c. These cleanups are only
possible now, thanks to splitting the CPROP code out from gcse.c

The first change is to not treat unfolded conditions as constant in
gcse_constant_p(). This never happens because:
- during hash table building any such condition should have been
simplified by any prior pass
- during cprop the expression table is not updated because the
patterns are unshared

This causes no changes in code generation for all cc1-i files on
x86_64-unknown-linux-gnu. I could add an assert to make sure this kind
of condition really never happens, but IMHO it's not worth it and the
bug would be elsewhere anyway.

The second change is to remove oprs_available_p(). After the
gcse_constant_p() cleanup, we do not have to traverse the whole
pattern of a SET candidate for CPROP, because we know that SET_DEST is
a REG and SET_SRC is a REG or a shareable constant. Therefore a simple
check to see if the registers involved were set in the block is
sufficient, and a regset can be used instead of the last_set table.
See reg_available_p().

The third change is to compute_hash_table_work(), which now traverses
the insns in each basic block just once (instead of twice), in reverse
order to record all registers set between BB_END and the current insn.
This change allows further simplify hash_scan_set() which now doesn't
have to look at INSN+1 anymore (saving another half insns stream
traversal by avoiding next_nonnote_nondebug_insn()).

Bootstrapped and tested on x86_64-unknown-linux-gnu. OK?

Ciao!
Steven
* cprop.c: Clean up hash table building.
(reg_avail_info): Remove.
(oprs_available_p): Remove.
(record_last_reg_set_info): Remove.
(record_last_set_info): Remove.
(reg_available_p): New function.
(gcse_constant_p): Do not treat unfolded conditions as constants.
(make_set_regs_unavailable): New function.
(hash_scan_set): Simplify with new reg_available_p.
(compute_hash_table_work): Traverse insns stream only once.
Do not compute reg_avail_info. Traverse insns in reverse order.
Record implicit sets after recording explicit sets from the block.

Index: cprop.c
===
*** cprop.c (revision 171627)
--- cprop.c (working copy)
*** static rtx *implicit_sets;
*** 118,124 
  
  /* Bitmap containing one bit for each register in the program.
 Used when performing GCSE to track which registers have been set since
!the start of the basic block.  */
  static regset reg_set_bitmap;
  
  /* Various variables for statistics gathering.  */
--- 118,124 
  
  /* Bitmap containing one bit for each register in the program.
 Used when performing GCSE to track which registers have been set since
!the start or end of the basic block while traversing that block.  */
  static regset reg_set_bitmap;
  
  /* Various variables for statistics gathering.  */
*** free_gcse_mem (void)
*** 183,261 
FREE_REG_SET (reg_set_bitmap);
  }
  
! struct reg_avail_info
! {
!   basic_block last_bb;
!   int last_set;
! };
! 
! static struct reg_avail_info *reg_avail_info;
! static basic_block current_bb;
! 
! /* Return nonzero if the operands of expression X are unchanged from
!INSN to the end of INSN's basic block.  */
  
  static int
! oprs_available_p (const_rtx x, const_rtx insn)
  {
!   int i, j;
!   enum rtx_code code;
!   const char *fmt;
! 
!   if (x == 0)
! return 1;
! 
!   code = GET_CODE (x);
!   switch (code)
! {
! case REG:
!   {
!   struct reg_avail_info *info = reg_avail_info[REGNO (x)];
! 
!   if (info-last_bb != current_bb)
! return 1;
!   return info-last_set  DF_INSN_LUID (insn);
!   }
! 
! case PRE_DEC:
! case PRE_INC:
! case POST_DEC:
! case POST_INC:
! case PRE_MODIFY:
! case POST_MODIFY:
!   return 0;
! 
! case PC:
! case CC0: /*FIXME*/
! case CONST:
! case CONST_INT:
! case CONST_DOUBLE:
! case CONST_FIXED:
! case CONST_VECTOR:
! case SYMBOL_REF:
! case LABEL_REF:
! case ADDR_VEC:
! case ADDR_DIFF_VEC:
!   return 1;
! 
! default:
!   break;
! }
! 
!   for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i = 0; 
i--)
! {
!   if (fmt[i] == 'e')
!   {
! if (! oprs_available_p (XEXP (x, i), insn))
!   return 0;
!   }
!   else if (fmt[i] == 'E')
!   for (j = 0; j  XVECLEN (x, i); j++)
! if (! oprs_available_p (XVECEXP (x, i, j), insn))
!   return 0;
! }
! 
!   return 1;
  }
  
  /* Hash a set of register REGNO.
--- 183,195 
FREE_REG_SET (reg_set_bitmap);
  }
  
! /* Return nonzero if register X is unchanged from INSN to the end
!of INSN's basic block.  */
  
  static int
! reg_available_p (const_rtx x, const_rtx insn ATTRIBUTE_UNUSED)
  {
!   return ! REGNO_REG_SET_P