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]

[RFC] CFG based RTL expansion


Hi,
the attached patch implements RTL expnasion in CFG transparent way.
It bootstraps/passes testsuite, but still has some corner issues.
It gets CFG right enought to be able to do cfg_cleanup and
verify_flow_info on it before it is destroyed and usual
rest_of_compilation path is executed.

The patch depends on CFG being valid, otherwise verify_flow_info fails.
I added checks to verify_flow_info Zdenek already sent with his patch
that founds several bugs in current implementation.  I hope Zdenek's
patch to go in soon so this gets solved.

One anoying thing are the nested functions.  At the present they are
expanded/optimized in between tree_optimize_function and expand_body.
This has a problem that it overwrite CFG so it is already lost at
expansion time and it also is bad for other reasons.

In my patch I made them expanded afterwards that however has problem
with fact that nonlocal labels and needed trampolines are discovered
during expansion of nested function.  I do conservative job on
constructing these and I can do better by walking nested bodies first,
but perhaps we simply don't want this and would rather unnest nested
functions in foreseeable future?

Another problem is that current way of constructing abnormal edges for
computed jumps and non-local jumps does not match RTL, so I simply
remove them and let find_sub_basic_blocks re-discover them.

Similar case happens in tablejump production.  I think in this case we
should lower the current switch_exprs to jump trees/tablejumps before
RTL expansion, so I will work on this later.

I also originally planned to go directly into cfg_layout mode.  This
does not happen with current patch as it is way too dificult to fire up
all the datastructures used to mask away the line number notes and
similar garbage and we are not able to find_sub_basic_blocks on it.  So
I think I need to delay this part and kill some of this mess first.

The CFG is also not used right now.  I would like to do this
incrementally too.

FInally I had to kill remove_useless_stmts_and_vars as it kills the CFG.
Hope this is not a problem.

So does seem that current status (after sorting out the bugs we noticed
on the way and removing commented debug code) is applicable or what of
problems I should sort out first?

Honza

Index: cfgbuild.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgbuild.c,v
retrieving revision 1.25.2.11
diff -c -3 -p -r1.25.2.11 cfgbuild.c
*** cfgbuild.c	28 Sep 2003 06:06:07 -0000	1.25.2.11
--- cfgbuild.c	6 Nov 2003 14:45:42 -0000
*************** control_flow_insn_p (rtx insn)
*** 118,123 ****
--- 118,128 ----
  	      || can_throw_internal (insn));
  
      case INSN:
+       /* We represent EH manipulation via unspec followed by barrier.
+          Such instruction is control flow instruction even when there is
+          no other clue specifying it.  */
+       if (NEXT_INSN (insn) && GET_CODE (NEXT_INSN (insn)) == BARRIER)
+ 	return true;
        return (flag_non_call_exceptions && can_throw_internal (insn));
  
      case BARRIER:
Index: gimple-low.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gimple-low.c,v
retrieving revision 1.1.4.6
diff -c -3 -p -r1.1.4.6 gimple-low.c
*** gimple-low.c	5 Nov 2003 13:39:23 -0000	1.1.4.6
--- gimple-low.c	6 Nov 2003 14:45:43 -0000
*************** expand_used_vars (void)
*** 283,288 ****
--- 283,291 ----
      {
        var = TREE_VALUE (cell);
  
+       if (TREE_CODE (var) == FUNCTION_DECL)
+ 	continue;
+ 
        if (TREE_CODE (var) == VAR_DECL)
  	{
  	  struct var_ann_d *ann = var_ann (var);
*************** expand_used_vars (void)
*** 301,306 ****
--- 304,323 ----
  	}
  
        expand_var (var);
+     }
+ }
+ 
+ void
+ expand_nested_functions (void)
+ {
+   tree var, cell;
+ 
+   for (cell = cfun->unexpanded_var_list; cell; cell = TREE_CHAIN (cell))
+     {
+       var = TREE_VALUE (cell);
+ 
+       if (TREE_CODE (var) == FUNCTION_DECL)
+         expand_var (var);
      }
  
    cfun->unexpanded_var_list = NULL_TREE;
Index: stmt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stmt.c,v
retrieving revision 1.267.2.39
diff -c -3 -p -r1.267.2.39 stmt.c
*** stmt.c	31 Oct 2003 07:29:42 -0000	1.267.2.39
--- stmt.c	6 Nov 2003 14:45:44 -0000
*************** declare_nonlocal_label (tree label)
*** 590,595 ****
--- 590,597 ----
      }
    nonlocal_goto_handler_slots
      = gen_rtx_EXPR_LIST (VOIDmode, slot, nonlocal_goto_handler_slots);
+   /* ??? We should walk nested functions to figure out whehter it is needed.  */
+   cfun->has_nonlocal_label = 1;
  }
  
  /* Generate RTL code for a `goto' statement with target label LABEL.
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.194
diff -c -3 -p -r1.1.4.194 tree-cfg.c
*** tree-cfg.c	5 Nov 2003 16:28:06 -0000	1.1.4.194
--- tree-cfg.c	6 Nov 2003 14:45:44 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 42,47 ****
--- 42,48 ----
  #include "toplev.h"
  #include "except.h"
  #include "cfgloop.h"
+ #include "cgraph.h"
  
  /* This file contains functions for building the Control Flow Graph (CFG)
     for a function tree.  */
*************** stmt_ends_bb_p (tree t)
*** 2464,2469 ****
--- 2491,2525 ----
  	  || is_ctrl_altering_stmt (t));
  }
  
+ /* Callback function for walk_tree to clear DFA/SSA annotations from node
+    *TP.  */
+ 
+ static tree
+ remove_annotations_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
+ 		      void *data ATTRIBUTE_UNUSED)
+ {
+   tree t = *tp;
+   enum tree_code code = TREE_CODE (t);
+ 
+   t->common.ann = NULL;
+ 
+   /* If the node is not a container, then it has nothing interesting
+      underneath it.  */
+   if (code != LOOP_EXPR
+       && code != COND_EXPR
+       && code != CATCH_EXPR
+       && code != TRY_CATCH_EXPR
+       && code != TRY_FINALLY_EXPR
+       && code != SWITCH_EXPR
+       && code != BIND_EXPR
+       && code != COMPOUND_EXPR)
+     {
+       *walk_subtrees = 0;
+       return NULL_TREE;
+     }
+ 
+   return NULL_TREE;
+ }
  
  /* Remove all the blocks and edges that make up the flowgraph.  */
  
*************** delete_tree_cfg (void)
*** 2473,2479 ****
    if (n_basic_blocks > 0)
      free_blocks_annotations ();
  
!   free_basic_block_vars (0);
  }
  
  
--- 2529,2537 ----
    if (n_basic_blocks > 0)
      free_blocks_annotations ();
  
!   /* Remove annotations from every tree in the function.  */
!   walk_tree (&DECL_SAVED_TREE (current_function_decl), remove_annotations_r,
! 	     NULL, NULL);
  }
  
  
*************** tree_redirect_edge_and_branch_force (edg
*** 4001,4006 ****
--- 4249,4507 ----
    if (!e)
      abort ();
    return e->src == old ? NULL : old;
+ }
+ 
+ #include <rtl.h>
+ #include <cfglayout.h>
+ static basic_block
+ expand_block (basic_block bb)
+ {
+   block_stmt_iterator bsi = bsi = bsi_start (bb);
+   tree stmt = NULL;
+   rtx note;
+   edge e;
+ 
+ #if 0
+   tree_register_cfg_hooks ();
+   debug_bb (bb);
+   rtl_register_cfg_hooks ();
+ #endif
+ 
+   if (!bsi_end_p (bsi))
+     stmt = bsi_stmt (bsi);
+   if (stmt && TREE_CODE (stmt) == LABEL_EXPR)
+     {
+       (*lang_hooks.rtl_expand.stmt) (stmt);
+       bb->head = get_last_insn ();
+       bsi_next (&bsi);
+       note = emit_note (NOTE_INSN_BASIC_BLOCK);
+     }
+   else
+     note = bb->head = 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);
+       (*lang_hooks.rtl_expand.stmt) (stmt);
+       switch (TREE_CODE (stmt))
+ 	{
+ 	  /* Cond expr expands into conditional jump followed by unconditional
+ 	     jump.  While in theory find_sub_basic_block would be able to deal
+ 	     with this, we rather do this by hand to make maintaining of profile
+ 	     easier as well as to allow edges to be moved instead of
+ 	     purged & re-created.  */
+ 	  case COND_EXPR:
+ 	    {
+ 	      rtx condjump = get_last_insn ();
+ 	      edge true_edge;
+ 	      edge false_edge;
+ 
+ 	      if (bb->succ->flags & EDGE_TRUE_VALUE)
+ 		true_edge = bb->succ, false_edge = bb->succ->succ_next;
+ 	      else
+ 		false_edge = bb->succ, true_edge = bb->succ->succ_next;
+ 	      if (!true_edge || !false_edge
+ 		  || !(true_edge->flags & EDGE_TRUE_VALUE)
+ 		  || !(false_edge->flags & EDGE_FALSE_VALUE)
+ 		  || bb->succ->succ_next->succ_next)
+ 		abort ();
+ 
+ 	      /* Skip the unconditional jump.  */
+ 	      if (GET_CODE (condjump) != BARRIER)
+ 		abort ();
+ 	      bb->end = condjump = PREV_INSN (condjump);
+ 	      if (GET_CODE (condjump) != JUMP_INSN)
+ 		abort ();
+ 	      /* Look backward for the conditional jump.  */
+ 	      do {
+ 		condjump = PREV_INSN (condjump);
+ 	      } while (GET_CODE (condjump) != JUMP_INSN);
+ 	      update_bb_for_insn (bb);
+ 	      split_block (bb, condjump);
+ 	      redirect_edge_pred (true_edge, bb);
+ 	      true_edge->flags &= ~EDGE_TRUE_VALUE;
+ 	      false_edge->flags &= ~EDGE_FALSE_VALUE;
+ 	      return bb->next_bb;
+ 	    }
+ 	  break;
+ 	  default:
+ 	  break;
+ 	}
+     }
+   do_pending_stack_adjust ();
+   bb->end = get_last_insn ();
+   if (GET_CODE (bb->end) == BARRIER)
+     bb->end = PREV_INSN (bb->end);
+   if (GET_CODE (bb->end) == JUMP_INSN
+       && (GET_CODE (PATTERN (bb->end)) == ADDR_VEC
+           || GET_CODE (PATTERN (bb->end)) == ADDR_DIFF_VEC))
+     bb->end = PREV_INSN (PREV_INSN (bb->end));
+ #if 0
+   debug_bb (bb);
+   if (bb->succ)
+   fprintf(stderr, "hele: %d", bb->succ->flags);
+ #endif
+   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;
+   struct cgraph_node *node = cgraph_node (current_function_decl)->nested;
+ 
+   /* It is possible to take address of nested function in another nested
+      function.  In that case we need to initialize trampoline_address in the
+      outer function.  We simply initialize all needed nested functions
+      to avoid need of walking their bodies.  */
+   while (node)
+     {
+       if (node->needed)
+         trampoline_address (node->decl);
+       node = node->next_nested;
+     }
+ 
+   /* 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);
+ 
+   /* If VARS have not yet been expanded, expand them now.  */
+   /*expand_vars (BIND_EXPR_VARS (exp)); */
+ 
+   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);
+ 
+   /* 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);
+   while (EXIT_BLOCK_PTR->pred)
+     redirect_edge_succ (EXIT_BLOCK_PTR->pred, 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;
+ 
+   /* We get confused horribly by conditional jumps folding to constants.  */
+   cleanup_control_flow ();
+ #ifdef ENABLE_CHECKING
+   verify_flow_info();
+ #endif
+   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);
+ 
+   delete_tree_cfg ();
+ 
+   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);
+   /*print_rtl_with_bb (stderr, get_insns ());*/
+   find_many_sub_basic_blocks (blocks);
+   purge_all_dead_edges (0);
+   sbitmap_free (blocks);
+ 
+   /*dump_flow_info (rtl_dump_file);*/
+   /*print_rtl_with_bb (stderr, get_insns ());*/
+ #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);
  }
  
  /* FIXME These need to be filled in with appropriate pointers.  But this
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.141
diff -c -3 -p -r1.1.4.141 tree-flow.h
*** tree-flow.h	5 Nov 2003 13:39:23 -0000	1.1.4.141
--- tree-flow.h	6 Nov 2003 14:45:44 -0000
*************** extern bool cleanup_switch_expr_graph (b
*** 460,465 ****
--- 460,466 ----
  extern void tree_optimize_tail_calls (void);
  extern basic_block tree_block_forwards_to (basic_block bb);
  extern void dump_cfg_function_to_file (tree, FILE *, int);
+ extern void tree_expand_cfg (void);
  
  /* In tree-dfa.c  */
  void find_referenced_vars (tree);
*************** extern void mark_new_vars_to_rename (tre
*** 506,511 ****
--- 507,513 ----
  void lower_function_body (tree *);
  void expand_used_vars (void);
  void record_vars (tree);
+ void expand_nested_functions (void);
  
  /* In tree-ssa.c  */
  extern void init_tree_ssa (void);
Index: tree-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.h,v
retrieving revision 1.4.2.4
diff -c -3 -p -r1.4.2.4 tree-inline.h
*** tree-inline.h	25 Oct 2003 19:42:52 -0000	1.4.2.4
--- tree-inline.h	6 Nov 2003 14:45:44 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 26,33 ****
  
  void optimize_inline_calls (tree);
  bool tree_inlinable_function_p (tree);
- tree walk_tree (tree*, walk_tree_fn, void*, void*);
- tree walk_tree_without_duplicates (tree*, walk_tree_fn, void*);
  tree copy_tree_r (tree*, int*, void*);
  void clone_body (tree, tree, void*);
  void remap_save_expr (tree*, void*, tree, int*);
--- 26,31 ----
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 1.1.4.68
diff -c -3 -p -r1.1.4.68 tree-optimize.c
*** tree-optimize.c	5 Nov 2003 13:39:23 -0000	1.1.4.68
--- tree-optimize.c	6 Nov 2003 14:45:44 -0000
*************** optimize_function_tree (tree fndecl, tre
*** 80,89 ****
--- 80,95 ----
  
        /* Eliminate tail recursion calls.  */
        tree_optimize_tail_calls ();
+ #ifdef ENABLE_CHECKING
+       verify_flow_info ();
+ #endif
  
        /* Compute aliasing information for all the variables referenced in
  	 the function.  */
        compute_may_aliases (fndecl);
+ #ifdef ENABLE_CHECKING
+       verify_flow_info ();
+ #endif
  
        /*			BEGIN SSA PASSES
  
*************** optimize_function_tree (tree fndecl, tre
*** 96,105 ****
--- 102,117 ----
        /* Rewrite the function into SSA form.  Initially, request all
  	 variables to be renamed.  */
        rewrite_into_ssa (fndecl, NULL, TDI_ssa_1);
+ #ifdef ENABLE_CHECKING
+       verify_flow_info ();
+ #endif
  
        /* Set up VARS_TO_RENAME to allow passes to inform which variables
  	 need to be renamed.  */
        vars_to_rename = sbitmap_alloc (num_referenced_vars);
+ #ifdef ENABLE_CHECKING
+       verify_flow_info ();
+ #endif
  
        /* Perform dominator optimizations.  */
        if (flag_tree_dom)
*************** optimize_function_tree (tree fndecl, tre
*** 119,124 ****
--- 131,139 ----
  	 dead pointer assignments taking the address of local variables.  */
        if (flag_tree_dce)
  	tree_ssa_dce (fndecl, TDI_dce_1);
+ #ifdef ENABLE_CHECKING
+       verify_flow_info ();
+ #endif
  
        /* The must-alias pass removes the aliasing and addressability bits
  	 from variables that used to have their address taken.  */
*************** optimize_function_tree (tree fndecl, tre
*** 131,136 ****
--- 146,154 ----
  	  if (sbitmap_first_set_bit (vars_to_rename) >= 0)
  	    rewrite_into_ssa (fndecl, vars_to_rename, TDI_ssa_3);
  	}
+ #ifdef ENABLE_CHECKING
+       verify_flow_info ();
+ #endif
  
        /* Run SCCP (Sparse Conditional Constant Propagation).  */
        if (flag_tree_ccp)
*************** optimize_function_tree (tree fndecl, tre
*** 142,151 ****
  	  if (sbitmap_first_set_bit (vars_to_rename) >= 0)
  	    rewrite_into_ssa (fndecl, vars_to_rename, TDI_ssa_4);
  	}
  
        /* Run SSA-PRE (Partial Redundancy Elimination).  */
!       if (flag_tree_pre)
  	tree_perform_ssapre (fndecl, TDI_pre);
  
        /* Perform a second pass of dominator optimizations.  */
        if (flag_tree_dom)
--- 160,175 ----
  	  if (sbitmap_first_set_bit (vars_to_rename) >= 0)
  	    rewrite_into_ssa (fndecl, vars_to_rename, TDI_ssa_4);
  	}
+ #ifdef ENABLE_CHECKING
+       verify_flow_info ();
+ #endif
  
        /* Run SSA-PRE (Partial Redundancy Elimination).  */
!       if (flag_tree_pre && 0)
  	tree_perform_ssapre (fndecl, TDI_pre);
+ #ifdef ENABLE_CHECKING
+       verify_flow_info ();
+ #endif
  
        /* Perform a second pass of dominator optimizations.  */
        if (flag_tree_dom)
*************** optimize_function_tree (tree fndecl, tre
*** 157,178 ****
  	  if (sbitmap_first_set_bit (vars_to_rename) >= 0)
  	    rewrite_into_ssa (fndecl, vars_to_rename, TDI_ssa_5);
  	}
  
        /* Run copy propagation.  */
        if (flag_tree_copyprop)
  	tree_ssa_copyprop (fndecl, TDI_copyprop);
  
        /* Do a second DCE pass.  */
        if (flag_tree_dce)
  	tree_ssa_dce (fndecl, TDI_dce_2);
  
        /* Rewrite the function out of SSA form.  */
        rewrite_out_of_ssa (fndecl, TDI_optimized);
  
        sbitmap_free (vars_to_rename);
      }
- 
-   delete_tree_cfg ();
  }
  
  
--- 181,212 ----
  	  if (sbitmap_first_set_bit (vars_to_rename) >= 0)
  	    rewrite_into_ssa (fndecl, vars_to_rename, TDI_ssa_5);
  	}
+ #ifdef ENABLE_CHECKING
+       verify_flow_info ();
+ #endif
  
        /* Run copy propagation.  */
        if (flag_tree_copyprop)
  	tree_ssa_copyprop (fndecl, TDI_copyprop);
+ #ifdef ENABLE_CHECKING
+       verify_flow_info ();
+ #endif
  
        /* Do a second DCE pass.  */
        if (flag_tree_dce)
  	tree_ssa_dce (fndecl, TDI_dce_2);
+ #ifdef ENABLE_CHECKING
+       verify_flow_info ();
+ #endif
  
        /* Rewrite the function out of SSA form.  */
        rewrite_out_of_ssa (fndecl, TDI_optimized);
+ #ifdef ENABLE_CHECKING
+       verify_flow_info ();
+ #endif
  
        sbitmap_free (vars_to_rename);
      }
  }
  
  
*************** tree_rest_of_compilation (tree fndecl, b
*** 335,361 ****
      DECL_SAVED_TREE (fndecl) = mudflap_c_function (fndecl);
  
    /* 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.  */
--- 369,402 ----
      DECL_SAVED_TREE (fndecl) = mudflap_c_function (fndecl);
  
    /* Generate the RTL for this function.  */
!   if (optimize >= 1 && !flag_disable_tree_ssa && 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 ();
!     }
  
!   expand_nested_functions ();
  
    /* 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-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.145
diff -c -3 -p -r1.1.4.145 tree-ssa.c
*** tree-ssa.c	5 Nov 2003 13:39:24 -0000	1.1.4.145
--- tree-ssa.c	6 Nov 2003 14:45:44 -0000
*************** static void rewrite_stmt (block_stmt_ite
*** 190,196 ****
  static inline void rewrite_operand (tree *);
  static void register_new_def (tree, tree, varray_type *);
  static void insert_phi_nodes_for (tree, bitmap *);
- static tree remove_annotations_r (tree *, int *, void *);
  static tree get_reaching_def (tree);
  static tree get_value_for (tree, varray_type);
  static void set_value_for (tree, tree, varray_type);
--- 190,195 ----
*************** rewrite_out_of_ssa (tree fndecl, enum tr
*** 1879,1894 ****
      }
  
    delete_elim_graph (g);
  
    /* If any copies were inserted on edges, actually insert them now.  */
    bsi_commit_edge_inserts (0, NULL);
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
  
    /* Do some cleanups which reduce the amount of data the
       tree->rtl expanders deal with.  */
!   remove_useless_stmts_and_vars (&DECL_SAVED_TREE (fndecl), true);
  
    /* Flush out flow graph and SSA data.  */
    delete_tree_ssa (fndecl);
--- 1878,1899 ----
      }
  
    delete_elim_graph (g);
+ #ifdef ENABLE_CHECKING
+   verify_flow_info ();
+ #endif
  
    /* If any copies were inserted on edges, actually insert them now.  */
    bsi_commit_edge_inserts (0, NULL);
+ #ifdef ENABLE_CHECKING
+   verify_flow_info ();
+ #endif
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
  
    /* Do some cleanups which reduce the amount of data the
       tree->rtl expanders deal with.  */
!   /*remove_useless_stmts_and_vars (&DECL_SAVED_TREE (fndecl), true);*/
  
    /* Flush out flow graph and SSA data.  */
    delete_tree_ssa (fndecl);
*************** delete_tree_ssa (tree fndecl)
*** 2245,2253 ****
  {
    size_t i;
  
-   /* Remove annotations from every tree in the function.  */
-   walk_tree (&DECL_SAVED_TREE (fndecl), remove_annotations_r, NULL, NULL);
- 
    /* Remove annotations from every referenced variable.  */
    for (i = 0; i < num_referenced_vars; i++)
      referenced_var (i)->common.ann = NULL;
--- 2250,2255 ----
*************** delete_tree_ssa (tree fndecl)
*** 2257,2292 ****
    call_clobbered_vars = NULL;
  }
  
- 
- /* Callback function for walk_tree to clear DFA/SSA annotations from node
-    *TP.  */
- 
- static tree
- remove_annotations_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
- 		      void *data ATTRIBUTE_UNUSED)
- {
-   tree t = *tp;
-   enum tree_code code = TREE_CODE (t);
- 
-   t->common.ann = NULL;
- 
-   /* If the node is not a container, then it has nothing interesting
-      underneath it.  */
-   if (code != LOOP_EXPR
-       && code != COND_EXPR
-       && code != CATCH_EXPR
-       && code != TRY_CATCH_EXPR
-       && code != TRY_FINALLY_EXPR
-       && code != SWITCH_EXPR
-       && code != BIND_EXPR
-       && code != COMPOUND_EXPR)
-     {
-       *walk_subtrees = 0;
-       return NULL_TREE;
-     }
- 
-   return NULL_TREE;
- }
  
  /* Return the current definition for variable VAR.  If none is found,
     create a new SSA name to act as the zeroth definition for VAR.  If VAR
--- 2259,2264 ----


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