flow tweeks

Richard Henderson rth@cygnus.com
Wed Mar 31 12:46:00 GMT 1999


There was a comment I'd left in find_basic_blocks,

  /* ??? Do this conditionally, or make this another entry point?  */
  delete_unreachable_blocks ();

Well, one of the optimization bits in Cygnus' internal tree
fell over on this.  So here's me putting in a bit to actually
make it conditional.

Long-term I'd like to never recalculate basic blocks.  They're
too easy to just keep up to date all the time.


r~


Wed Mar 31 12:32:43 1999  Richard Henderson  <rth@cygnus.com>

        * flow.c (find_basic_blocks): New argument `do_cleanup'.
        Conditionally call delete_unreachable_blocks.
        (free_basic_block_vars): Zero ENTRY/EXIT data.
        (allocate_for_life_analysis): Kill.  Split into...
        (allocate_bb_life_data, allocate_reg_life_data): ... new functions.
        (life_analysis_1): Update.
        * gcse.c (gcse_main): Update find_basic_blocks call.
        * toplev.c (rest_of_compilation): Likewise.
        * stupid.c (stupid_life_analysis): Update life data calls.
        * rtl.h, output.h: Update prototypes.

Index: flow.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/flow.c,v
retrieving revision 1.170
diff -c -p -d -r1.170 flow.c
*** flow.c	1999/03/27 23:21:02	1.170
--- flow.c	1999/03/31 20:28:33
*************** static void new_insn_dead_notes		PROTO (
*** 354,363 ****
     numbers in use.  */
  
  void
! find_basic_blocks (f, nregs, file)
       rtx f;
       int nregs ATTRIBUTE_UNUSED;
       FILE *file ATTRIBUTE_UNUSED;
  {
    rtx *bb_eh_end;
    int max_uid;
--- 354,364 ----
     numbers in use.  */
  
  void
! find_basic_blocks (f, nregs, file, do_cleanup)
       rtx f;
       int nregs ATTRIBUTE_UNUSED;
       FILE *file ATTRIBUTE_UNUSED;
+      int do_cleanup;
  {
    rtx *bb_eh_end;
    int max_uid;
*************** find_basic_blocks (f, nregs, file)
*** 416,424 ****
    make_edges (label_value_list, bb_eh_end);
  
    /* Delete unreachable blocks.  */
-   /* ??? Do this conditionally, or make this another entry point?  */
  
!   delete_unreachable_blocks ();
  
    /* Mark critical edges.  */
  
--- 417,425 ----
    make_edges (label_value_list, bb_eh_end);
  
    /* Delete unreachable blocks.  */
  
!   if (do_cleanup)
!     delete_unreachable_blocks ();
  
    /* Mark critical edges.  */
  
*************** free_basic_block_vars (keep_head_end_p)
*** 2111,2116 ****
--- 2112,2122 ----
        clear_edges ();
        VARRAY_FREE (basic_block_info);
        n_basic_blocks = 0;
+ 
+       ENTRY_BLOCK_PTR->aux = NULL;
+       ENTRY_BLOCK_PTR->global_live_at_end = NULL;
+       EXIT_BLOCK_PTR->aux = NULL;
+       EXIT_BLOCK_PTR->global_live_at_start = NULL;
      }
  }
  
*************** life_analysis_1 (f, nregs)
*** 2312,2318 ****
    /* Allocate and zero out many data structures
       that will record the data from lifetime analysis.  */
  
!   allocate_for_life_analysis ();
  
    reg_next_use = (rtx *) alloca (nregs * sizeof (rtx));
    memset (reg_next_use, 0, nregs * sizeof (rtx));
--- 2318,2325 ----
    /* Allocate and zero out many data structures
       that will record the data from lifetime analysis.  */
  
!   allocate_reg_life_data ();
!   allocate_bb_life_data ();
  
    reg_next_use = (rtx *) alloca (nregs * sizeof (rtx));
    memset (reg_next_use, 0, nregs * sizeof (rtx));
*************** life_analysis_1 (f, nregs)
*** 2525,2545 ****
     of life analysis.  Not static since used also for stupid life analysis.  */
  
  void
! allocate_for_life_analysis ()
  {
    register int i;
  
-   /* Recalculate the register space, in case it has grown.  Old style
-      vector oriented regsets would set regset_{size,bytes} here also.  */
-   allocate_reg_info (max_regno, FALSE, FALSE);
- 
-   /* Because both reg_scan and flow_analysis want to set up the REG_N_SETS
-      information, explicitly reset it here.  The allocation should have
-      already happened on the previous reg_scan pass.  Make sure in case
-      some more registers were allocated.  */
-   for (i = 0; i < max_regno; i++)
-     REG_N_SETS (i) = 0;
- 
    for (i = 0; i < n_basic_blocks; i++)
      {
        basic_block bb = BASIC_BLOCK (i);
--- 2532,2541 ----
     of life analysis.  Not static since used also for stupid life analysis.  */
  
  void
! allocate_bb_life_data ()
  {
    register int i;
  
    for (i = 0; i < n_basic_blocks; i++)
      {
        basic_block bb = BASIC_BLOCK (i);
*************** allocate_for_life_analysis ()
*** 2555,2561 ****
      = OBSTACK_ALLOC_REG_SET (function_obstack);
  
    regs_live_at_setjmp = OBSTACK_ALLOC_REG_SET (function_obstack);
!   CLEAR_REG_SET (regs_live_at_setjmp);
  }
  
  /* Make each element of VECTOR point at a regset.  The vector has
--- 2551,2573 ----
      = OBSTACK_ALLOC_REG_SET (function_obstack);
  
    regs_live_at_setjmp = OBSTACK_ALLOC_REG_SET (function_obstack);
! }
! 
! void
! allocate_reg_life_data ()
! {
!   int i;
! 
!   /* Recalculate the register space, in case it has grown.  Old style
!      vector oriented regsets would set regset_{size,bytes} here also.  */
!   allocate_reg_info (max_regno, FALSE, FALSE);
! 
!   /* Because both reg_scan and flow_analysis want to set up the REG_N_SETS
!      information, explicitly reset it here.  The allocation should have
!      already happened on the previous reg_scan pass.  Make sure in case
!      some more registers were allocated.  */
!   for (i = 0; i < max_regno; i++)
!     REG_N_SETS (i) = 0;
  }
  
  /* Make each element of VECTOR point at a regset.  The vector has
*************** cygnus_merge_blocks (f)
*** 5086,5092 ****
      return;
    
    /* First break the program into basic blocks.  */
!   find_basic_blocks (f, max_reg_num (), NULL);
  
    /* If we have only a single block, then there's nothing to do.  */
    if (n_basic_blocks <= 1)
--- 5098,5104 ----
      return;
    
    /* First break the program into basic blocks.  */
!   find_basic_blocks (f, max_reg_num (), NULL, 1);
  
    /* If we have only a single block, then there's nothing to do.  */
    if (n_basic_blocks <= 1)
Index: gcse.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/gcse.c,v
retrieving revision 1.62
diff -c -p -d -r1.62 gcse.c
*** gcse.c	1999/03/21 15:47:00	1.62
--- gcse.c	1999/03/31 20:28:34
*************** gcse_main (f, file)
*** 665,671 ****
    /* 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);
  
    /* Return if there's nothing to do.  */
    if (n_basic_blocks <= 1)
--- 665,671 ----
    /* 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, 1);
  
    /* Return if there's nothing to do.  */
    if (n_basic_blocks <= 1)
*************** gcse_main (f, file)
*** 698,704 ****
      {
        /* Call find_basic_blocks to compute the new number of basic
  	 blocks and new edge data.  */
!       find_basic_blocks (f, max_gcse_regno, file);
  
        /* This leaks memory until the end of this function.  I don't see
  	 a good way to fix this without introducing more complexity in
--- 698,704 ----
      {
        /* Call find_basic_blocks to compute the new number of basic
  	 blocks and new edge data.  */
!       find_basic_blocks (f, max_gcse_regno, file, 1);
  
        /* This leaks memory until the end of this function.  I don't see
  	 a good way to fix this without introducing more complexity in
*************** delete_null_pointer_checks (f)
*** 5535,5541 ****
    sbitmap *nonnull_avin, *nonnull_avout;
    
    /* First break the program into basic blocks.  */
!   find_basic_blocks (f, max_reg_num (), NULL);
  
    /* If we have only a single block, then there's nothing to do.  */
    if (n_basic_blocks <= 1)
--- 5535,5541 ----
    sbitmap *nonnull_avin, *nonnull_avout;
    
    /* First break the program into basic blocks.  */
!   find_basic_blocks (f, max_reg_num (), NULL, 1);
  
    /* If we have only a single block, then there's nothing to do.  */
    if (n_basic_blocks <= 1)
Index: output.h
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/output.h,v
retrieving revision 1.48
diff -c -p -d -r1.48 output.h
*** output.h	1999/03/16 23:58:09	1.48
--- output.h	1999/03/31 20:28:34
*************** extern int only_leaf_regs_used	PROTO((vo
*** 124,134 ****
  extern void leaf_renumber_regs_insn PROTO((rtx));
  
  /* Functions in flow.c */
! extern void allocate_for_life_analysis	PROTO((void));
  extern int regno_uninitialized		PROTO((int));
  extern int regno_clobbered_at_setjmp	PROTO((int));
  extern void dump_flow_info		PROTO((FILE *));
! extern void find_basic_blocks           PROTO((rtx, int, FILE *));
  extern void free_basic_block_vars       PROTO((int));
  extern void set_block_num               PROTO((rtx, int));
  extern void life_analysis               PROTO((rtx, int, FILE *));
--- 124,135 ----
  extern void leaf_renumber_regs_insn PROTO((rtx));
  
  /* Functions in flow.c */
! extern void allocate_bb_life_data	PROTO((void));
! extern void allocate_reg_life_data	PROTO((void));
  extern int regno_uninitialized		PROTO((int));
  extern int regno_clobbered_at_setjmp	PROTO((int));
  extern void dump_flow_info		PROTO((FILE *));
! extern void find_basic_blocks           PROTO((rtx, int, FILE *, int));
  extern void free_basic_block_vars       PROTO((int));
  extern void set_block_num               PROTO((rtx, int));
  extern void life_analysis               PROTO((rtx, int, FILE *));
Index: range.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/range.c,v
retrieving revision 1.13
diff -c -p -d -r1.13 range.c
*** range.c	1999/03/05 20:43:31	1.13
--- range.c	1999/03/31 20:28:34
*************** range_update_basic_block (stream, first_
*** 1101,1106 ****
--- 1101,1111 ----
    for (i = 0; i < old_n_basic_blocks; i++)
      {
        rtx p = emit_note_before (NOTE_INSN_LIVE, BLOCK_HEAD (i));
+ 
+       /* ??? Note that we are putting a pointer to the current
+ 	 global_live_at_start info into the rtl.  When we reallocate 
+ 	 basic block below, we need to create new reg sets to avoid
+ 	 sharing.  */
        NOTE_LIVE_INFO (p) = gen_rtx (RANGE_LIVE, VOIDmode,
  				    BASIC_BLOCK (i)->global_live_at_start, i);
        map_bb[i] = -1;
*************** range_update_basic_block (stream, first_
*** 1121,1135 ****
      putc ('\n', stream);
  
    /* Recalculate the basic blocks.  */
!   find_basic_blocks (first_insn, max_regno, stream);
    free_basic_block_vars (TRUE);
  
!   /* Restore the live information.  We assume that flow will find either a
!      previous start of a basic block, or the newly created insn blocks as
!      the start of the new basic blocks.  */
  
!   if (old_n_basic_blocks != n_basic_blocks)
!     allocate_for_life_analysis ();
  
    block = 0;
    in_block_p = FALSE;
--- 1126,1139 ----
      putc ('\n', stream);
  
    /* Recalculate the basic blocks.  */
!   find_basic_blocks (first_insn, max_regno, stream, 0);
    free_basic_block_vars (TRUE);
  
!   /* Reallocate the life information.  
!      ??? We're assuming we get new data structures so that we avoid sharing
!      with the old data structures squirreled away above.  */
  
!   allocate_bb_life_data ();
  
    block = 0;
    in_block_p = FALSE;
*************** range_update_basic_block (stream, first_
*** 1212,1217 ****
--- 1216,1229 ----
  	  if (block < n_basic_blocks)
  	    {
  	      block_start = BLOCK_HEAD (block);
+ 
+ 	      /* We want to skip the NOTE_INSN_BASIC_BLOCK notes emitted by
+ 		 flow, so that the new_bb[i].first_insn test above will
+ 		 work.  */
+ 	      if (GET_CODE (block_start) == NOTE
+ 		  && NOTE_LINE_NUMBER (block_start) == NOTE_INSN_BASIC_BLOCK)
+ 		block_start = NEXT_INSN (block_start);
+ 
  	      block_end = BLOCK_END (block);
  	    }
  	  else
Index: rtl.h
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/rtl.h,v
retrieving revision 1.120
diff -c -p -d -r1.120 rtl.h
*** rtl.h	1999/03/25 20:09:10	1.120
--- rtl.h	1999/03/31 20:28:34
*************** extern void stupid_life_analysis	PROTO (
*** 1458,1464 ****
  #endif
  
  /* In flow.c */
! extern void allocate_for_life_analysis	PROTO ((void));
  extern void recompute_reg_usage		PROTO ((rtx, int));
  #ifdef BUFSIZ
  extern void dump_flow_info		PROTO ((FILE *));
--- 1458,1465 ----
  #endif
  
  /* In flow.c */
! extern void allocate_bb_life_data	PROTO ((void));
! extern void allocate_reg_life_data	PROTO ((void));
  extern void recompute_reg_usage		PROTO ((rtx, int));
  #ifdef BUFSIZ
  extern void dump_flow_info		PROTO ((FILE *));
Index: sibcall.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/sibcall.c,v
retrieving revision 1.10
diff -c -p -d -r1.10 sibcall.c
*** sibcall.c	1999/03/17 04:25:28	1.10
--- sibcall.c	1999/03/31 20:28:34
*************** optimize_sibling_and_tail_recursive_call
*** 339,345 ****
  
    /* We need cfg information to determine which blocks are succeeded
       only by the epilogue.  */
!   find_basic_blocks (insns, max_reg_num (), 0);
  
    /* If there are no basic blocks, then there is nothing to do.  */
    if (n_basic_blocks == 0)
--- 339,345 ----
  
    /* We need cfg information to determine which blocks are succeeded
       only by the epilogue.  */
!   find_basic_blocks (insns, max_reg_num (), 0, 1);
  
    /* If there are no basic blocks, then there is nothing to do.  */
    if (n_basic_blocks == 0)
Index: stupid.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/stupid.c,v
retrieving revision 1.36
diff -c -p -d -r1.36 stupid.c
*** stupid.c	1999/01/15 07:57:58	1.36
--- stupid.c	1999/03/31 20:28:34
*************** stupid_life_analysis (f, nregs, file)
*** 253,259 ****
    /* Allocate and zero out many data structures
       that will record the data from lifetime analysis.  */
  
!   allocate_for_life_analysis ();
  
    for (i = 0; i < max_regno; i++)
      REG_N_DEATHS (i) = 1;
--- 253,260 ----
    /* Allocate and zero out many data structures
       that will record the data from lifetime analysis.  */
  
!   allocate_reg_life_data ();
!   allocate_bb_life_data ();
  
    for (i = 0; i < max_regno; i++)
      REG_N_DEATHS (i) = 1;
Index: toplev.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/toplev.c,v
retrieving revision 1.352
diff -c -p -d -r1.352 toplev.c
*** toplev.c	1999/03/12 16:50:52	1.352
--- toplev.c	1999/03/31 20:28:35
*************** rest_of_compilation (decl)
*** 4070,4076 ****
        TIMEVAR
  	(flow_time,
  	 {
! 	   find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
  	   life_analysis (insns, max_reg_num (), rtl_dump_file);
  	 });
  
--- 4070,4076 ----
        TIMEVAR
  	(flow_time,
  	 {
! 	   find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1);
  	   life_analysis (insns, max_reg_num (), rtl_dump_file);
  	 });
  
*************** rest_of_compilation (decl)
*** 4268,4274 ****
        TIMEVAR
  	(flow2_time,
  	 {
! 	   find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
  	   life_analysis (insns, max_reg_num (), rtl_dump_file);
  	 });
      }
--- 4268,4274 ----
        TIMEVAR
  	(flow2_time,
  	 {
! 	   find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1);
  	   life_analysis (insns, max_reg_num (), rtl_dump_file);
  	 });
      }
*************** main (argc, argv)
*** 4917,4924 ****
  
  	 If/when we add LRS support to our dwarf2 code we can enable LRS
  	 optimizations for more targets.  */
!       /* ??? Temporary.  Live range splitting is broken with new flow code. */
!       /* flag_live_range = (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG); */
        /* END CYGNUS LOCAL */
        /* CYGNUS LOCAL peephole2 */
        flag_peephole2 = 1;
--- 4917,4923 ----
  
  	 If/when we add LRS support to our dwarf2 code we can enable LRS
  	 optimizations for more targets.  */
!       flag_live_range = 1 || (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG);
        /* END CYGNUS LOCAL */
        /* CYGNUS LOCAL peephole2 */
        flag_peephole2 = 1;


More information about the Gcc-patches mailing list