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]
Other format: [Raw text]

[tree-profiling/tree-ssa?] CFG transparent RTL expansion


Hi,
this patch implements the CFG transparent RTL expansion.
It has been bootstrapped/regtested on i686/x86-64/ppc/ppc64 -linux
and it cause no regression except for breaking mudflap.  I guess I will need to
enable the expansion at -O0 too in order to avoid need to implement mudflap for
both ways of chaining instructions and will try to do so incrementally
now.

I measured no slowdown (but also no speedup) on compiling GCC components.  I
will install it to the tree-profilling patch, but I would also welcome a review
or if it was accepted for tree-ssa (after fixing the libmudflap problem of
course)

There are number of improvements from here:
 1) make it update profile correctly  (there is no code to insert REG_BR_PROB notes yet)
 2) use the CFG (there is loop header duplication/eh lowering/old unroller in a
    way but hope to have these resolved soon)
 3) kill line number notes (it needs to move coverage code to trees, I am not sure how
    feasible it is with TER)
 4) implement some basic optimizations during lowering so we don't produce too much
    of garbage (basic CSE can be done, we can also insert loads of constants into
    proper place in the CFG reducing memory usage and also it would help to
    obsolette GCSE/multiblock CSE pass)
 5) perhaps expanding directly out of SSA to save some effort
    (expanding SSA_NAME nodes can be done via precomputed table, copies
    representing PHI nodes can be inserted to the edges of new CFG)

I hope to get into some of the plans eventually.
The patch also appears to fix/mask the string-opt failure.

Honza

2004-02-19  Jan Hubicka  <jh@suse.cz>
	* Makefile.in (builtins.o): Include basic-blocks.h.
	(cfgexpand.o): New file.
	* builtins.c: Inlucde basic-blocks.h
	(entry_of_function): New static function.
	(expand_builtin_saveregs, expand_builtin_apply_args): Use it.
	* cfgexpand.c: New file.
	* tree-cfg.c (cleanup_control_flow): Make global.
	(delete_tree_annotations): Break out from...
	(delete_tree_cfg): ... this one.
	* tree-dump.c (dump_files): Add expanded.
	* tree-flow.h (delete_tree_cfg_annotations): Declare.
	(tree_expand_cfg, cleanup_control_flow): Declare.
	* tree-optimize.c (execute_del_cfg): Do not delete the basic block
	datastructure.
	(tree_rest_of_compilation): Use tree_expand_cfg if needed.
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.179.2.1
diff -c -3 -p -r1.903.2.179.2.1 Makefile.in
*** Makefile.in	16 Feb 2004 17:22:45 -0000	1.903.2.179.2.1
--- Makefile.in	20 Feb 2004 21:05:54 -0000
*************** OBJS-common = \
*** 891,897 ****
   targhooks.o timevar.o toplev.o tracer.o tree.o tree-dump.o unroll.o	   \
   varasm.o varray.o version.o vmsdbgout.o xcoffout.o alloc-pool.o	   \
   et-forest.o cfghooks.o bt-load.o pretty-print.o $(GGC) web.o              \
!  rtl-profile.o tree-profile.o
  
  OBJS-md = $(out_object_file)
  OBJS-archive = $(EXTRA_OBJS) $(host_hook_obj) hashtable.o tree-inline.o	   \
--- 891,897 ----
   targhooks.o timevar.o toplev.o tracer.o tree.o tree-dump.o unroll.o	   \
   varasm.o varray.o version.o vmsdbgout.o xcoffout.o alloc-pool.o	   \
   et-forest.o cfghooks.o bt-load.o pretty-print.o $(GGC) web.o              \
!  rtl-profile.o tree-profile.o cfgexpand.o
  
  OBJS-md = $(out_object_file)
  OBJS-archive = $(EXTRA_OBJS) $(host_hook_obj) hashtable.o tree-inline.o	   \
*************** dojump.o : dojump.c $(CONFIG_H) $(SYSTEM
*** 1724,1730 ****
  builtins.o : builtins.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H)\
     flags.h $(TARGET_H) function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) insn-config.h \
     $(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \
!    except.h $(TM_P_H) $(PREDICT_H) libfuncs.h real.h langhooks.h
  calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) flags.h \
     $(EXPR_H) $(OPTABS_H) langhooks.h $(TARGET_H) \
     libfuncs.h $(REGS_H) toplev.h output.h function.h $(TIMEVAR_H) $(TM_P_H) cgraph.h except.h
--- 1724,1730 ----
  builtins.o : builtins.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H)\
     flags.h $(TARGET_H) function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) insn-config.h \
     $(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \
!    except.h $(TM_P_H) $(PREDICT_H) libfuncs.h real.h langhooks.h basic-block.h
  calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) flags.h \
     $(EXPR_H) $(OPTABS_H) langhooks.h $(TARGET_H) \
     libfuncs.h $(REGS_H) toplev.h output.h function.h $(TIMEVAR_H) $(TM_P_H) cgraph.h except.h
*************** cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) co
*** 1860,1865 ****
--- 1860,1868 ----
     function.h except.h $(GGC_H) $(TM_P_H) alloc-pool.h $(TIMEVAR_H) 
  cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
     $(BASIC_BLOCK_H) cfglayout.h $(TREE_FLOW_H) $(TIMEVAR_H) toplev.h
+ cfgexpand.o : cfgexpand.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+    $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) function.h $(TIMEVAR_H) $(TM_H) coretypes.h \
+    $(TREE_DUMP_H) except.h langhooks.h cfgloop.h gt-tree-cfg.h tree-pass.h $(RTL_H)
  cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
     insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
     function.h except.h $(GGC_H) $(TM_P_H) insn-config.h $(EXPR_H)
Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.152.2.50.2.1
diff -c -3 -p -r1.152.2.50.2.1 builtins.c
*** builtins.c	16 Feb 2004 17:22:46 -0000	1.152.2.50.2.1
--- builtins.c	20 Feb 2004 21:05:55 -0000
*************** Software Foundation, 59 Temple Place - S
*** 44,49 ****
--- 44,50 ----
  #include "tm_p.h"
  #include "target.h"
  #include "langhooks.h"
+ #include "basic-block.h"
  
  #define CALLED_AS_BUILT_IN(NODE) \
     (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10))
*************** expand_builtin_apply_args_1 (void)
*** 1255,1260 ****
--- 1256,1268 ----
    return copy_addr_to_reg (XEXP (registers, 0));
  }
  
+ /* Return RTX to emit after when we want to emit code on the entry of function.  */
+ static rtx
+ entry_of_function (void)
+ {
+   return (n_basic_blocks ? BB_HEAD (ENTRY_BLOCK_PTR->next_bb) : get_insns ());
+ }
+ 
  /* __builtin_apply_args returns block of memory allocated on
     the stack into which is stored the arg pointer, structure
     value address, static chain, and all the registers that might
*************** expand_builtin_apply_args (void)
*** 1288,1294 ****
         chain current, so the code is placed at the start of the
         function.  */
      push_topmost_sequence ();
!     emit_insn_before (seq, NEXT_INSN (get_insns ()));
      pop_topmost_sequence ();
      return temp;
    }
--- 1296,1302 ----
         chain current, so the code is placed at the start of the
         function.  */
      push_topmost_sequence ();
!     emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
      pop_topmost_sequence ();
      return temp;
    }
*************** expand_builtin_saveregs (void)
*** 3910,3916 ****
       is inside a start_sequence, make the outer-level insn chain current, so
       the code is placed at the start of the function.  */
    push_topmost_sequence ();
!   emit_insn_after (seq, get_insns ());
    pop_topmost_sequence ();
  
    return val;
--- 3918,3924 ----
       is inside a start_sequence, make the outer-level insn chain current, so
       the code is placed at the start of the function.  */
    push_topmost_sequence ();
!   emit_insn_after (seq, entry_of_function ());
    pop_topmost_sequence ();
  
    return val;
Index: cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfg.c,v
retrieving revision 1.34.2.23.2.2
diff -c -3 -p -r1.34.2.23.2.2 cfg.c
*** cfg.c	20 Feb 2004 21:05:21 -0000	1.34.2.23.2.2
--- cfg.c	20 Feb 2004 21:05:55 -0000
*************** dump_flow_info (FILE *file)
*** 517,527 ****
        for (e = bb->succ; e; e = e->succ_next)
  	dump_edge_info (file, e, 1);
  
!       fprintf (file, "\nRegisters live at start:");
!       dump_regset (bb->global_live_at_start, file);
  
!       fprintf (file, "\nRegisters live at end:");
!       dump_regset (bb->global_live_at_end, file);
  
        putc ('\n', file);
  
--- 517,533 ----
        for (e = bb->succ; e; e = e->succ_next)
  	dump_edge_info (file, e, 1);
  
!       if (bb->global_live_at_start)
! 	{
! 	  fprintf (file, "\nRegisters live at start:");
! 	  dump_regset (bb->global_live_at_start, file);
! 	}
  
!       if (bb->global_live_at_end)
! 	{
! 	  fprintf (file, "\nRegisters live at end:");
! 	  dump_regset (bb->global_live_at_end, file);
! 	}
  
        putc ('\n', file);
  
Index: cfgexpand.c
===================================================================
RCS file: cfgexpand.c
diff -N cfgexpand.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- cfgexpand.c	20 Feb 2004 21:05:55 -0000
***************
*** 0 ****
--- 1,372 ----
+ /* A pass lowering trees to rtl.
+    Copyright (C) 2004 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+ 
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING.  If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.  */
+ 
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "tm.h"
+ #include "tree.h"
+ #include "rtl.h"
+ #include "tm_p.h"
+ #include "basic-block.h"
+ #include "function.h"
+ #include "expr.h"
+ #include "langhooks.h"
+ #include "tree-flow.h"
+ #include "timevar.h"
+ #include "tree-dump.h"
+ #include "tree-pass.h"
+ #include "except.h"
+ 
+ /* Expand basic block BB fron trees to RTL form.  */
+ static basic_block
+ expand_block (basic_block bb, FILE * dump_file)
+ {
+   block_stmt_iterator bsi = bsi_start (bb);
+   tree stmt = NULL;
+   rtx note;
+   edge e;
+ 
+   if (dump_file)
+     {
+       tree_register_cfg_hooks ();
+       dump_bb (bb, dump_file, 0);
+       rtl_register_cfg_hooks ();
+     }
+ 
+   if (!bsi_end_p (bsi))
+     stmt = bsi_stmt (bsi);
+   if (stmt && TREE_CODE (stmt) == LABEL_EXPR)
+     {
+       rtx last = get_last_insn ();
+ 
+       (*lang_hooks.rtl_expand.stmt) (stmt);
+ 
+       /* Java emits line number notes in the top of labels. 
+          ??? Make this to go once line number notes are obsoletted.  */
+       BB_HEAD (bb) = NEXT_INSN (last);
+       if (GET_CODE (BB_HEAD (bb)) == NOTE)
+ 	BB_HEAD (bb) = NEXT_INSN (BB_HEAD (bb));
+       bsi_next (&bsi);
+       note = emit_note_after (NOTE_INSN_BASIC_BLOCK, BB_HEAD (bb));
+     }
+   else
+     note = BB_HEAD (bb) = emit_note (NOTE_INSN_BASIC_BLOCK);
+   NOTE_BASIC_BLOCK (note) = bb;
+ 
+   /* This flag is never used by RTL backend.  */
+   for (e = bb->succ; e; e = e->succ_next)
+     {
+       e->flags &= ~EDGE_EXECUTABLE;
+ 
+       /* At the moment not all abnormal edges match RTL representation.
+          It is safe to remove them here as find_sub_basic_blocks will
+          rediscover.  In future we should get this fixed properly.  */
+       if (e->flags & EDGE_ABNORMAL)
+ 	remove_edge (e);
+     }
+ 
+   for (; !bsi_end_p (bsi); bsi_next (&bsi))
+     {
+       tree stmt = bsi_stmt (bsi);
+       rtx last = get_last_insn ();
+ 
+       if (!stmt)
+ 	continue;
+ 
+       (*lang_hooks.rtl_expand.stmt) (stmt);
+       switch (TREE_CODE (stmt))
+ 	{
+ 	case COND_EXPR:
+ 	  {
+ 	    edge true_edge;
+ 	    edge false_edge;
+ 	    tree pred = TREE_OPERAND (stmt, 0);
+ 	    tree then_exp = TREE_OPERAND (stmt, 1);
+ 	    tree else_exp = TREE_OPERAND (stmt, 2);
+ 	    rtx last;
+ 	    basic_block new_bb, dest;
+ 	    edge new_edge;
+ 
+ 	    /* One of the succestors can be fallthru.  */
+ 	    true_edge = bb->succ;
+ 	    false_edge = bb->succ->succ_next;
+ 	    if ((false_edge->flags & EDGE_TRUE_VALUE)
+ 		|| (true_edge->flags & EDGE_FALSE_VALUE))
+ 	      {
+ 	        false_edge = bb->succ;
+ 	        true_edge = bb->succ->succ_next;
+ 	      }
+ 	    if (!(false_edge->flags & EDGE_FALSE_VALUE)
+ 		&& (true_edge->flags & EDGE_TRUE_VALUE))
+ 	      abort ();
+ 
+ 	    true_edge->flags &= ~EDGE_TRUE_VALUE;
+ 	    false_edge->flags &= ~EDGE_FALSE_VALUE;
+ 
+ 	    /* We can either see pure conditional jump with one fallthru
+ 	       edge or two-way jump that needs to be decomposed into two
+ 	       basic blocks.  */
+ 	    if (TREE_CODE (then_exp) == GOTO_EXPR
+ 		&& TREE_CODE (else_exp) == NOP_EXPR)
+ 	      {
+ 		jumpif (pred, label_rtx (GOTO_DESTINATION (then_exp)));
+ 		break;
+ 	      }
+ 	    if (TREE_CODE (else_exp) == GOTO_EXPR
+ 		&& TREE_CODE (then_exp) == NOP_EXPR)
+ 	      {
+ 		jumpifnot (pred, label_rtx (GOTO_DESTINATION (else_exp)));
+ 		break;
+ 	      }
+ 	    if (TREE_CODE (then_exp) != GOTO_EXPR
+ 		|| TREE_CODE (else_exp) != GOTO_EXPR)
+ 	      abort ();
+ 	    jumpif (pred, label_rtx (GOTO_DESTINATION (then_exp)));
+ 	    last = get_last_insn ();
+ 	    expand_expr (else_exp, const0_rtx, VOIDmode, 0);
+ 
+ 	    BB_END (bb) = last;
+ 	    if (GET_CODE (BB_END (bb)) == BARRIER)
+ 	      BB_END (bb) = PREV_INSN (BB_END (bb));
+ 	    update_bb_for_insn (bb);
+ 
+ 	    new_bb = create_basic_block (NEXT_INSN (last), get_last_insn (), bb);
+ 	    dest = false_edge->dest;
+ 	    redirect_edge_succ (false_edge, new_bb);
+ 	    false_edge->flags |= EDGE_FALLTHRU;
+ 	    new_bb->count = false_edge->count;
+ 	    new_bb->frequency = EDGE_FREQUENCY (false_edge);
+ 	    new_edge = make_edge (new_bb, dest, 0);
+ 	    new_edge->probability = REG_BR_PROB_BASE;
+ 	    new_edge->count = new_bb->count;
+ 	    if (GET_CODE (BB_END (new_bb)) == BARRIER)
+ 	      BB_END (new_bb) = PREV_INSN (BB_END (new_bb));
+ 	    update_bb_for_insn (new_bb);
+ 
+ 	    if (dump_file)
+ 	      {
+ 		dump_bb (bb, dump_file, 0);
+ 		dump_bb (new_bb, dump_file, 0);
+ 	      }
+ 	    return new_bb;
+ 	  }
+ 	  /* Update after expansion of sibling call.  */
+ 	case CALL_EXPR:
+ 	case MODIFY_EXPR:
+ 	case RETURN_EXPR:
+ 	  for (last = NEXT_INSN (last); last; last = NEXT_INSN (last))
+ 	    {
+ 	      if (GET_CODE (last) == CALL_INSN && SIBLING_CALL_P (last))
+ 		{
+ 		  edge e;
+ 		  int probability = 0;
+ 		  gcov_type count = 0;
+ 
+ 		  do_pending_stack_adjust ();
+ 		  for (e = bb->succ; e; e = e->succ_next)
+ 		    if (!(e->flags & (EDGE_ABNORMAL | EDGE_EH)))
+ 		      {
+ 			count += e->count;
+ 			probability += e->probability;
+ 			remove_edge (e);
+ 		      }
+ 
+ 		  e = make_edge (bb, EXIT_BLOCK_PTR,
+ 				     EDGE_ABNORMAL | EDGE_SIBCALL);
+ 		  e->probability += probability;
+ 		  e->count += count;
+ 		  BB_END (bb) = last;
+ 
+ 		  last = NEXT_INSN (last);
+ 		  if (GET_CODE (last) != BARRIER)
+ 		    abort ();
+ 		  while (NEXT_INSN (last))
+ 		    delete_insn (NEXT_INSN (last));
+ 		  update_bb_for_insn (bb);
+ 		  if (dump_file)
+ 		    dump_bb (bb, dump_file, 0);
+ 		  return bb;
+ 		}
+ 	    }
+ 	  break;
+ 	default:
+ 	  break;
+ 	}
+     }
+   do_pending_stack_adjust ();
+   BB_END (bb) = get_last_insn ();
+   if (GET_CODE (BB_END (bb)) == BARRIER)
+     BB_END (bb) = PREV_INSN (BB_END (bb));
+ 
+   if (GET_CODE (BB_END (bb)) == JUMP_INSN
+       && (GET_CODE (PATTERN (BB_END (bb))) == ADDR_VEC
+ 	  || GET_CODE (PATTERN (BB_END (bb))) == ADDR_DIFF_VEC))
+     BB_END (bb) = PREV_INSN (PREV_INSN (BB_END (bb)));
+ 
+   if (dump_file)
+     dump_bb (bb, dump_file, 0);
+   update_bb_for_insn (bb);
+   return bb;
+ }
+ 
+ /* Create basic block for initialization code.  */
+ static basic_block
+ construct_init_block (void)
+ {
+   basic_block init_block, first_block;
+   edge e;
+   tree bind_expr = DECL_SAVED_TREE (current_function_decl);
+   tree block;
+ 
+   /* Expand start of outermost BIND_EXPR.  */
+   if (TREE_CODE (bind_expr) != BIND_EXPR)
+     abort ();
+   block = BIND_EXPR_BLOCK (bind_expr);
+   expand_start_bindings_and_block (0, block);
+ 
+   for (e = ENTRY_BLOCK_PTR->succ; e; e = e->succ_next)
+     if (e->dest == ENTRY_BLOCK_PTR->next_bb)
+       break;
+   init_block = create_basic_block (NEXT_INSN (get_insns ()), get_last_insn (), ENTRY_BLOCK_PTR);
+   if (e)
+     {
+       first_block = e->dest;
+       redirect_edge_succ (e, init_block);
+       make_edge (init_block, first_block, EDGE_FALLTHRU);
+     }
+   else
+     make_edge (init_block, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
+   update_bb_for_insn (init_block);
+ 
+   return init_block;
+ }
+ 
+ /* Create block containing landing pads and similar stuff.  */
+ static void
+ construct_exit_block (void)
+ {
+   rtx head = get_last_insn ();
+   rtx end;
+   basic_block exit_block;
+   tree bind_expr = DECL_SAVED_TREE (current_function_decl);
+   edge e, next;
+ 
+   /* We hard-wired immediate_size_expand to zero above.
+      expand_function_end will decrement this variable.  So, we set the
+      variable to one here, so that after the decrement it will remain
+      zero.  */
+   immediate_size_expand = 1;
+ 
+   /* Make sure the locus is set to the end of the function, so that 
+      epilogue line numbers and warnings are set properly.  */
+   if (cfun->function_end_locus.file)
+     input_location = cfun->function_end_locus;
+ 
+   /* The following insns belong to the top scope.  */
+   record_block_change (DECL_INITIAL (current_function_decl));
+ 
+   expand_end_bindings (BIND_EXPR_VARS (bind_expr), 1, 0);
+   
+   /* Allow language dialects to perform special processing.  */
+   (*lang_hooks.rtl_expand.end) ();
+ 
+   /* Generate rtl for function exit.  */
+   expand_function_end ();
+ 
+   end = get_last_insn ();
+   if (head == end)
+     return;
+   exit_block = create_basic_block (NEXT_INSN (head), end, EXIT_BLOCK_PTR->prev_bb);
+   for (e = EXIT_BLOCK_PTR->pred; e; e = next)
+     {
+       next = e->pred_next;
+       if (!(e->flags & EDGE_ABNORMAL))
+         redirect_edge_succ (e, exit_block);
+     }
+   make_edge (exit_block, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
+   update_bb_for_insn (exit_block);
+ }
+ 
+ /* Convert IL representation from a GIMPLE to RTL.
+    We do conversion per basic block basis and preserve GIMPLE CFG.  This
+    imply some magic as CFG is partly consisting of RTL and partly of GIMPLE
+    basic blocks, so be curefull to not manipulate CFG during the expansion.  */
+ void
+ tree_expand_cfg (void)
+ {
+   basic_block bb, init_block;
+   rtx insn;
+   sbitmap blocks;
+   int dump_flags;
+   FILE *dump_file = dump_begin (TDI_expand, &dump_flags);
+ 
+   /* Code updating conditional jumps rely that no conditionals will be
+      simplified into unconditional jumps.  This also serve as usefull sanity
+      checking.  */
+   cleanup_control_flow ();
+ 
+   /* Write the flowgraph to a dot file.  */
+   rtl_register_cfg_hooks ();
+ 
+   init_block = construct_init_block ();
+ 
+   FOR_BB_BETWEEN (bb, init_block->next_bb, EXIT_BLOCK_PTR, next_bb)
+     bb = expand_block (bb, dump_file);
+ 
+   construct_exit_block ();
+ 
+   /* Convert from NOTE_INSN_EH_REGION style notes, and do other
+      sorts of eh initialization.  Delay this until after the
+      initial rtl dump so that we can see the original nesting.  */
+   convert_from_eh_region_ranges ();
+ 
+   rebuild_jump_labels (get_insns ());
+   find_exception_handler_labels ();
+ 
+   blocks = sbitmap_alloc (last_basic_block);
+   sbitmap_ones (blocks);
+   find_many_sub_basic_blocks (blocks);
+   purge_all_dead_edges (0);
+   sbitmap_free (blocks);
+ 
+   if (dump_file)
+     {
+       fprintf (dump_file, "\n\n\nExpanded body:\n\n\n");
+       print_rtl_with_bb (dump_file, get_insns ());
+     }
+ #ifdef ENABLE_CHECKING
+   verify_flow_info();
+ #endif
+   cleanup_cfg (CLEANUP_PRE_LOOP);
+ #ifdef ENABLE_CHECKING
+   verify_flow_info();
+ #endif
+ 
+   free_basic_block_vars (0);
+   free_bb_for_insn ();
+ 
+   /* ??? Avoid confusion while rebuilding CFG.  */
+   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+     if (GET_CODE (insn) == NOTE
+ 	&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)
+       delete_insn (insn);
+ }
+ 
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.267.2.2
diff -c -3 -p -r1.1.4.267.2.2 tree-cfg.c
*** tree-cfg.c	20 Feb 2004 21:01:06 -0000	1.1.4.267.2.2
--- tree-cfg.c	20 Feb 2004 21:05:55 -0000
*************** static void bsi_commit_edge_inserts_1 (e
*** 110,116 ****
  static void tree_merge_blocks (basic_block, basic_block);
  static bool tree_can_merge_blocks_p (basic_block, basic_block);
  static void remove_bb (basic_block);
- static bool cleanup_control_flow (void);
  static bool cleanup_control_expr_graph (basic_block, block_stmt_iterator);
  static edge find_taken_edge_cond_expr (basic_block, tree);
  static edge find_taken_edge_switch_expr (basic_block, tree);
--- 110,115 ----
*************** tree_block_forwards_to (basic_block bb)
*** 1610,1616 ****
  
  /* Try to remove superfluous control structures.  */
  
! static bool
  cleanup_control_flow (void)
  {
    basic_block bb;
--- 1609,1615 ----
  
  /* Try to remove superfluous control structures.  */
  
! bool
  cleanup_control_flow (void)
  {
    basic_block bb;
*************** disband_implicit_edges (void)
*** 2351,2367 ****
    factored_computed_goto_label = NULL;
  }
  
! /* Remove all the blocks and edges that make up the flowgraph.  */
  
  void
! delete_tree_cfg (void)
  {
    if (n_basic_blocks > 0)
      free_blocks_annotations ();
  
    free_basic_block_vars (0);
    basic_block_info = NULL;
-   label_to_block_map = NULL;
  }
  
  /* Return the first statement in basic block BB, stripped of any NOP
--- 2350,2375 ----
    factored_computed_goto_label = NULL;
  }
  
! /* Remove block annotations and other datastructures.  */
  
  void
! delete_tree_cfg_annotations (void)
  {
    if (n_basic_blocks > 0)
      free_blocks_annotations ();
+   free_dominance_info (CDI_DOMINATORS);
+ 
+   label_to_block_map = NULL;
+ }
  
+ /* Remove all the blocks and edges that make up the flowgraph.  */
+ 
+ void
+ delete_tree_cfg (void)
+ {
+   delete_tree_cfg_annotations ();
    free_basic_block_vars (0);
    basic_block_info = NULL;
  }
  
  /* Return the first statement in basic block BB, stripped of any NOP
*************** tree_redirect_edge_and_branch_force (edg
*** 3610,3616 ****
  
    return NULL;
  }
- 
  /* Splits basic block BB after statement STMT (but at least after the
     labels).  If STMT is NULL, the BB is split just after the labels.  */
  
--- 3618,3623 ----
Index: tree-dump.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-dump.c,v
retrieving revision 1.6.2.63.2.1
diff -c -3 -p -r1.6.2.63.2.1 tree-dump.c
*** tree-dump.c	16 Feb 2004 17:23:05 -0000	1.6.2.63.2.1
--- tree-dump.c	20 Feb 2004 21:05:55 -0000
*************** static struct dump_file_info dump_files[
*** 652,657 ****
--- 652,658 ----
    {".generic", "tree-generic", 0, 0},
    {".nested", "tree-nested", 0, 0},
    {".inlined", "tree-inlined", 0, 0},
+   {".expanded", "tree-expanded", 0, 0},
    {".dot", "tree-dot", 0, 0},
    {".xml", "call-graph", 0, 0},
    {NULL, "tree-all", 0, 0},
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.187.2.1
diff -c -3 -p -r1.1.4.187.2.1 tree-flow.h
*** tree-flow.h	16 Feb 2004 17:23:05 -0000	1.1.4.187.2.1
--- tree-flow.h	20 Feb 2004 21:05:55 -0000
*************** extern void bsi_replace (const block_stm
*** 446,451 ****
--- 446,452 ----
  #define PENDING_STMT(e)	((e)->insns.t)
  
  extern void build_tree_cfg (tree *);
+ extern void delete_tree_cfg_annotations (void);
  extern void delete_tree_cfg (void);
  extern void disband_implicit_edges (void);
  extern bool stmt_ends_bb_p (tree);
*************** extern bool verify_stmt (tree);
*** 484,489 ****
--- 485,492 ----
  extern void verify_stmts (void);
  extern basic_block tree_duplicate_bb (basic_block, edge);
  extern void extract_true_false_edges_from_block (basic_block, edge *, edge *);
+ extern void tree_expand_cfg (void);
+ extern bool cleanup_control_flow (void);
  
  
  /* In tree-pretty-print.c.  */
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 1.1.4.122.2.1
diff -c -3 -p -r1.1.4.122.2.1 tree-optimize.c
*** tree-optimize.c	16 Feb 2004 17:23:06 -0000	1.1.4.122.2.1
--- tree-optimize.c	20 Feb 2004 21:05:55 -0000
*************** static struct tree_opt_pass pass_all_opt
*** 143,149 ****
  static void
  execute_del_cfg (void)
  {
-   basic_block bb;
    tree *chain;
  
    /* ??? This isn't the right place for this.  Worse, it got computed
--- 143,148 ----
*************** execute_del_cfg (void)
*** 160,172 ****
    /* Re-chain the statements from the blocks.  */
    chain = &DECL_SAVED_TREE (current_function_decl);
    *chain = alloc_stmt_list ();
-   FOR_EACH_BB (bb)
-     {
-       append_to_statement_list_force (bb->stmt_list, chain);
-     }
  
!   /* And get rid of the cfg.  */
!   delete_tree_cfg ();
  }
  
  static struct tree_opt_pass pass_del_cfg =
--- 159,167 ----
    /* Re-chain the statements from the blocks.  */
    chain = &DECL_SAVED_TREE (current_function_decl);
    *chain = alloc_stmt_list ();
  
!   /* And get rid of annotations we no longer need.  */
!   delete_tree_cfg_annotations ();
  }
  
  static struct tree_opt_pass pass_del_cfg =
*************** tree_rest_of_compilation (tree fndecl, b
*** 547,573 ****
      expand_main_function ();
  
    /* Generate the RTL for this function.  */
!   (*lang_hooks.rtl_expand.stmt) (DECL_SAVED_TREE (fndecl));
  
!   /* We hard-wired immediate_size_expand to zero above.
!      expand_function_end will decrement this variable.  So, we set the
!      variable to one here, so that after the decrement it will remain
!      zero.  */
!   immediate_size_expand = 1;
! 
!   /* Make sure the locus is set to the end of the function, so that 
!      epilogue line numbers and warnings are set properly.  */
!   if (cfun->function_end_locus.file)
!     input_location = cfun->function_end_locus;
! 
!   /* The following insns belong to the top scope.  */
!   record_block_change (DECL_INITIAL (current_function_decl));
!   
!   /* Allow language dialects to perform special processing.  */
!   (*lang_hooks.rtl_expand.end) ();
  
!   /* Generate rtl for function exit.  */
!   expand_function_end ();
  
    /* If this is a nested function, protect the local variables in the stack
       above us from being collected while we're compiling this function.  */
--- 542,573 ----
      expand_main_function ();
  
    /* Generate the RTL for this function.  */
!   if (n_basic_blocks > 0)
!     tree_expand_cfg ();
!   else
!     {
!       (*lang_hooks.rtl_expand.stmt) (DECL_SAVED_TREE (fndecl));
  
!       /* We hard-wired immediate_size_expand to zero above.
! 	 expand_function_end will decrement this variable.  So, we set the
! 	 variable to one here, so that after the decrement it will remain
! 	 zero.  */
!       immediate_size_expand = 1;
! 
!       /* Make sure the locus is set to the end of the function, so that 
! 	 epilogue line numbers and warnings are set properly.  */
!       if (cfun->function_end_locus.file)
! 	input_location = cfun->function_end_locus;
! 
!       /* The following insns belong to the top scope.  */
!       record_block_change (DECL_INITIAL (current_function_decl));
!       
!       /* Allow language dialects to perform special processing.  */
!       (*lang_hooks.rtl_expand.end) ();
  
!       /* Generate rtl for function exit.  */
!       expand_function_end ();
!     }
  
    /* If this is a nested function, protect the local variables in the stack
       above us from being collected while we're compiling this function.  */
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.342.2.169.2.1
diff -c -3 -p -r1.342.2.169.2.1 tree.h
*** tree.h	16 Feb 2004 17:23:06 -0000	1.342.2.169.2.1
--- tree.h	20 Feb 2004 21:05:56 -0000
*************** enum tree_dump_index
*** 3577,3582 ****
--- 3577,3583 ----
    TDI_nested,			/* dump each function after unnesting it */
    TDI_inlined,			/* dump each function after inlining
  				   within it.  */
+   TDI_expand,			/* dump RTL expansion of each function */
    TDI_dot,			/* create a dot graph file for each 
  				   function's flowgraph.  */
    TDI_xml,                      /* dump function call graph.   */


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