This is the mail archive of the gcc@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-ssa] Overlapping live range patch.


On Tue, 2003-06-03 at 17:36, Diego Novillo wrote:
> On Tue, 2003-06-03 at 17:26, Toon Moene wrote:
>                                              ^^^^
> > Ah, yes - that's because g95 is not yet part of the tree-ssa branch :-)
> > 
> It's part of my secret plan to detect when you guys finally include g95 
> :)
> 
> 
> > stage1/xgcc .... f95/array.c -o f95/array.o
> > ../../gcc/gcc/f95/array.c: In function `spec_size':
> > ../../gcc/gcc/f95/array.c:1565: internal compiler error: in assign_vars, 
> > at tree-ssa.c:1553
> > 
> Should be fixed by Andrew's overlapping LRs patch which should be ready
> anytime now.  It works on amd64 and ia64, but Andrew found a corner case
> on x86.  It should be ready RSN (says he who's not actually working on
> the fix).

RSN for sure. no, now. just about. now. no, not quite... Thats been my
last week or so :-)

So, It now bootstraps and appears to do everything fine, with one minor
exception. The stage 1 compiler miscompiles the fortran file f/intrin.c,
and this results in a bootstrapped fortran compiler which fails a lot of
the fortran tests. If you dont bootstrap, it works great :-|

The problem is that the into SSA pass is generating a structure copy
which has a VDEF as a real use. This is a no-no. The out of SSA pass
creates a new temporary which is undefined on entry since there is no
defintion present. This of course causes problem :-)

Diego is looking at is today.

I will not check this in until he has resolved that problem on the
outside chance something else comes up, but until then, here is the
patch which I intend to commit when everything is worked out.

Andrew


	* toplev.c (parse_options_and_default_flags): Turn tree_copyprop on by 
	default.
	* tree-cfg.c (linearize_control_structures, linearize_cond_expr,
	replace_stmt, merge_tree_blocks, remap_stmts): Fix PROTOS.
	(find_insert_location): Add additional basic block parameter. Handle
	switch stmts.
	(handle_switch_split): New. Split edges to switch labels.
	(bsi_commit_first_edge_insert): Add extra parameter to 
	find_insert_location call. Fix split block chaining in THEN & ELSE.
	* tree-ssa-live.c (calculate_live_on_entry): Process all PHI def's after
	all the arguments have been processed.
	* tree-ssa.c (struct ssa_stats_d, struct loops *loops, var_is_live,
	rewrite_into_ssa): Remove old UNSSA code.
	(rewrite_block): Remove stmt is rewrite_stmt returns 1.
	(assign_vars): Remove abort and enable overlapping live ranges.
	(replace_variable): New. Replace SSA name with the partition variable.
	(rewrite_out_of_ssa): Use replace_variable().
	(dump_tree_ssa_stats): Remove old UNSSA code.
	(rewrite_stmt): Return 1 if stmt should be deleted. Remove old UNSSA 
	code.

Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.654.2.53
diff -c -p -r1.654.2.53 toplev.c
*** toplev.c	3 Jun 2003 16:50:51 -0000	1.654.2.53
--- toplev.c	3 Jun 2003 23:10:53 -0000
*************** parse_options_and_default_flags (argc, a
*** 5107,5112 ****
--- 5107,5113 ----
        flag_if_conversion2 = 1;
        flag_tree_ccp = 1;
        flag_tree_dce = 1;
+       flag_tree_copyprop = 1;
      }
  
    if (optimize >= 2)
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.98
diff -c -p -r1.1.4.98 tree-cfg.c
*** tree-cfg.c	2 Jun 2003 18:49:53 -0000	1.1.4.98
--- tree-cfg.c	3 Jun 2003 23:10:55 -0000
*************** static void disconnect_unreachable_case_
*** 127,137 ****
  static edge find_taken_edge_cond_expr	PARAMS ((basic_block, tree));
  static edge find_taken_edge_switch_expr	PARAMS ((basic_block, tree));
  static bool value_matches_some_label	PARAMS ((edge, tree, edge *));
! static void linearize_control_structures (void);
! static bool linearize_cond_expr		(tree *, basic_block);
! static void replace_stmt		(tree *, tree *);
! static void merge_tree_blocks		(basic_block, basic_block);
! static bool remap_stmts			(basic_block, basic_block, tree *);
  
  /* Block iterator helpers.  */
  
--- 127,138 ----
  static edge find_taken_edge_cond_expr	PARAMS ((basic_block, tree));
  static edge find_taken_edge_switch_expr	PARAMS ((basic_block, tree));
  static bool value_matches_some_label	PARAMS ((edge, tree, edge *));
! static void linearize_control_structures	PARAMS ((void));
! static bool linearize_cond_expr		PARAMS ((tree *, basic_block));
! static void replace_stmt		PARAMS ((tree *, tree *));
! static void merge_tree_blocks		PARAMS ((basic_block, basic_block));
! static bool remap_stmts			PARAMS ((basic_block, basic_block, tree *));
! static tree *handle_switch_split	PARAMS ((basic_block, basic_block));
  
  /* Block iterator helpers.  */
  
*************** enum find_location_action { 
*** 149,155 ****
    EDGE_INSERT_LOCATION_ELSE,
    EDGE_INSERT_LOCATION_NEW_ELSE };
  
! static tree_stmt_iterator find_insert_location	PARAMS ((basic_block, basic_block, enum find_location_action *));
  
  /* Location to track pending stmt for edge insertion.  */
  #define PENDING_STMT(e)	((tree)(e->insns))
--- 150,156 ----
    EDGE_INSERT_LOCATION_ELSE,
    EDGE_INSERT_LOCATION_NEW_ELSE };
  
! static tree_stmt_iterator find_insert_location	PARAMS ((basic_block, basic_block, basic_block, enum find_location_action *));
  
  /* Location to track pending stmt for edge insertion.  */
  #define PENDING_STMT(e)	((tree)(e->insns))
*************** bsi_insert_before (curr_bsi, t, mode)
*** 3622,3636 ****
    return;
  }
  
  /* Given an edge between src and dest, return a TSI representing the location
     that any instructions on this edge should be inserted.  
     The location parameter returns a value indicating how this iterator is
     to be used.  */
  
  static tree_stmt_iterator
! find_insert_location (src, dest, location)
       basic_block src;
       basic_block dest;
       enum find_location_action *location;
  {
    block_stmt_iterator bsi;
--- 3623,3788 ----
    return;
  }
  
+ 
+ /* Arrange for a place to insert a stmt when we are splitting a block which is
+    targetting by a switch stmt.  Return the container which is used to build
+    a TSI where the edge stmt should be inserted after. 
+ 
+    Fallthrough code must be directed around the target label, and a target 
+    label must be inserted on the other side of the code we are inserting.  
+    ie:
+      case X:
+ 	// fallthrough 
+   BB_a
+      case Y:
+        code;
+    
+    will be turned into:
+ 
+      case X:
+   BB_b
+        goto newlab;
+   BB_c
+      case Y:
+        inserted_code;
+   BB_a
+      newlab:
+        code;
+   
+    This will cause the creation of 2 new basic blocks, and require some 
+    edges to be redirected.  
+ 
+    Note that upon entry to this function, src is *not* the switch stmt's block
+    any more. commit_one_edge_insertion() has already split the edge from
+    src->dest, so we have   original_src -> src -> dest. This new src block 
+    is currently empty. 
+    
+    This routine will create BB_b. BB_c will be the SRC block passed in.
+    BB_a will remain the DEST block.  */
+ 
+ static tree *
+ handle_switch_split (src, dest)
+      basic_block src;
+      basic_block dest;
+ {
+   block_stmt_iterator bsi, tmp;
+   tree_stmt_iterator tsi;
+   tree stmt, label, parent;
+   basic_block new_bb;
+   edge e;
+   bb_ann_t bb_ann;
+ 
+ 
+   /* 1.  Insert the goto immediately preceeding the labels that are targeted. 
+      This should place the goto in the correct location in the tree.  */
+ 
+   tsi = tsi_start (dest->head_tree_p);
+   parent = parent_stmt (tsi_stmt (tsi));
+ 
+   label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+   TREE_USED (label) = 1;
+   stmt = build1 (GOTO_EXPR, void_type_node, label);
+ 
+   tsi_link_before (&tsi, stmt, TSI_NEW_STMT);
+   modify_stmt (stmt);
+ 
+   /* 2.  Make a new basic block of which this stmt is the sole member.  */
+ 
+   new_bb = create_bb ();
+   alloc_aux_for_block (new_bb, sizeof (struct bb_ann_d));
+   bb_ann = (bb_ann_t) xmalloc (sizeof (struct bb_ann_d));
+   new_bb->aux = bb_ann;
+   bb_ann->phi_nodes = NULL_TREE;
+   bb_ann->ephi_nodes = NULL_TREE;
+   bb_ann->dom_children = (bitmap) NULL;
+   append_stmt_to_bb (tsi_container (tsi), new_bb, parent);
+ 
+   /* Reset the head of dest since the container might be different now.  */
+   tsi_next (&tsi);
+   dest->head_tree_p = tsi_container (tsi);
+ 
+   /* 3. Redirect all the edges except the one from src to point to this
+ 	block.  */
+     
+   for (e = dest->pred; e ; e = e->pred_next)
+     {
+       if (e->src == src)
+ 	continue;
+       redirect_edge_succ (e, new_bb);
+     }
+ 
+   /* 4. Now make dest the target of the new block.  */
+ 
+   make_edge (new_bb, dest, 0);
+ 
+   /* 5. Find the last case label.  That will be where the code seperation
+      between bb_c and bb_a will be formed.  Upon exit of the loop, bsi will
+      point to the first stmt in BB_a.  */
+ 
+   bsi = bsi_start (dest);
+   for (tmp = bsi; !bsi_end_p (bsi); bsi_next (&bsi))
+     {
+       stmt = bsi_stmt (bsi);
+       if (is_label_stmt (bsi_stmt (bsi)))
+ 	{
+ 	  /* FIXME.  This block may also be the target of a GOTO.  Hopefully 
+ 	     there are no case stmts after the label. ick.  */
+ 	  if (TREE_CODE (stmt) != CASE_LABEL_EXPR)
+ 	    break;
+ 	}
+       else
+         break;
+       tmp = bsi;
+     }
+ 
+   /* 6. Now the stmts delinieating the new block are known. Change the basic
+ 	block for those stmts. It cannot be done in the above loop, for 
+ 	changing the basic block of a stmt pointed to by an iterator will cause
+ 	the iterator to think its reached the end of a block. (It is now 
+ 	pointing to BB_c, the next stmt is in BB_a, so it terminates.  */
+ 
+   for (tsi = tsi_start (dest->head_tree_p); 
+        !tsi_end_p (tsi) && (tsi_container (tsi) != bsi_container (bsi));
+        tsi_next (&tsi))
+     append_stmt_to_bb (tsi_container (tsi), src, parent_stmt (tsi_stmt (tsi)));
+ 
+ 
+   /* 7. Issue the label at the beginning of DEST, and update DEST's head
+ 	and end pointers.  */
+ 
+   stmt = build1 (LABEL_EXPR, void_type_node, label);
+   if (bsi_end_p (bsi))
+     {
+       /* There are no stmts left, so we need to link an empty_stmt node
+ 	 after the last stmt in BB_c (which is pointed to by 'tmp'), and make 
+ 	 it the only element of BB_a.  */
+       tsi = tsi_from_bsi (tmp);
+       tsi_link_after (&tsi, stmt, TSI_NEW_STMT);
+       dest->head_tree_p = (tree *) NULL;
+       dest->end_tree_p = (tree *) NULL;
+       append_stmt_to_bb (tsi_container (tsi), 
+ 			 dest, 
+ 			 parent_stmt (bsi_stmt (tmp)));
+     }
+   else
+     {
+       dest->head_tree_p = bsi_container (bsi);
+       bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
+     }
+ 
+   return bsi_container (tmp);
+ }
+ 
  /* Given an edge between src and dest, return a TSI representing the location
     that any instructions on this edge should be inserted.  
     The location parameter returns a value indicating how this iterator is
     to be used.  */
  
  static tree_stmt_iterator
! find_insert_location (src, dest, new_block, location)
       basic_block src;
       basic_block dest;
+      basic_block new_block;
       enum find_location_action *location;
  {
    block_stmt_iterator bsi;
*************** find_insert_location (src, dest, locatio
*** 3676,3682 ****
  	    ret = src->end_tree_p;
  	    *location = EDGE_INSERT_LOCATION_AFTER;
  	    break;
! 	  
  	  default:
  	    ret = dest->head_tree_p;
  	    break;
--- 3828,3839 ----
  	    ret = src->end_tree_p;
  	    *location = EDGE_INSERT_LOCATION_AFTER;
  	    break;
! 
! 	  case SWITCH_EXPR:
! 	    ret = handle_switch_split (new_block, dest);
! 	    *location = EDGE_INSERT_LOCATION_AFTER;
! 	    break;
! 
  	  default:
  	    ret = dest->head_tree_p;
  	    break;
*************** bsi_commit_first_edge_insert (e, stmt)
*** 3797,3803 ****
    bb_ann->ephi_nodes = NULL_TREE;
    bb_ann->dom_children = (bitmap) NULL;
  
!   tsi = find_insert_location (src, dest, &location);
    parent = parent_stmt (tsi_stmt (tsi));
  
    switch (location)
--- 3954,3960 ----
    bb_ann->ephi_nodes = NULL_TREE;
    bb_ann->dom_children = (bitmap) NULL;
  
!   tsi = find_insert_location (src, dest, new_bb, &location);
    parent = parent_stmt (tsi_stmt (tsi));
  
    switch (location)
*************** bsi_commit_first_edge_insert (e, stmt)
*** 3824,3832 ****
        case EDGE_INSERT_LOCATION_ELSE:
  	stmt = last_stmt (src);
  	if (location == EDGE_INSERT_LOCATION_THEN)
! 	  COND_EXPR_THEN (stmt) = inserted_stmt;
  	else
! 	  COND_EXPR_ELSE (stmt) = inserted_stmt;
  	/* Fallthru.  */
  
        case EDGE_INSERT_LOCATION_BEFORE:
--- 3981,3989 ----
        case EDGE_INSERT_LOCATION_ELSE:
  	stmt = last_stmt (src);
  	if (location == EDGE_INSERT_LOCATION_THEN)
! 	  COND_EXPR_THEN (stmt) = *tsi_container (tsi);
  	else
! 	  COND_EXPR_ELSE (stmt) = *tsi_container (tsi);
  	/* Fallthru.  */
  
        case EDGE_INSERT_LOCATION_BEFORE:
Index: tree-ssa-live.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-live.c,v
retrieving revision 1.1.2.5
diff -c -p -r1.1.2.5 tree-ssa-live.c
*** tree-ssa-live.c	24 May 2003 13:08:51 -0000	1.1.2.5
--- tree-ssa-live.c	3 Jun 2003 23:10:56 -0000
*************** calculate_live_on_entry (map)
*** 490,496 ****
        for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
  	{
  	  var = PHI_RESULT (phi);
- 	  set_if_valid (map, saw_def, var);
  	  for (i = 0; i < PHI_NUM_ARGS (phi); i++)
  	    {
  	      var = PHI_ARG_DEF (phi, i);
--- 490,495 ----
*************** calculate_live_on_entry (map)
*** 503,508 ****
--- 502,520 ----
  		add_livein_if_notdef (live, saw_def, var, e->src);
  	    }
          }
+ 
+       /* Don't mark PHI results as defined until all the PHI nodes have
+ 	 been processed. If the PHI sequence is:
+ 	    a_3 = PHI <a_1, a_2>
+ 	    b_3 = PHI <b_1, a_3>
+ 	 The a_3 referred to in b_3's PHI node is the one incoming on the
+ 	 edge, *not* the PHI node just seen.  */
+ 
+       for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
+         {
+ 	  var = PHI_RESULT (phi);
+ 	  set_if_valid (map, saw_def, var);
+ 	}
  
        for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
          {
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.85
diff -c -p -r1.1.4.85 tree-ssa.c
*** tree-ssa.c	2 Jun 2003 18:49:54 -0000	1.1.4.85
--- tree-ssa.c	3 Jun 2003 23:10:57 -0000
*************** struct ssa_stats_d
*** 150,169 ****
    long num_const_prop;
    long num_copy_prop;
    long num_re;
-   /* FIXME.  [UNSSA] Not needed after SSA->normal pass is working.  */
- #if 1
-   long blocked_optimizations;
-   long blocked_by_life_crossing;
- #endif
  };
  
  static struct ssa_stats_d ssa_stats;
  
- #if 1
- /* FIXME: [UNSSA] Remove this once overlapping live ranges are allowed.  */
- static struct loops *loops = NULL;
- #endif
- 
  /* Local functions.  */
  static void init_tree_ssa		PARAMS ((void));
  static void delete_tree_ssa		PARAMS ((tree));
--- 150,159 ----
*************** static void set_livein_block		PARAMS ((t
*** 174,180 ****
  static void insert_phi_nodes		PARAMS ((bitmap *, sbitmap));
  static void insert_phis_for_deferred_variables PARAMS ((varray_type));
  static void rewrite_block		PARAMS ((basic_block, tree));
! static void rewrite_stmt		PARAMS ((block_stmt_iterator,
  						 varray_type *,
  						 varray_type *));
  static inline void rewrite_operand	PARAMS ((tree *));
--- 164,170 ----
  static void insert_phi_nodes		PARAMS ((bitmap *, sbitmap));
  static void insert_phis_for_deferred_variables PARAMS ((varray_type));
  static void rewrite_block		PARAMS ((basic_block, tree));
! static int rewrite_stmt			PARAMS ((block_stmt_iterator,
  						 varray_type *,
  						 varray_type *));
  static inline void rewrite_operand	PARAMS ((tree *));
*************** static void coalesce_ssa_name		PARAMS ((
*** 213,224 ****
  static void assign_vars			PARAMS ((var_map));
  static inline void set_if_valid		PARAMS ((var_map, sbitmap, tree));
  static inline void add_conflicts_if_valid	PARAMS ((root_var_p, conflict_graph, var_map, sbitmap, tree));
! 
! /* FIXME: [UNSSA] Remove once the real unSSA pass is implemented.  */
! #if 1
! static bool var_is_live			PARAMS ((tree, basic_block));
! #endif
! 
  
  /* Main entry point to the SSA builder.  FNDECL is the gimplified function
     to convert.
--- 203,209 ----
  static void assign_vars			PARAMS ((var_map));
  static inline void set_if_valid		PARAMS ((var_map, sbitmap, tree));
  static inline void add_conflicts_if_valid	PARAMS ((root_var_p, conflict_graph, var_map, sbitmap, tree));
! static void replace_variable		PARAMS ((var_map, tree *));
  
  /* Main entry point to the SSA builder.  FNDECL is the gimplified function
     to convert.
*************** rewrite_into_ssa (fndecl)
*** 312,323 ****
    
    timevar_push (TV_TREE_SSA_OTHER);
  
- #if 1
-   /* FIXME: [UNSSA] Remove once overlapping live ranges are allowed.  */
-   if (loops == NULL)
-     loops = loop_optimizer_init (NULL);
- #endif
- 
    /* Initialize common SSA structures.  */
    init_tree_ssa ();
  
--- 297,302 ----
*************** rewrite_into_ssa (fndecl)
*** 360,374 ****
    htab_delete (avail_exprs);
    htab_delete (const_and_copies);
  
- #if 1
-   /* FIXME: [UNSSA] Remove this once overlapping live ranges are allowed.  */
-   if (loops)
-     {
-       loop_optimizer_finalize (loops, NULL);
-       loops = NULL;
-     }
- #endif
- 
    /* Debugging dumps.  */
    if (tree_ssa_dump_file)
      {
--- 339,344 ----
*************** rewrite_block (bb, eq_expr_value)
*** 784,791 ****
    /* Step 2.  Rewrite every variable used in each statement the block with
       its immediate reaching definitions.  Update the current definition of
       a variable when a new real or virtual definition is found.  */
!   for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
!     rewrite_stmt (si, &block_defs, &block_avail_exprs);
  
    /* Step 3.  Visit all the successor blocks of BB looking for PHI nodes.
       For every PHI node found, add a new argument containing the current
--- 754,764 ----
    /* Step 2.  Rewrite every variable used in each statement the block with
       its immediate reaching definitions.  Update the current definition of
       a variable when a new real or virtual definition is found.  */
!   for (si = bsi_start (bb); !bsi_end_p (si); )
!     if (!rewrite_stmt (si, &block_defs, &block_avail_exprs))
!       bsi_next (&si);
!     else
!       bsi_remove (&si);
  
    /* Step 3.  Visit all the successor blocks of BB looking for PHI nodes.
       For every PHI node found, add a new argument containing the current
*************** assign_vars (map)
*** 1547,1557 ****
  	      print_generic_expr (tree_ssa_dump_file, var, TDF_SLIM);
  	    }
  
- 	  /* FIXME. Since we still don't have passes that create overlapping 
- 	  live ranges, the code above should've coalesced all the versions of
- 	  the variable together.  */
- 	  abort ();
- 
  	  var = create_temp (t);
  	  change_partition_var (map, var, i);
  	  ann = var_ann (var);
--- 1520,1525 ----
*************** assign_vars (map)
*** 1568,1583 ****
    delete_root_var (rv);
  }
  
  
! /* Take function FNDECL out of SSA form.
  
!    FIXME: Need to support overlapping live ranges for different versions of
! 	  the same variable.  At the moment, we will silently generate
! 	  wrong code if an optimizer pass moves code so that two versions
! 	  of the same variable have overlapping live ranges.
  
! 	  NOTE: Look for the string '[UNSSA]' to re-enable code that
! 	  depends on a properly working unSSA pass.  */
  
  void
  rewrite_out_of_ssa (fndecl)
--- 1536,1573 ----
    delete_root_var (rv);
  }
  
+ /* Replace *p with whatever variable it has been rewritten to.  */
  
! static void
! replace_variable (map, p)
!      var_map map;
!      tree *p;
! {
!   tree new_var;
!   tree var = *p;
!   tree copy;
  
!   new_var = var_to_partition_to_var (map, var);
!   if (new_var)
!     *p = new_var;
!   else
!     {
!       /* Replace (*var)_version with just (*var).  */
!       if (TREE_CODE (SSA_NAME_VAR (var)) == INDIRECT_REF)
! 	{
! 	  tree var2 = TREE_OPERAND (SSA_NAME_VAR (var), 0);
! 	  new_var = var_to_partition_to_var (map, var2);
! 	  copy = copy_node (SSA_NAME_VAR (var));
! 	  if (new_var)
! 	    TREE_OPERAND (copy, 0) = new_var;
! 	  else
! 	    TREE_OPERAND (copy, 0) = var2;
! 	  *p = copy;
! 	}
!     }
! }
  
! /* Take function FNDECL out of SSA form.  */
  
  void
  rewrite_out_of_ssa (fndecl)
*************** rewrite_out_of_ssa (fndecl)
*** 1648,1662 ****
  	  for (i = 0; i < num_ops; i++)
  	    {
  	      use_p = VARRAY_GENERIC_PTR (ops, i);
! 	      *use_p = var_to_partition_to_var (map, *use_p);
  	    }
  
  	  if (def_op (stmt))
  	    {
  	      tree *def_p = def_op (stmt);
  	      *def_p = var_to_partition_to_var (map, *def_p);
  
! 	      if (is_copy && num_ops == 1 && use_p && (*def_p == *use_p))
  		remove = 1;
  	    }
  
--- 1638,1653 ----
  	  for (i = 0; i < num_ops; i++)
  	    {
  	      use_p = VARRAY_GENERIC_PTR (ops, i);
! 	      replace_variable (map, use_p);
  	    }
  
  	  if (def_op (stmt))
  	    {
  	      tree *def_p = def_op (stmt);
  	      *def_p = var_to_partition_to_var (map, *def_p);
+ 	      replace_variable (map, def_p);
  
! 	      if (is_copy && num_ops == 1 && use_p && def_p && (*def_p == *use_p))
  		remove = 1;
  	    }
  
*************** void
*** 1761,1767 ****
  dump_tree_ssa_stats (file)
       FILE *file;
  {
!   long tmp, n_exprs;
  
    fprintf (file, "Total number of statements:                   %6ld\n\n",
  	   ssa_stats.num_stmts);
--- 1752,1758 ----
  dump_tree_ssa_stats (file)
       FILE *file;
  {
!   long n_exprs;
  
    fprintf (file, "Total number of statements:                   %6ld\n\n",
  	   ssa_stats.num_stmts);
*************** dump_tree_ssa_stats (file)
*** 1782,1798 ****
  	   ssa_stats.num_re, PERCENT (ssa_stats.num_re,
  				      n_exprs));
  
-   /* FIXME.  [UNSSA] Not needed after SSA->normal pass is working.  */
- #if 1
-   fprintf (file, "    Optimizations blocked by lack of unSSA:   %6ld (%.0f%%)\n",
- 	   ssa_stats.blocked_optimizations,
- 	   PERCENT (ssa_stats.blocked_optimizations, n_exprs));
- 
-   tmp = ssa_stats.blocked_optimizations - ssa_stats.blocked_by_life_crossing;
-   fprintf (file, "    Optimizations blocked due to pruned SSA:  %6ld (%.0f%%)\n",
- 	   tmp, PERCENT (tmp, n_exprs));
- #endif
- 
    fprintf (file, "\nHash table statistics:\n");
  
    fprintf (file, "    def_blocks: ");
--- 1773,1778 ----
*************** insert_phi_nodes_for (var, dfs, def_maps
*** 1979,1985 ****
  }
  
  
! /* Rewrite the statement pointed by iterator SI into SSA form.
     
     BLOCK_DEFS_P points to a stack with all the definitions found in the
        block.  This is used by rewrite_block to restore the current reaching
--- 1959,1966 ----
  }
  
  
! /* Rewrite the statement pointed by iterator SI into SSA form.  Return 1 if
!    the stmt is to be deleted.  
     
     BLOCK_DEFS_P points to a stack with all the definitions found in the
        block.  This is used by rewrite_block to restore the current reaching
*************** insert_phi_nodes_for (var, dfs, def_maps
*** 2025,2031 ****
        replace the constant and copy propagation passes.  It only does very
        simplistic propagation while renaming.  */
  
! static void
  rewrite_stmt (si, block_defs_p, block_avail_exprs_p)
       block_stmt_iterator si;
       varray_type *block_defs_p;
--- 2006,2012 ----
        replace the constant and copy propagation passes.  It only does very
        simplistic propagation while renaming.  */
  
! static int
  rewrite_stmt (si, block_defs_p, block_avail_exprs_p)
       block_stmt_iterator si;
       varray_type *block_defs_p;
*************** rewrite_stmt (si, block_defs_p, block_av
*** 2039,2045 ****
  
    stmt = bsi_stmt (si);
    if (IS_EMPTY_STMT (stmt))
!     return;
  
    ann = stmt_ann (stmt);
    ssa_stats.num_stmts++;
--- 2020,2026 ----
  
    stmt = bsi_stmt (si);
    if (IS_EMPTY_STMT (stmt))
!     return 0;
  
    ann = stmt_ann (stmt);
    ssa_stats.num_stmts++;
*************** rewrite_stmt (si, block_defs_p, block_av
*** 2086,2103 ****
        val = get_value_for (*op_p, const_and_copies);
        if (val)
  	{
- #if 1
- 	  /* FIXME: [UNSSA] Remove the following check after implementing
- 	     SSA->normal.  For the time being, avoid doing copy propagation
- 	     if that would make two versions of VAL to be live at the same
- 	     time.  */
- 	  if (TREE_CODE (val) == SSA_NAME && !var_is_live (val, ann->bb))
- 	    {
- 	      ssa_stats.blocked_optimizations++;
- 	      continue;
- 	    }
- #endif
- 
  	  /* Gather statistics.  */
  	  if (TREE_CONSTANT (val))
  	    ssa_stats.num_const_prop++;
--- 2067,2072 ----
*************** rewrite_stmt (si, block_defs_p, block_av
*** 2156,2195 ****
  	      fprintf (tree_ssa_dump_file, "'\n");
  	    }
  
! 	  /* FIXME: [UNSSA] Re-enable this once the SSA->normal pass is
! 	     implemented.  Otherwise, this leads to cases where a PHI node
! 	     contains arguments from different variables, which is
! 	     something we can't handle with the current unSSA pass.  It may
! 	     also lead to cases where we re-use the LHS of a computation at
! 	     a point where more than one version of the LHS is live at the
! 	     same time.  */
! #if 0
! 	  ssa_stats.num_re++;
! 	  TREE_OPERAND (stmt, 1) = cached_lhs;
! 	  ann->modified = 1;
! #else
! 	  if (cached_lhs
! 	      && get_value_for (*def_p, currdefs) == cached_lhs
! 	      && var_is_live (cached_lhs, ann->bb))
  	    {
  	      /* A redundant assignment to the same lhs, perhaps a new
                   evaluation of an expression temporary that is still live.
                   Just discard it.  */
  	      ssa_stats.num_re++;
! 	      bsi_remove (&si);
! 	      return;
  	    }
  
! 	  if (var_is_live (cached_lhs, ann->bb))
! 	    {
! 	      register_new_def (*def_p, cached_lhs, block_defs_p);
! 	      TREE_OPERAND (stmt, 1) = cached_lhs;
! 	      ann->modified = 1;
! 	      ssa_stats.num_re++;
! 	    }
! 	  else
! 	    ssa_stats.blocked_optimizations++;
! #endif
  	}
      }
  
--- 2125,2142 ----
  	      fprintf (tree_ssa_dump_file, "'\n");
  	    }
  
! 	  if (cached_lhs && get_value_for (*def_p, currdefs) == cached_lhs)
  	    {
  	      /* A redundant assignment to the same lhs, perhaps a new
                   evaluation of an expression temporary that is still live.
                   Just discard it.  */
  	      ssa_stats.num_re++;
! 	      return 1;
  	    }
  
! 	  ssa_stats.num_re++;
! 	  TREE_OPERAND (stmt, 1) = cached_lhs;
! 	  ann->modified = 1;
  	}
      }
  
*************** rewrite_stmt (si, block_defs_p, block_av
*** 2222,2227 ****
--- 2169,2176 ----
        register_new_def (SSA_NAME_VAR (VDEF_RESULT (vdef)), 
  			VDEF_RESULT (vdef), block_defs_p);
      }
+ 
+   return 0;
  }
  
  
*************** get_def_blocks_for (var)
*** 2692,2767 ****
    dm.var = var;
    return (struct def_blocks_d *) htab_find (def_blocks, (void *) &dm);
  }
- 
- #if 1
- /* Return true if the variable VAR is live at this point of the
-    dominator tree walk.  This means that the current reaching definition
-    for VAR is itself and that VAR is livein at basic block BB.
- 
-    FIXME: [UNSSA] This will not be necessary when the unSSA pass is
-    implemented.  */
- 
- static bool
- var_is_live (var, bb)
-      tree var;
-      basic_block bb;
- {
-   int i;
-   basic_block def_bb;
-   struct def_blocks_d *def_map;
-   tree real_var = SSA_NAME_VAR (var);
- 
-   if (get_value_for (real_var, currdefs) != var)
-     {
-       ssa_stats.blocked_by_life_crossing++;
-       return false;
-     }
- 
-   /* This is gross, but since it's temporary, close your eyes.  It's needed
-      to avoid miscompiling java/jcf-write.c:generate_classfile, where the
-      fully pruned SSA form is not inserting PHI nodes in the main loop of
-      the function for variable 'ptr'.  This makes two versions of 'ptr'
-      live at the same time.
- 
-      If there are any blocks between VAR's definition block and BB where
-      VAR is defined again, then two versions of VAR are live at the same
-      time.  Notice that this heuristic assumes that blocks in the path from
-      DEF_BB to BB will be numbered in ascending order.  This is only true
-      when the CFG is initially built.  But since we only use this in the
-      SSA renaming pass, it should still be safe to assume.  Another
-      limitation is that if there exists another overlapping definition for
-      VAR in block BB, this code will not realize that.  */
-   def_map = get_def_blocks_for (real_var);
-   def_bb = bb_for_stmt (SSA_NAME_DEF_STMT (var));
-   if (def_bb && bitmap_first_set_bit (def_map->def_blocks) >= 0)
-     EXECUTE_IF_SET_IN_BITMAP (def_map->def_blocks, def_bb->index + 1, i,
-       { if (i < bb->index) return false; });
- 
-   /* VAR doesn't have definitions between DEF_BB and BB.  If BB is inside a
-      loop but DEF_BB is outside BB's loop, we may still have definitions
-      below BB wrapping around in cases where the pruned SSA form has
-      removed a PHI function for VAR at the header block for the loop.  */
-   {
-     if (def_bb
- 	&& loops
- 	&& bb->loop_depth > 0
- 	&& (def_bb->loop_depth == 0
- 	    || !flow_bb_inside_loop_p (bb->loop_father, def_bb)))
-       EXECUTE_IF_SET_IN_BITMAP (def_map->def_blocks, bb->index + 1, i,
- 	{
- 	  basic_block other_def_bb = BASIC_BLOCK (i);
- 
- 	  /* If BB is inside the same loop L as the other definition block
- 	     (OTHER_DEF_BB), definition at OTHER_DEF_BB wraps around and
- 	     reaches VAR at BB.  Meaning that the other definition at
- 	     OTHER_DEF_BB overlaps with VAR at DEF_BB.  */
- 	  if (flow_bb_inside_loop_p (other_def_bb->loop_father, bb)
- 	      || flow_bb_inside_loop_p (bb->loop_father, other_def_bb))
- 	    return false;
- 	});
-   }
- 
- 
-   return true;
- }
- #endif
--- 2641,2643 ----


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