[dataflow] Don't rescan everything after CSE

Kenneth Zadeck zadeck@naturalbridge.com
Tue Mar 6 16:07:00 GMT 2007


Paolo Bonzini wrote:
> This saves ~1% of compilation time.
>
> More ideas that I have, but did not implement are:
>
> 1) delay computation of LR/UR until where we did it in the trunk.  fwprop and GCSE do not need it, for example.
>
> 2) don't update REG_DEAD/REG_UNUSED notes for patches that don't need it.  Updating them could/should be a changeable flag.
>
> Bootstrapped/regtested i686-pc-linux-gnu.
>
> Paolo
>   
>   
If this really works, it is ok to commit.  I would like see it
bootstrapped on more platforms.  My skepticism is because Steven and I
both tried to do this and we were never able to track down all of the
places where insns were being modified.

Do you have access to a ppc or an ia-64?  You can get an ia-64 account
from willy.

> ------------------------------------------------------------------------
>
> 2007-03-06  Paolo Bonzini  <bonzini@gnu.org>
>
> 	* cse.c (validate_canon_reg): Don't do anything if *XLOC is NULL.  Assert
> 	it is only called with insn != 0 and it never resets something non-NULL to
> 	NULL.  Always use validate_change.
> 	(cse_insn): Always call canon_reg with an INSN except when it is used on
> 	a REG.  When processing notes, first canonicalize, then fold, and call
> 	df_notes_rescan.
> 	(cse_process_notes): Rename to cse_process_notes_1, add CHANGED parameter.
> 	(cse_process_notes_1): Wrapper around cse_process_notes to set the CHANGED
> 	parameter.
> 	(cse_extended_basic_block): Adjust call to cse_process_notes and use result
> 	to call df_notes_rescan.
> 	(cse_main): Set deferred insn rescanning flag, don't rescan on exit.
> 	(pass_cse2): Add TODO_df_finish.
> 	* gcse.c (pass_gcse): Likewise.
>
> Index: cse.c
> ===================================================================
> --- cse.c	(revision 122403)
> +++ cse.c	(working copy)
> @@ -585,7 +585,7 @@ static void record_jump_cond (enum rtx_c
>  static void cse_insn (rtx, rtx);
>  static void cse_prescan_path (struct cse_basic_block_data *);
>  static void invalidate_from_clobbers (rtx);
> -static rtx cse_process_notes (rtx, rtx);
> +static rtx cse_process_notes (rtx, rtx, bool *);
>  static void cse_extended_basic_block (struct cse_basic_block_data *);
>  static void count_reg_usage (rtx, int *, rtx, int);
>  static int check_for_label_ref (rtx *, void *);
> @@ -2642,14 +2642,15 @@ cse_rtx_varies_p (rtx x, int from_alias)
>  static void
>  validate_canon_reg (rtx *xloc, rtx insn)
>  {
> -  rtx new = canon_reg (*xloc, insn);
> +  if (*xloc)
> +    {
> +      rtx new = canon_reg (*xloc, insn);
>  
> -  /* If replacing pseudo with hard reg or vice versa, ensure the
> -     insn remains valid.  Likewise if the insn has MATCH_DUPs.  */
> -  if (insn != 0 && new != 0)
> -    validate_change (insn, xloc, new, 1);
> -  else
> -    *xloc = new;
> +      /* If replacing pseudo with hard reg or vice versa, ensure the
> +         insn remains valid.  Likewise if the insn has MATCH_DUPs.  */
> +      gcc_assert (insn && new);
> +      validate_change (insn, xloc, new, 1);
> +    }
>  }
>  
>  /* Canonicalize an expression:
> @@ -4119,12 +4120,12 @@ cse_insn (rtx insn, rtx libcall_insn)
>  		 This does nothing when a register is clobbered
>  		 because we have already invalidated the reg.  */
>  	      if (MEM_P (XEXP (y, 0)))
> -		canon_reg (XEXP (y, 0), NULL_RTX);
> +		canon_reg (XEXP (y, 0), insn);
>  	    }
>  	  else if (GET_CODE (y) == USE
>  		   && ! (REG_P (XEXP (y, 0))
>  			 && REGNO (XEXP (y, 0)) < FIRST_PSEUDO_REGISTER))
> -	    canon_reg (y, NULL_RTX);
> +	    canon_reg (y, insn);
>  	  else if (GET_CODE (y) == CALL)
>  	    {
>  	      /* The result of apply_change_group can be ignored; see
> @@ -4138,14 +4139,14 @@ cse_insn (rtx insn, rtx libcall_insn)
>    else if (GET_CODE (x) == CLOBBER)
>      {
>        if (MEM_P (XEXP (x, 0)))
> -	canon_reg (XEXP (x, 0), NULL_RTX);
> +	canon_reg (XEXP (x, 0), insn);
>      }
>  
>    /* Canonicalize a USE of a pseudo register or memory location.  */
>    else if (GET_CODE (x) == USE
>  	   && ! (REG_P (XEXP (x, 0))
>  		 && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER))
> -    canon_reg (XEXP (x, 0), NULL_RTX);
> +    canon_reg (XEXP (x, 0), insn);
>    else if (GET_CODE (x) == CALL)
>      {
>        /* The result of apply_change_group can be ignored; see canon_reg.  */
> @@ -4163,8 +4164,12 @@ cse_insn (rtx insn, rtx libcall_insn)
>        && (! rtx_equal_p (XEXP (tem, 0), SET_SRC (sets[0].rtl))
>  	  || GET_CODE (SET_DEST (sets[0].rtl)) == STRICT_LOW_PART))
>      {
> -      src_eqv = fold_rtx (canon_reg (XEXP (tem, 0), NULL_RTX), insn);
> +      /* The result of apply_change_group can be ignored; see canon_reg.  */
> +      canon_reg (XEXP (tem, 0), insn);
> +      apply_change_group ();
> +      src_eqv = fold_rtx (XEXP (tem, 0), insn);
>        XEXP (tem, 0) = src_eqv;
> +      df_notes_rescan (insn);
>      }
>  
>    /* Canonicalize sources and addresses of destinations.
> @@ -4829,6 +4834,7 @@ cse_insn (rtx insn, rtx libcall_insn)
>  		    XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0),
>  							   sets[i].orig_src,
>  							   copy_rtx (new));
> +		  df_notes_rescan (libcall_insn);
>  		}
>  
>  	      /* The result of apply_change_group can be ignored; see
> @@ -4947,6 +4953,7 @@ cse_insn (rtx insn, rtx libcall_insn)
>  	      /* Record the actual constant value in a REG_EQUAL note,
>  		 making a new one if one does not already exist.  */
>  	      set_unique_reg_note (insn, REG_EQUAL, src_const);
> +	      df_notes_rescan (insn);
>  	    }
>  	}
>  
> @@ -5683,7 +5690,7 @@ invalidate_from_clobbers (rtx x)
>     Return the replacement for X.  */
>  
>  static rtx
> -cse_process_notes (rtx x, rtx object)
> +cse_process_notes_1 (rtx x, rtx object, bool *changed)
>  {
>    enum rtx_code code = GET_CODE (x);
>    const char *fmt = GET_RTX_FORMAT (code);
> @@ -5704,22 +5711,22 @@ cse_process_notes (rtx x, rtx object)
>  
>      case MEM:
>        validate_change (x, &XEXP (x, 0),
> -		       cse_process_notes (XEXP (x, 0), x), 0);
> +		       cse_process_notes (XEXP (x, 0), x, changed), 0);
>        return x;
>  
>      case EXPR_LIST:
>      case INSN_LIST:
>        if (REG_NOTE_KIND (x) == REG_EQUAL)
> -	XEXP (x, 0) = cse_process_notes (XEXP (x, 0), NULL_RTX);
> +	XEXP (x, 0) = cse_process_notes (XEXP (x, 0), NULL_RTX, changed);
>        if (XEXP (x, 1))
> -	XEXP (x, 1) = cse_process_notes (XEXP (x, 1), NULL_RTX);
> +	XEXP (x, 1) = cse_process_notes (XEXP (x, 1), NULL_RTX, changed);
>        return x;
>  
>      case SIGN_EXTEND:
>      case ZERO_EXTEND:
>      case SUBREG:
>        {
> -	rtx new = cse_process_notes (XEXP (x, 0), object);
> +	rtx new = cse_process_notes (XEXP (x, 0), object, changed);
>  	/* We don't substitute VOIDmode constants into these rtx,
>  	   since they would impede folding.  */
>  	if (GET_MODE (new) != VOIDmode)
> @@ -5755,10 +5762,20 @@ cse_process_notes (rtx x, rtx object)
>    for (i = 0; i < GET_RTX_LENGTH (code); i++)
>      if (fmt[i] == 'e')
>        validate_change (object, &XEXP (x, i),
> -		       cse_process_notes (XEXP (x, i), object), 0);
> +		       cse_process_notes (XEXP (x, i), object, changed), 0);
>  
>    return x;
>  }
> +
> +static rtx
> +cse_process_notes (rtx x, rtx object, bool *changed)
> +{
> +  rtx new = cse_process_notes_1 (x, object, changed);
> +  if (new != x)
> +    *changed = true;
> +  return new;
> +}
> +
>  

>  /* Find a path in the CFG, starting with FIRST_BB to perform CSE on.
>  
> @@ -6006,8 +6023,13 @@ cse_extended_basic_block (struct cse_bas
>  	      /* Process notes first so we have all notes in canonical forms
>  		 when looking for duplicate operations.  */
>  	      if (REG_NOTES (insn))
> -		REG_NOTES (insn) = cse_process_notes (REG_NOTES (insn),
> -						      NULL_RTX);
> +		{
> +		  bool changed = false;
> +		  REG_NOTES (insn) = cse_process_notes (REG_NOTES (insn),
> +						        NULL_RTX, &changed);
> +		  if (changed)
> +		    df_notes_rescan (insn);
> +		}
>  
>  	      /* Track when we are inside in LIBCALL block.  Inside such
>  		 a block we do not want to record destinations.  The last
> @@ -6181,7 +6203,10 @@ cse_main (rtx f ATTRIBUTE_UNUSED, int nr
>    int i, n_blocks;
>  
>    if (df)
> -    df_set_flags (DF_NO_INSN_RESCAN);
> +    {
> +      df_analyze ();
> +      df_set_flags (DF_DEFER_INSN_RESCAN);
> +    }
>  
>    init_cse_reg_info (nregs);
>  
> @@ -6264,11 +6289,6 @@ cse_main (rtx f ATTRIBUTE_UNUSED, int nr
>    sbitmap_free (reg_used_in_multiple_bb);
>    free (rc_order);
>    rtl_hooks = general_rtl_hooks;
> -  if (df)
> -    {
> -      df_clear_flags (DF_NO_INSN_RESCAN);
> -      df_insn_rescan_all ();
> -    }
>  
>    return cse_jumps_altered || recorded_label_ref;
>  }
> @@ -7080,6 +7100,7 @@ struct tree_opt_pass pass_cse2 =
>    0,                                    /* properties_provided */
>    0,                                    /* properties_destroyed */
>    0,                                    /* todo_flags_start */
> +  TODO_df_finish |
>    TODO_dump_func |
>    TODO_ggc_collect |
>    TODO_verify_flow,                     /* todo_flags_finish */
> Index: gcse.c
> ===================================================================
> --- gcse.c	(revision 122403)
> +++ gcse.c	(working copy)
> @@ -6731,6 +6731,7 @@ struct tree_opt_pass pass_gcse =
>    0,                                    /* properties_provided */
>    0,                                    /* properties_destroyed */
>    0,                                    /* todo_flags_start */
> +  TODO_df_finish |
>    TODO_dump_func |
>    TODO_verify_flow | TODO_ggc_collect,  /* todo_flags_finish */
>    'G'                                   /* letter */
>   




More information about the Gcc-patches mailing list