cond_exec patch 2/4

Richard Henderson rth@cygnus.com
Fri Apr 7 02:33:00 GMT 2000


If-conversion requires the CFG to be correct on entry, and
it also leaves the the CFG correct on exit.

Pull most of the calls to find_basic_blocks et al into 
rest_of_compilation where we can see them, and we can begin
to remove redundant invocations.

The only functional change is to the call to split_all_insns,
which I actually intended to go in with a different logical hunk,
but got lazy and didn't fix it after discovering the mistake.



r~

        * gcse.c (gcse_main): Don't rebuild the CFG here.
        (delete_null_pointer_checks): Likewise.
        * ssa.c (convert_to_ssa): Likewise.
        * toplev.c (rest_of_compilation): Do it here instead.  Combine
	sequential calls to TIMEVAR.  Consistently use `insns' instead of
	`get_insns()'.  Always split insns after reload when optimizing.

Index: gcse.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/gcse.c,v
retrieving revision 1.84
diff -c -p -d -r1.84 gcse.c
*** gcse.c	2000/03/25 18:34:02	1.84
--- gcse.c	2000/04/07 08:56:54
*************** gcse_main (f, file)
*** 669,686 ****
    /* Identify the basic block information for this function, including
       successors and predecessors.  */
    max_gcse_regno = max_reg_num ();
-   find_basic_blocks (f, max_gcse_regno, file);
-   cleanup_cfg (f);
  
    if (file)
      dump_flow_info (file);
  
    /* Return if there's nothing to do.  */
    if (n_basic_blocks <= 1)
!     {
!       free_basic_block_vars (0);
!       return 0;
!     }
  
    /* Trying to perform global optimizations on flow graphs which have
       a high connectivity will take a long time and is unlikely to be
--- 669,681 ----
    /* Identify the basic block information for this function, including
       successors and predecessors.  */
    max_gcse_regno = max_reg_num ();
  
    if (file)
      dump_flow_info (file);
  
    /* Return if there's nothing to do.  */
    if (n_basic_blocks <= 1)
!     return 0;
  
    /* Trying to perform global optimizations on flow graphs which have
       a high connectivity will take a long time and is unlikely to be
*************** gcse_main (f, file)
*** 691,700 ****
       a couple switch statements.  So we require a relatively large number
       of basic blocks and the ratio of edges to blocks to be high.  */
    if (n_basic_blocks > 1000 && n_edges / n_basic_blocks >= 20)
!     {
!       free_basic_block_vars (0);
!       return 0;
!     }
  
    /* See what modes support reg/reg copy operations.  */
    if (! can_copy_init_p)
--- 686,692 ----
       a couple switch statements.  So we require a relatively large number
       of basic blocks and the ratio of edges to blocks to be high.  */
    if (n_basic_blocks > 1000 && n_edges / n_basic_blocks >= 20)
!     return 0;
  
    /* See what modes support reg/reg copy operations.  */
    if (! can_copy_init_p)
*************** gcse_main (f, file)
*** 807,813 ****
  
    obstack_free (&gcse_obstack, NULL_PTR);
    free_reg_set_mem ();
-   free_basic_block_vars (0);
    return run_jump_opt_after_gcse;
  }
  
--- 799,804 ----
*************** delete_null_pointer_checks (f)
*** 5070,5086 ****
    int max_reg;
    struct null_pointer_info npi;
  
-   /* First break the program into basic blocks.  */
-   find_basic_blocks (f, max_reg_num (), NULL);
-   cleanup_cfg (f);
- 
    /* If we have only a single block, then there's nothing to do.  */
    if (n_basic_blocks <= 1)
!     {
!       /* Free storage allocated by find_basic_blocks.  */
!       free_basic_block_vars (0);
!       return;
!     }
  
    /* Trying to perform global optimizations on flow graphs which have
       a high connectivity will take a long time and is unlikely to be
--- 5061,5069 ----
    int max_reg;
    struct null_pointer_info npi;
  
    /* If we have only a single block, then there's nothing to do.  */
    if (n_basic_blocks <= 1)
!     return;
  
    /* Trying to perform global optimizations on flow graphs which have
       a high connectivity will take a long time and is unlikely to be
*************** delete_null_pointer_checks (f)
*** 5091,5101 ****
       a couple switch statements.  So we require a relatively large number
       of basic blocks and the ratio of edges to blocks to be high.  */
    if (n_basic_blocks > 1000 && n_edges / n_basic_blocks >= 20)
!     {
!       /* Free storage allocated by find_basic_blocks.  */
!       free_basic_block_vars (0);
!       return;
!     }
  
    /* We need four bitmaps, each with a bit for each register in each
       basic block.  */
--- 5074,5080 ----
       a couple switch statements.  So we require a relatively large number
       of basic blocks and the ratio of edges to blocks to be high.  */
    if (n_basic_blocks > 1000 && n_edges / n_basic_blocks >= 20)
!     return;
  
    /* We need four bitmaps, each with a bit for each register in each
       basic block.  */
*************** delete_null_pointer_checks (f)
*** 5151,5159 ****
        delete_null_pointer_checks_1 (block_reg, nonnull_avin,
  				    nonnull_avout, &npi);
      }
- 
-   /* Free storage allocated by find_basic_blocks.  */
-   free_basic_block_vars (0);
  
    /* Free the table of registers compared at the end of every block.  */
    free (block_reg);
--- 5130,5135 ----
Index: ssa.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ssa.c,v
retrieving revision 1.5
diff -c -p -d -r1.5 ssa.c
*** ssa.c	2000/04/06 21:22:48	1.5
--- ssa.c	2000/04/07 08:56:54
*************** convert_to_ssa()
*** 855,864 ****
    if (in_ssa_form)
      abort ();
  
-   find_basic_blocks (get_insns (), max_reg_num(), NULL);
-   /* The dominator algorithms assume all blocks are reachable; clean
-      up first.  */
-   cleanup_cfg (get_insns ());
    /* Don't eliminate dead code here.  The CFG we computed above must
       remain unchanged until we are finished emerging from SSA form --
       the phi node representation depends on it.  */
--- 855,860 ----
*************** convert_to_ssa()
*** 930,937 ****
    in_ssa_form = 1;
  
    reg_scan (get_insns (), max_reg_num (), 1);
-   find_basic_blocks (get_insns (), max_reg_num (), NULL);
-   life_analysis (get_insns (), max_reg_num (), NULL, 0);
  }
  
  
--- 926,931 ----
*************** convert_from_ssa()
*** 1818,1824 ****
    rtx insns = get_insns ();
      
    /* We need up-to-date life information.  */
-   find_basic_blocks (insns, max_reg_num (), NULL);
    life_analysis (insns, max_reg_num (), NULL, 0);
  
    /* Figure out which regs in copies and phi nodes don't conflict and
--- 1812,1817 ----
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/toplev.c,v
retrieving revision 1.314
diff -c -p -d -r1.314 toplev.c
*** toplev.c	2000/04/06 21:22:48	1.314
--- toplev.c	2000/04/07 08:56:55
*************** rest_of_compilation (decl)
*** 2881,2887 ****
  	      int saved_optimize = optimize;
  	      optimize = 0;
  	      find_exception_handler_labels ();
! 	      jump_optimize (get_insns(), !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
  			     !JUMP_AFTER_REGSCAN);
  	      optimize = saved_optimize;
  	    }
--- 2881,2887 ----
  	      int saved_optimize = optimize;
  	      optimize = 0;
  	      find_exception_handler_labels ();
! 	      jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
  			     !JUMP_AFTER_REGSCAN);
  	      optimize = saved_optimize;
  	    }
*************** rest_of_compilation (decl)
*** 2927,2935 ****
  
    /* Don't return yet if -Wreturn-type; we need to do jump_optimize.  */
    if ((rtl_dump_and_exit || flag_syntax_only) && !warn_return_type)
!     {
!       goto exit_rest_of_compilation;
!     }
  
    /* Emit code to get eh context, if needed. */
    emit_eh_context ();
--- 2927,2933 ----
  
    /* Don't return yet if -Wreturn-type; we need to do jump_optimize.  */
    if ((rtl_dump_and_exit || flag_syntax_only) && !warn_return_type)
!     goto exit_rest_of_compilation;
  
    /* Emit code to get eh context, if needed. */
    emit_eh_context ();
*************** rest_of_compilation (decl)
*** 2955,2961 ****
    insns = get_insns ();
  
    /* Copy any shared structure that should not be shared.  */
- 
    unshare_all_rtl (current_function_decl, insns);
  
  #ifdef SETJMP_VIA_SAVE_AREA
--- 2953,2958 ----
*************** rest_of_compilation (decl)
*** 2965,2977 ****
  #endif
  
    /* Instantiate all virtual registers.  */
! 
!   instantiate_virtual_regs (current_function_decl, get_insns ());
! 
!   /* See if we have allocated stack slots that are not directly addressable.
!      If so, scan all the insns and create explicit address computation
!      for all references to such slots.  */
!   /* fixup_stack_slots (); */
  
    /* Find all the EH handlers.  */
    find_exception_handler_labels ();
--- 2962,2968 ----
  #endif
  
    /* Instantiate all virtual registers.  */
!   instantiate_virtual_regs (current_function_decl, insns);
  
    /* Find all the EH handlers.  */
    find_exception_handler_labels ();
*************** rest_of_compilation (decl)
*** 2981,3007 ****
    /* Always do one jump optimization pass to ensure that JUMP_LABEL fields
       are initialized and to compute whether control can drop off the end
       of the function.  */
!   TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0));
!   TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
! 				     JUMP_AFTER_REGSCAN));
! 
!   /* Jump optimization, and the removal of NULL pointer checks, may
!      have reduced the number of instructions substantially.  CSE, and
!      future passes, allocate arrays whose dimensions involve the maximum
!      instruction UID, so if we can reduce the maximum UID we'll save big on
!      memory.  */
!   renumber_insns (rtl_dump_file);
! 
!   close_dump_file (DFI_jump, print_rtl, insns);
  
    /* Now is when we stop if -fsyntax-only and -Wreturn-type.  */
    if (rtl_dump_and_exit || flag_syntax_only || DECL_DEFER_OUTPUT (decl))
!     goto exit_rest_of_compilation;
  
!   /* Try to identify useless null pointer tests and delete them.  */
!   if (flag_delete_null_pointer_checks)
!     TIMEVAR (jump_time, delete_null_pointer_checks (get_insns ()));
  
    if (ggc_p)
      ggc_collect ();
  
--- 2972,3011 ----
    /* Always do one jump optimization pass to ensure that JUMP_LABEL fields
       are initialized and to compute whether control can drop off the end
       of the function.  */
!   TIMEVAR (jump_time,
! 	   {
! 	     reg_scan (insns, max_reg_num (), 0);
! 	     jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
! 			    JUMP_AFTER_REGSCAN);
! 	   });
  
    /* Now is when we stop if -fsyntax-only and -Wreturn-type.  */
    if (rtl_dump_and_exit || flag_syntax_only || DECL_DEFER_OUTPUT (decl))
!     {
!       close_dump_file (DFI_jump, print_rtl, insns);
!       goto exit_rest_of_compilation;
!     }
  
!   TIMEVAR (jump_time,
! 	   {
! 	     /* Try to identify useless null pointer tests and delete them.  */
! 	     if (flag_delete_null_pointer_checks)
! 	       {
! 		 find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
! 		 cleanup_cfg (insns);
! 		 delete_null_pointer_checks (insns);
! 	       }
  
+ 	     /* Jump optimization, and the removal of NULL pointer checks,
+ 		may have reduced the number of instructions substantially. 
+ 		CSE, and future passes, allocate arrays whose dimensions
+ 		involve the maximum instruction UID, so if we can reduce
+ 		the maximum UID we'll save big on memory.  */
+ 	     renumber_insns (rtl_dump_file);
+ 	   });
+ 
+   close_dump_file (DFI_jump, print_rtl, insns);
+ 
    if (ggc_p)
      ggc_collect ();
  
*************** rest_of_compilation (decl)
*** 3021,3026 ****
--- 3025,3031 ----
  
        TIMEVAR (cse_time, tem = cse_main (insns, max_reg_num (),
  					 0, rtl_dump_file));
+ 
        /* If we are not running the second CSE pass, then we are no longer
  	 expecting CSE to be run.  */
        cse_not_expected = !flag_rerun_cse_after_loop;
*************** rest_of_compilation (decl)
*** 3036,3042 ****
  
        /* Try to identify useless null pointer tests and delete them.  */
        if (flag_delete_null_pointer_checks)
! 	TIMEVAR (jump_time, delete_null_pointer_checks (get_insns ()));
  
        /* The second pass of jump optimization is likely to have
           removed a bunch more instructions.  */
--- 3041,3052 ----
  
        /* Try to identify useless null pointer tests and delete them.  */
        if (flag_delete_null_pointer_checks)
! 	TIMEVAR (jump_time,
! 		 {
! 		   find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
! 		   cleanup_cfg (insns);
! 		   delete_null_pointer_checks (insns);
! 		 });
  
        /* The second pass of jump optimization is likely to have
           removed a bunch more instructions.  */
*************** rest_of_compilation (decl)
*** 3055,3075 ****
    if (ggc_p)
      ggc_collect ();
  
!   if (flag_ssa)
      {
        open_dump_file (DFI_ssa, decl);
!       TIMEVAR (to_ssa_time, convert_to_ssa ());
        close_dump_file (DFI_ssa, print_rtl_with_bb, insns);
  
        open_dump_file (DFI_ussa, decl);
-       TIMEVAR (from_ssa_time, convert_from_ssa ());
-       /* New registers have been created.  Rescan their usage.  */
-       reg_scan (insns, max_reg_num (), 1);
-       close_dump_file (DFI_ussa, print_rtl_with_bb, insns);
  
!       /* Life analysis used in SSA adds log_links but these shouldn't
! 	 be there until the flow stage, so clear them away.  */
!       clear_log_links (insns);
  
        if (ggc_p)
  	ggc_collect ();
--- 3065,3099 ----
    if (ggc_p)
      ggc_collect ();
  
!   if (optimize > 0 && flag_ssa)
      {
        open_dump_file (DFI_ssa, decl);
! 
!       TIMEVAR (to_ssa_time,
! 	       {
! 		 find_basic_blocks (insns, max_reg_num(), rtl_dump_file);
! 		 cleanup_cfg (insns);
! 		 convert_to_ssa ();
! 	       });
! 
        close_dump_file (DFI_ssa, print_rtl_with_bb, insns);
  
        open_dump_file (DFI_ussa, decl);
  
!       TIMEVAR (from_ssa_time,
! 	       {
! 		 convert_from_ssa ();
! 
! 		 /* New registers have been created.  Rescan their usage.  */
! 		 reg_scan (insns, max_reg_num (), 1);
! 
! 		 /* Life analysis used in SSA adds log_links but these
! 		    shouldn't be there until the flow stage, so clear
! 		    them away.  */
! 		 clear_log_links (insns);
! 	       });
! 
!       close_dump_file (DFI_ussa, print_rtl_with_bb, insns);
  
        if (ggc_p)
  	ggc_collect ();
*************** rest_of_compilation (decl)
*** 3081,3087 ****
      {
        open_dump_file (DFI_gcse, decl);
  
!       TIMEVAR (gcse_time, tem = gcse_main (insns, rtl_dump_file));
  
        /* If gcse altered any jumps, rerun jump optimizations to clean
  	 things up.  */
--- 3105,3116 ----
      {
        open_dump_file (DFI_gcse, decl);
  
!       TIMEVAR (gcse_time,
! 	       {
! 		 find_basic_blocks (insns, max_reg_num(), rtl_dump_file);
! 		 cleanup_cfg (insns);
! 		 tem = gcse_main (insns, rtl_dump_file);
! 	       });
  
        /* If gcse altered any jumps, rerun jump optimizations to clean
  	 things up.  */
*************** rest_of_compilation (decl)
*** 3097,3102 ****
--- 3126,3132 ----
        if (ggc_p)
  	ggc_collect ();
      }
+ 
    /* Move constant computations out of loops.  */
  
    if (optimize > 0)
*************** rest_of_compilation (decl)
*** 3111,3118 ****
  	       /* We only want to perform unrolling once.  */
  	       
  	       loop_optimize (insns, rtl_dump_file, 0, 0);
! 	       
! 	
  	       /* The first call to loop_optimize makes some instructions
  		  trivially dead.  We delete those instructions now in the
  		  hope that doing so will make the heuristics in loop work
--- 3141,3147 ----
  	       /* We only want to perform unrolling once.  */
  	       
  	       loop_optimize (insns, rtl_dump_file, 0, 0);
! 
  	       /* The first call to loop_optimize makes some instructions
  		  trivially dead.  We delete those instructions now in the
  		  hope that doing so will make the heuristics in loop work
*************** rest_of_compilation (decl)
*** 3148,3161 ****
  	     the second CSE pass to do a better job.  Jump_optimize can change
  	     max_reg_num so we must rerun reg_scan afterwards.
  	     ??? Rework to not call reg_scan so often.  */
! 	  TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0));
! 	  TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
! 					     !JUMP_NOOP_MOVES,
! 					     JUMP_AFTER_REGSCAN));
  	  
! 	  TIMEVAR (cse2_time, reg_scan (insns, max_reg_num (), 0));
! 	  TIMEVAR (cse2_time, tem = cse_main (insns, max_reg_num (),
! 					      1, rtl_dump_file));
  	  if (tem)
  	    TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
  					       !JUMP_NOOP_MOVES,
--- 3177,3196 ----
  	     the second CSE pass to do a better job.  Jump_optimize can change
  	     max_reg_num so we must rerun reg_scan afterwards.
  	     ??? Rework to not call reg_scan so often.  */
! 	  TIMEVAR (jump_time,
! 		   {
! 		     reg_scan (insns, max_reg_num (), 0);
! 		     jump_optimize (insns, !JUMP_CROSS_JUMP,
! 				    !JUMP_NOOP_MOVES, JUMP_AFTER_REGSCAN);
! 		   });
  	  
! 	  TIMEVAR (cse2_time,
! 		   {
! 		     reg_scan (insns, max_reg_num (), 0);
! 		     tem = cse_main (insns, max_reg_num (),
! 				     1, rtl_dump_file);
! 		   });
! 
  	  if (tem)
  	    TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
  					       !JUMP_NOOP_MOVES,
*************** rest_of_compilation (decl)
*** 3166,3173 ****
  	{
  	  /* This pass of jump threading straightens out code
  	     that was kinked by loop optimization.  */
! 	  TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0));
! 	  TIMEVAR (jump_time, thread_jumps (insns, max_reg_num (), 0));
  	}
  
        close_dump_file (DFI_cse2, print_rtl, insns);
--- 3201,3211 ----
  	{
  	  /* This pass of jump threading straightens out code
  	     that was kinked by loop optimization.  */
! 	  TIMEVAR (jump_time,
! 		   {
! 		     reg_scan (insns, max_reg_num (), 0);
! 		     thread_jumps (insns, max_reg_num (), 0);
! 		   });
  	}
  
        close_dump_file (DFI_cse2, print_rtl, insns);
*************** rest_of_compilation (decl)
*** 3180,3190 ****
      {
        open_dump_file (DFI_bp, decl);
  
!       TIMEVAR
! 	(branch_prob_time,
! 	 {
! 	   branch_prob (insns, rtl_dump_file);
! 	 });
  
        close_dump_file (DFI_bp, print_rtl, insns);
  
--- 3218,3227 ----
      {
        open_dump_file (DFI_bp, decl);
  
!       TIMEVAR (branch_prob_time,
! 	       {
! 		 branch_prob (insns, rtl_dump_file);
! 	       });
  
        close_dump_file (DFI_bp, print_rtl, insns);
  
*************** rest_of_compilation (decl)
*** 3321,3328 ****
  
    if (dump_file[DFI_lreg].enabled)
      {
!       TIMEVAR (dump_time, dump_flow_info (rtl_dump_file));
!       TIMEVAR (dump_time, dump_local_alloc (rtl_dump_file));
  
        close_dump_file (DFI_lreg, print_rtl_with_bb, insns);
      }
--- 3358,3368 ----
  
    if (dump_file[DFI_lreg].enabled)
      {
!       TIMEVAR (dump_time,
! 	       {
! 		 dump_flow_info (rtl_dump_file);
! 		 dump_local_alloc (rtl_dump_file);
! 	       });
  
        close_dump_file (DFI_lreg, print_rtl_with_bb, insns);
      }
*************** rest_of_compilation (decl)
*** 3356,3368 ****
    if (optimize > 0)
      reload_cse_regs (insns);
  
!   /* If optimizing and we are performing instruction scheduling after
!      reload, then go ahead and split insns now since we are about to
!      recompute flow information anyway.
! 
!      reload_cse_regs may expose more splitting opportunities, expecially
!      for double-word operations.  */
!   if (optimize > 0 && flag_schedule_insns_after_reload)
      split_all_insns (0);
  
    /* Register allocation and reloading may have turned an indirect jump into
--- 3396,3404 ----
    if (optimize > 0)
      reload_cse_regs (insns);
  
!   /* If optimizing, then go ahead and split insns now since we are about
!      to recompute flow information anyway.  */
!   if (optimize > 0)
      split_all_insns (0);
  
    /* Register allocation and reloading may have turned an indirect jump into
*************** rest_of_compilation (decl)
*** 3382,3387 ****
--- 3418,3424 ----
    
    TIMEVAR (flow2_time,
  	   {
+ 	     jump_optimize_minimal (insns);
  	     find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
  	   });
  
*************** rest_of_compilation (decl)
*** 3518,3527 ****
  
       Note this must run before reg-stack because of death note (ab)use
       in the ia32 backend.  */
!   TIMEVAR (shorten_branch_time,
! 	   {
! 	     shorten_branches (get_insns ());
! 	   });
  
  #ifdef STACK_REGS
    open_dump_file (DFI_stack, decl);
--- 3555,3561 ----
  
       Note this must run before reg-stack because of death note (ab)use
       in the ia32 backend.  */
!   TIMEVAR (shorten_branch_time, shorten_branches (get_insns ()));
  
  #ifdef STACK_REGS
    open_dump_file (DFI_stack, decl);


More information about the Gcc-patches mailing list