This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch to block removal optimization


We were crashing left and right on the g++ testsuite with -g -O2,
because we were faced with orphaned local classes; the same problem
occurred with nested functions in C.  This patch fixes things so that:

1) We don't consider a local class from a deleted block to be an orphan.
2) We set NOTE_BLOCK before referring to it.
3) We don't try to remove blocks in final if we've done insn
   scheduling, since that moves block notes around arbitrarily;
   otherwise, we end up throwing away information for code that wasn't
   deleted at all.  Perhaps we should fix the scheduler so that block 
   notes are preserved better...

2000-03-03  Jason Merrill  <jason@casey.cygnus.com>

	* toplev.c (rest_of_compilation): find_loop_tree_blocks before
	remove_unnecessary_notes.
	(debug_ignore_block): New fn.
	* toplev.h: Declare it.
	* emit-rtl.c (remove_unncessary_notes): Call it.
	* dwarf2out.c (dwarf2out_ignore_block): New fn.
	* dwarf2out.h: Declare it.
	* final.c (final_start_function): Don't call remove_unnecessary_notes
	if we did insn scheduling.

Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/dwarf2out.c,v
retrieving revision 1.155
diff -c -p -r1.155 dwarf2out.c
*** dwarf2out.c	2000/02/29 23:33:48	1.155
--- dwarf2out.c	2000/03/03 23:55:50
*************** dwarf2out_end_block (blocknum)
*** 9592,9597 ****
--- 9576,9608 ----
  {
    function_section (current_function_decl);
    ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum);
+ }
+ 
+ /* We've decided not to emit any debugging information for BLOCK; make
+    sure that we don't end up with orphans as a result.  */
+ 
+ void
+ dwarf2out_ignore_block (block)
+      tree block;
+ {
+   tree decl;
+   for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl))
+     {
+       dw_die_ref die;
+ 
+       if (TREE_CODE (decl) == FUNCTION_DECL)
+ 	die = lookup_decl_die (decl);
+       else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl))
+ 	die = lookup_type_die (TREE_TYPE (decl));
+       else
+ 	die = NULL;
+ 
+       /* Just give them a dummy value for parent so dwarf2out_finish
+ 	 doesn't blow up; we would use add_child_die if we really
+ 	 wanted to add them to comp_unit_die's children.  */
+       if (die && die->die_parent == 0)
+ 	die->die_parent = comp_unit_die;
+     }
  }
  
  /* Output a marker (i.e. a label) at a point in the assembly code which
Index: dwarf2out.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/dwarf2out.h,v
retrieving revision 1.6
diff -c -p -r1.6 dwarf2out.h
*** dwarf2out.h	2000/02/06 03:40:45	1.6
--- dwarf2out.h	2000/03/03 23:55:50
*************** dwarf2out.h	P
*** 29,34 ****
--- 29,35 ----
  
  extern void dwarf2out_begin_block	PARAMS ((unsigned));
  extern void dwarf2out_end_block		PARAMS ((unsigned));
+ extern void dwarf2out_ignore_block	PARAMS ((tree));
  extern void dwarf2out_label		PARAMS ((rtx));			
  extern void dwarf2out_decl		PARAMS ((tree));	
  extern void dwarf2out_line		PARAMS ((const char *, unsigned));
Index: emit-rtl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/emit-rtl.c,v
retrieving revision 1.111
diff -c -p -r1.111 emit-rtl.c
*** emit-rtl.c	2000/02/28 09:51:40	1.111
--- emit-rtl.c	2000/03/03 23:55:58
*************** remove_unncessary_notes ()
*** 2710,2715 ****
--- 2710,2717 ----
  		     nesting structure.  */
  		  if (NOTE_BLOCK (prev) != NOTE_BLOCK (insn))
  		    abort ();
+ 
+ 		  debug_ignore_block (NOTE_BLOCK (insn));
  		  
  		  remove_insn (prev);
  		  remove_insn (insn);
Index: final.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/final.c,v
retrieving revision 1.114
diff -c -p -r1.114 final.c
*** final.c	2000/02/29 23:33:48	1.114
--- final.c	2000/03/03 23:56:00
*************** final_start_function (first, file, optim
*** 1644,1650 ****
    if (write_symbols)
      {
        number_blocks (current_function_decl);
!       remove_unncessary_notes ();
        /* We never actually put out begin/end notes for the top-level
  	 block in the function.  But, conceptually, that block is
  	 always needed.  */
--- 1644,1653 ----
    if (write_symbols)
      {
        number_blocks (current_function_decl);
!       /* Scheduling packs block notes together at the top of a basic block,
! 	 so we can't learn anything from them.  */
!       if (! flag_schedule_insns && ! flag_schedule_insns_after_reload)
! 	remove_unncessary_notes ();
        /* We never actually put out begin/end notes for the top-level
  	 block in the function.  But, conceptually, that block is
  	 always needed.  */
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/toplev.c,v
retrieving revision 1.297
diff -c -p -r1.297 toplev.c
*** toplev.c	2000/02/29 23:33:48	1.297
--- toplev.c	2000/03/03 23:56:10
*************** rest_of_compilation (decl)
*** 2845,2858 ****
       have been run to re-initialize it.  */
    cse_not_expected = ! optimize;
  
!   /* First, remove any notes we don't need.  That will make iterating
       over the instruction sequence faster, and allow the garbage
       collector to reclaim the memory used by the notes.  */
    remove_unncessary_notes ();
  
-   /* We need to make sure that NOTE_BLOCK is set correctly
-      for each NOTE_INSN_BLOCK_BEG/NOTE_INSN_BLOCK_END note.  */
-   find_loop_tree_blocks ();
    /* In function-at-a-time mode, we do not attempt to keep the BLOCK
       tree in sensible shape.  So, we just recalculate it here.  */
    if (cfun->x_whole_function_mode_p)
--- 2845,2859 ----
       have been run to re-initialize it.  */
    cse_not_expected = ! optimize;
  
!   /* First, make sure that NOTE_BLOCK is set correctly for each
!      NOTE_INSN_BLOCK_BEG/NOTE_INSN_BLOCK_END note.  */
!   find_loop_tree_blocks ();
! 
!   /* Then remove any notes we don't need.  That will make iterating
       over the instruction sequence faster, and allow the garbage
       collector to reclaim the memory used by the notes.  */
    remove_unncessary_notes ();
  
    /* In function-at-a-time mode, we do not attempt to keep the BLOCK
       tree in sensible shape.  So, we just recalculate it here.  */
    if (cfun->x_whole_function_mode_p)
*************** debug_undef (lineno, buffer)
*** 5159,5162 ****
--- 5158,5175 ----
        && write_symbols == DWARF2_DEBUG)
      dwarf2out_undef (lineno, buffer);
  #endif /* DWARF2_DEBUGGING_INFO */
+ }
+ 
+ /* Tell the debugging backend that we've decided not to emit any
+    debugging information for BLOCK, so it can clean up after any local
+    classes or nested functions.  */
+ 
+ void
+ debug_ignore_block (block)
+      tree block;
+ {
+ #ifdef DWARF2_DEBUGGING_INFO
+   if (write_symbols == DWARF2_DEBUG)
+     dwarf2out_ignore_block (block);
+ #endif
  }
Index: toplev.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/toplev.h,v
retrieving revision 1.33
diff -c -p -r1.33 toplev.h
*** toplev.h	2000/02/06 03:40:46	1.33
--- toplev.h	2000/03/03 23:56:10
*************** toplev.h	PARA
*** 35,40 ****
--- 35,41 ----
  extern void debug_end_source_file	PARAMS ((unsigned));
  extern void debug_define		PARAMS ((unsigned, char *));
  extern void debug_undef			PARAMS ((unsigned, char *));
+ extern void debug_ignore_block		PARAMS ((union tree_node *));
  extern void fatal			PARAMS ((const char *, ...))
    ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
  extern void fatal_io_error		PARAMS ((const char *))

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]