PATCH to insert BLOCKs without calls back to front-ends

Mark Mitchell markATcodesourcery.com
Fri Sep 17 15:22:00 GMT 1999


This change allows front-ends that do function-at-a-time processing to
be unconcerned with the insertion of new BLOCKs during inlining.
Instead, that happens automatically in the back-end.  Note that this
change should not in any way affect front-ends that do not do
function-at-a-time processing; everything will continue to work as
usual.

FYI, function-at-a-time processing in the C++ front-end is now working
(make check and bootstrap succeed, at least) and will be going in the
near future.  This is the last of the language-independent changes
required; all other changes will be in the C++ front-end itself.

Fri Sep 17 15:19:01 1999  Mark Mitchell  <mark@codesourcery.com>

	* functiion.h (struct function): Add x_whole_function_mode_p.
	(retrofit_block): Declare.
	* function.c (retrofit_block): New function.
	(identify_blocks): Add assertions.  Allow an incomplete set of
	block notes if we're still generating code for the function.
	* integrate.c: Include loop.h.
	(expand_inline_function): Call find_loop_tree_blocks to map block
	notes to blocks when in whole-function mode.  Use retrofit_block
	to insert new BLOCKs for the inlined function, rather than
	insert_block.
	* stmt.c (expand_fixup): Likewise.  Don't use pushlevel/polevel.
	* Makefile.in (integrate.o): Depend on loop.h.

Index: gcc/function.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/function.h,v
retrieving revision 1.32
diff -c -p -r1.32 function.h
*** function.h	1999/09/16 01:12:24	1.32
--- function.h	1999/09/17 18:24:08
*************** struct function
*** 293,298 ****
--- 293,304 ----
    /* Number of function calls seen so far in current function.  */
    int x_function_call_count;
  
+   /* Nonzero if this function is being processed in function-at-a-time
+      mode.  In other words, if all tree structure for this function,
+      including the BLOCK tree is created, before RTL generation
+      commences.  */
+   int x_whole_function_mode_p;
+ 
    /* List (chain of TREE_LIST) of LABEL_DECLs for all nonlocal labels
       (labels to which there can be nonlocal gotos from nested functions)
       in this function.  */
*************** extern struct function *outer_function_c
*** 521,526 ****
--- 527,534 ----
     Also store in each NOTE for the beginning or end of a block
     the index of that block in the vector.  */
  extern void identify_blocks PROTO((tree, rtx));
+ /* Insert a new BLOCK at an appropriate place in the block tree.  */
+ extern void retrofit_block PROTO((tree, rtx));
  
  /* Return size needed for stack frame based on slots so far allocated.
     This size counts from zero.  It is not rounded to STACK_BOUNDARY;
Index: gcc/Makefile.in
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/Makefile.in,v
retrieving revision 1.305
diff -c -p -r1.305 Makefile.in
*** Makefile.in	1999/09/15 03:42:23	1.305
--- Makefile.in	1999/09/17 18:23:55
*************** emit-rtl.o : emit-rtl.c $(CONFIG_H) syst
*** 1519,1525 ****
  real.o : real.c $(CONFIG_H) system.h $(TREE_H) toplev.h
  integrate.o : integrate.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
     integrate.h insn-flags.h insn-config.h $(EXPR_H) real.h $(REGS_H) \
!    intl.h function.h output.h $(RECOG_H) except.h toplev.h
  jump.o : jump.c $(CONFIG_H) system.h $(RTL_H) flags.h hard-reg-set.h $(REGS_H) \
     insn-config.h insn-flags.h $(RECOG_H) $(EXPR_H) real.h except.h function.h \
     toplev.h insn-attr.h
--- 1519,1525 ----
  real.o : real.c $(CONFIG_H) system.h $(TREE_H) toplev.h
  integrate.o : integrate.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
     integrate.h insn-flags.h insn-config.h $(EXPR_H) real.h $(REGS_H) \
!    intl.h function.h output.h $(RECOG_H) except.h toplev.h loop.h
  jump.o : jump.c $(CONFIG_H) system.h $(RTL_H) flags.h hard-reg-set.h $(REGS_H) \
     insn-config.h insn-flags.h $(RECOG_H) $(EXPR_H) real.h except.h function.h \
     toplev.h insn-attr.h
Index: gcc/function.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/function.c,v
retrieving revision 1.116
diff -c -p -r1.116 function.c
*** function.c	1999/09/16 04:39:51	1.116
--- function.c	1999/09/17 18:24:08
*************** round_trampoline_addr (tramp)
*** 5381,5386 ****
--- 5381,5429 ----
    return tramp;
  }
  
+ /* Insert the BLOCK in the block-tree before LAST_INSN.  */
+ 
+ void
+ retrofit_block (block, last_insn)
+      tree block;
+      rtx last_insn;
+ {
+   rtx insn;
+ 
+   /* Now insert the new BLOCK at the right place in the block trees
+      for the function which called the inline function.  We just look
+      backwards for a NOTE_INSN_BLOCK_{BEG,END}.  If we find the
+      beginning of a block, then this new block becomes the first
+      subblock of that block.  If we find the end of a block, then this
+      new block follows that block in the list of blocks.  */
+   for (insn = last_insn; insn; insn = PREV_INSN (insn))
+     if (GET_CODE (insn) == NOTE
+ 	&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
+ 	    || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END))
+       break;
+   if (!insn || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
+     {
+       tree superblock;
+ 
+       if (insn)
+ 	superblock = NOTE_BLOCK (insn);
+       else
+ 	superblock = DECL_INITIAL (current_function_decl);
+ 
+       BLOCK_SUPERCONTEXT (block) = superblock;
+       BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (superblock);
+       BLOCK_SUBBLOCKS (superblock) = block;
+     }
+   else
+     {
+       tree prevblock = NOTE_BLOCK (insn);
+ 
+       BLOCK_SUPERCONTEXT (block) = BLOCK_SUPERCONTEXT (prevblock);
+       BLOCK_CHAIN (block) = BLOCK_CHAIN (prevblock);
+       BLOCK_CHAIN (prevblock) = block;
+     }
+ }
+ 
  /* The functions identify_blocks and reorder_blocks provide a way to
     reorder the tree of BLOCK nodes, for optimizers that reshuffle or
     duplicate portions of the RTL code.  Call identify_blocks before
*************** identify_blocks (block, insns)
*** 5423,5437 ****
  	  {
  	    tree b;
  
  	    b = block_vector[current_block_number++];
  	    NOTE_BLOCK (insn) = b;
  	    block_stack[depth++] = b;
  	  }
- 	if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
- 	  NOTE_BLOCK (insn) = block_stack[--depth];
        }
  
!   if (n_blocks != current_block_number)
      abort ();
  
    free (block_vector);
--- 5466,5495 ----
  	  {
  	    tree b;
  
+ 	      /* If there are more block notes than BLOCKs, something
+ 		 is badly wrong.  */
+ 	    if (current_block_number == n_blocks)
+ 	      abort ();
+ 
  	    b = block_vector[current_block_number++];
  	    NOTE_BLOCK (insn) = b;
  	    block_stack[depth++] = b;
+ 	  }
+ 	else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
+ 	  {
+ 	    if (depth == 0)
+ 	      /* There are more NOTE_INSN_BLOCK_ENDs that
+ 		 NOTE_INSN_BLOCK_BEGs.  Something is badly wrong.  */
+ 	      abort ();
+ 
+ 	    NOTE_BLOCK (insn) = block_stack[--depth];
  	  }
        }
  
!   /* In whole-function mode, we might not have seen the whole function
!      yet, so we might not use up all the blocks.  */
!   if (n_blocks != current_block_number 
!       && !current_function->x_whole_function_mode_p)
      abort ();
  
    free (block_vector);
Index: gcc/integrate.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/integrate.c,v
retrieving revision 1.67
diff -c -p -r1.67 integrate.c
*** integrate.c	1999/09/16 04:39:52	1.67
--- integrate.c	1999/09/17 18:24:10
*************** Boston, MA 02111-1307, USA.  */
*** 38,43 ****
--- 38,44 ----
  #include "function.h"
  #include "toplev.h"
  #include "intl.h"
+ #include "loop.h"
  
  #include "obstack.h"
  #define	obstack_chunk_alloc	xmalloc
*************** static void set_decl_origin_self	PROTO((
*** 74,81 ****
  static void set_block_abstract_flags	PROTO((tree, int));
  static void process_reg_param		PROTO((struct inline_remap *, rtx,
  					       rtx));
- 
- 
  void set_decl_abstract_flags		PROTO((tree, int));
  static tree copy_and_set_decl_abstract_origin PROTO((tree));
  
--- 75,80 ----
*************** expand_inline_function (fndecl, parms, t
*** 742,747 ****
--- 741,751 ----
  	RTX_INTEGRATED_P (note) = 1;
      }
  
+   /* Figure out where the blocks are if we're going to have to insert
+      new BLOCKs into the existing block tree.  */
+   if (current_function->x_whole_function_mode_p)
+     find_loop_tree_blocks ();
+ 
    /* Process each argument.  For each, set up things so that the function's
       reference to the argument will refer to the argument being passed.
       We only replace REG with REG here.  Any simplifications are done
*************** expand_inline_function (fndecl, parms, t
*** 1279,1285 ****
    BLOCK_ABSTRACT_ORIGIN (block) = (DECL_ABSTRACT_ORIGIN (fndecl) == NULL
  				   ? fndecl : DECL_ABSTRACT_ORIGIN (fndecl));
    inline_function_decl = 0;
!   insert_block (block);
  
    /* End the scope containing the copied formal parameter variables
       and copied LABEL_DECLs.  We pass NULL_TREE for the variables list
--- 1283,1298 ----
    BLOCK_ABSTRACT_ORIGIN (block) = (DECL_ABSTRACT_ORIGIN (fndecl) == NULL
  				   ? fndecl : DECL_ABSTRACT_ORIGIN (fndecl));
    inline_function_decl = 0;
! 
!   if (current_function->x_whole_function_mode_p)
!     /* Insert the block into the already existing block-tree.  */
!     retrofit_block (block, map->insns_at_start);
!   else
!     /* In statement-at-a-time mode, we just tell the front-end to add
!        this block to the list of blocks at this binding level.  We
!        can't do it the way it's done for function-at-a-time mode the
!        superblocks have not been created yet.  */
!     insert_block (block);
  
    /* End the scope containing the copied formal parameter variables
       and copied LABEL_DECLs.  We pass NULL_TREE for the variables list
Index: gcc/stmt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/stmt.c,v
retrieving revision 1.91
diff -c -p -r1.91 stmt.c
*** stmt.c	1999/09/16 01:12:24	1.91
--- stmt.c	1999/09/17 18:24:21
*************** expand_fixup (tree_label, rtl_label, las
*** 1016,1028 ****
          register rtx original_before_jump
            = last_insn ? last_insn : get_last_insn ();
  	rtx start;
  
          start_sequence ();
-         pushlevel (0);
          start = emit_note (NULL_PTR, NOTE_INSN_BLOCK_BEG);
  	fixup->before_jump = emit_note (NULL_PTR, NOTE_INSN_DELETED);
          last_block_end_note = emit_note (NULL_PTR, NOTE_INSN_BLOCK_END);
!         fixup->context = poplevel (1, 0, 0);  /* Create the BLOCK node now! */
          end_sequence ();
          emit_insns_after (start, original_before_jump);
        }
--- 1016,1039 ----
          register rtx original_before_jump
            = last_insn ? last_insn : get_last_insn ();
  	rtx start;
+ 	tree block;
  
+ 	block = make_node (BLOCK);
+ 	TREE_USED (block) = 1;
+ 
+ 	if (current_function->x_whole_function_mode_p)
+ 	  {
+ 	    find_loop_tree_blocks ();
+ 	    retrofit_block (block, original_before_jump);
+ 	  }
+ 	else
+ 	  insert_block (block);
+ 
          start_sequence ();
          start = emit_note (NULL_PTR, NOTE_INSN_BLOCK_BEG);
  	fixup->before_jump = emit_note (NULL_PTR, NOTE_INSN_DELETED);
          last_block_end_note = emit_note (NULL_PTR, NOTE_INSN_BLOCK_END);
!         fixup->context = block;
          end_sequence ();
          emit_insns_after (start, original_before_jump);
        }


More information about the Gcc-patches mailing list