[PATCH,RFC] CSE path following on basic blocks

Eric Botcazou ebotcazou@libertysurf.fr
Tue Nov 28 11:33:00 GMT 2006


>         * cse.c: Include cfglayout.h.
>         (struct cse_basic_block_data): Remove LAST field.
>         (struct branch_path): Remove BRANCH and TAKEN fields. Add new
>         BB field.
>         (cse_visited_basic_blocks): New static bitmap.

Probably already corrected, but not static in the patch.


>         (cse_end_of_basic_block, cse_basic_block): Remove.
>         (cse_find_path, cse_dump_path, cse_prescan_path,
>         cse_extended_basic_block): New static functions.

!   /* There is a previous path.  Make sure it started with FIRST_BB.  */
!   if (path_size)
!     gcc_assert (data->path[0].bb = first_bb);

Not sure what you're trying to do here.  Or maybe an annoying typo?


!   /* There was only one basic block in the last path.  Clear the path and
!      return, so that paths starting at another basic block can be tried.  */
!   if (path_size == 1)
!     {
!       data->path[--path_size].bb = NULL;
!       goto done;
!     }

I think it is not cse_find_path's job to care "so that paths starting at 
another basic block can be tried", it's that of its caller.  IMHO the caller 
should not expect anything from cse_find_path if it returns false and, in 
this case, must take care of re-initializing the framework.  Same a few lines 
below in the function.


!       /* Otherwise, path_size must be equal to or greater than 2, because
! 	 a previous path exists that is at least two basic blocks long.  */
!       gcc_assert (path_size >= 2);

I'm generally for assertions, but this one is useless as the 0 and 1 cases are 
short-circuited just above.

It seems to me that cse_find_path is a nop if flag_cse_follow_jumps is not set 
so it should not be invoked in this case, only cse_prescan_path should be.

But aren't you fundamentally altering the meaning of flag_cse_follow_jumps 
here?  The current CSE works on extended basic blocks independently of 
whether flag_cse_follow_jumps is set.


! #if ENABLE_CHECKING
! 		  /* We should only see blocks here that we have not
! 		     visited yet.  */
! 		  gcc_assert (!TEST_BIT (cse_visited_basic_blocks, bb->index));
! #endif

Is that really true with a DFS traversal?

>         (cse_insn): Don't CSE over setjmp calls.  Use the CFG to find
>         basic block boundaries.  Don't record jump equivalences here.

        if ((src_ent->first_reg == REGNO (SET_DEST (sets[0].rtl)))
  	  && ! find_reg_note (insn, REG_RETVAL, NULL_RTX))
  	{
  	  /* Scan for the previous nonnote insn, but stop at a basic
  	     block boundary.  */
+ 	  rtx prev = insn;
+ 	  rtx bb_head = BB_HEAD (BLOCK_FOR_INSN (insn));
  	  do
  	    {
  	      prev = PREV_INSN (prev);
  	    }
! 	  while (prev != bb_head);
  
  	  /* Do not swap the registers around if the previous instruction
  	     attaches a REG_EQUIV note to REG1.

Convoluted way to write "prev = bb_head;" :-)


*************** cse_insn (rtx insn, rtx libcall_insn)
*** 5599,5606 ****
  	     This section previously turned the REG_EQUIV into a REG_EQUAL
  	     note.  We cannot do that because REG_EQUIV may provide an
  	     uninitialized stack slot when REG_PARM_STACK_SPACE is used.  */
! 
! 	  if (prev != 0 && NONJUMP_INSN_P (prev)
  	      && GET_CODE (PATTERN (prev)) == SET
  	      && SET_DEST (PATTERN (prev)) == SET_SRC (sets[0].rtl)
  	      && ! find_reg_note (prev, REG_EQUIV, NULL_RTX))
--- 5609,5616 ----
  	     This section previously turned the REG_EQUIV into a REG_EQUAL
  	     note.  We cannot do that because REG_EQUIV may provide an
  	     uninitialized stack slot when REG_PARM_STACK_SPACE is used.  */
! 	  gcc_assert (prev);
! 	  if (NONJUMP_INSN_P (prev)
  	      && GET_CODE (PATTERN (prev)) == SET
  	      && SET_DEST (PATTERN (prev)) == SET_SRC (sets[0].rtl)
  	      && ! find_reg_note (prev, REG_EQUIV, NULL_RTX))

Please explain.


*************** cse_insn (rtx insn, rtx libcall_insn)
*** 5647,5652 ****
--- 5652,5659 ----
    prev_insn_cc0_mode = this_insn_cc0_mode;
    prev_insn = insn;
  #endif
+ 
+   return;
  }
   
Rather clever attempt to grow the size of the patch. :-)


>         (cse_main): Rewrite.  Look for extended basic block headers
>         and call cse_extended_basic_block on them until all paths that
>         start at this header are exhausted.

! 	  /* Get a reasonable extimate for the maximum number of qty's
! 	     needed for this path.  For this, we take the number of sets
! 	     and multiply that by MAX_RECOG_OPERANDS.
! 	     The old CSE path following code would use MIN(2*nsets,500)
! 	     but now that we know exactly how many insns (and hence sets)
! 	     we will see in the path, it seemed like a good idea to just
! 	     use max_qty = 2 * nsets.  Interestingly, we end up writing
! 	     past the end of qty_table with that value for max_qty.  In
! 	     other words, this was a latent bug in cse.c present since 
! 	     at least 1992.
! 	     Oh well, we just take a bigger max_qty now to play safe.  */
! 	  max_qty = ebb_data.nsets * MAX_RECOG_OPERANDS;
! 	  cse_basic_block_start = ebb_data.low_cuid;
! 	  cse_basic_block_end = ebb_data.high_cuid;

Firstly it's MAX(2*nsets,500), not MIN, in the old code.  Secondly, "a 
reasonable estimate" sounds a little worrying and the old code really
thinks it computes an upper bound.  If that's not true, we should try to 
identify the problem instead of papering over it.


>         (rest_of_handle_cse): Initialize cfglayout mode.  Verify that
>         the CFG is incrementally updated and correct after cse_main.
>         Don't call delete_trivially_dead_insns, let cfgcleanup do that.
>         (rest_of_handle_cse2): Verify the CFG here, too, after cse_main.

Why the dissymmetry between rest_of_handle_cse and rest_of_handle_cse2?

! #ifdef ENABLE_CHECKING
!   if (purge_all_dead_edges ())
!     gcc_unreachable ();
! #endif

Could you add a comment (especially in rest_of_handle_cse2)?

>         (pass_cse): Add TODO_verify_flow.
>         (pass_cse2): Likewise.

Thanks for writing down the ChangeLog.

-- 
Eric Botcazou



More information about the Gcc-patches mailing list