[tree-ssa] Removing redundant loads

Andrew MacLeod amacleod@redhat.com
Fri May 30 00:15:00 GMT 2003


On Thu, 2003-05-29 at 17:30, Daniel Berlin wrote:
> 

> > What we should do is make these transformations conditional as any 
> > other
> > transformation.  Later on, when PRE is finished, we can start playing
> > the flags game with SPEC or what-have-you.
> 
> PRE is of course, waiting on live range out-of-ssa stuff.
> 
Which mostly works now. It bootstraps on its own now, and passes all the
testsuites. When I turn on copyprop however, there is a problem during
stage2 boostrap. Im trying to track it down now.

I've attached the patch if you want to start using it. I dont really
feel like enabling it in general until I find out what the issue with
copyprop is.

Andrew


-------------- next part --------------
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.82
diff -c -p -r1.1.4.82 tree-ssa.c
*** tree-ssa.c	29 May 2003 20:40:32 -0000	1.1.4.82
--- tree-ssa.c	29 May 2003 21:51:08 -0000
*************** struct ssa_stats_d
*** 149,156 ****
    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
--- 149,155 ----
    long num_const_prop;
    long num_copy_prop;
    long num_re;
! #ifdef NO_UNSSA
    long blocked_optimizations;
    long blocked_by_life_crossing;
  #endif
*************** static void set_livein_block		PARAMS ((t
*** 169,175 ****
  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 *));
--- 168,174 ----
  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 ((
*** 208,216 ****
  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
  
--- 207,215 ----
  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 *));
  
! #ifdef NO_UNSSA
  static bool var_is_live			PARAMS ((tree, basic_block));
  #endif
  
*************** rewrite_block (bb, eq_expr_value)
*** 764,771 ****
    /* 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
--- 763,773 ----
    /* 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)
*** 1524,1534 ****
  	      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);
--- 1526,1531 ----
*************** assign_vars (map)
*** 1545,1560 ****
    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)
--- 1542,1579 ----
    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)
*** 1572,1577 ****
--- 1591,1599 ----
  
    tree_ssa_dump_file = dump_begin (TDI_optimized, &tree_ssa_dump_flags);
  
+   if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
+     dump_tree_cfg (tree_ssa_dump_file, tree_ssa_dump_flags & ~TDF_DETAILS);
+ 
    map = create_ssa_var_map ();
  
    /* Shrink the map to include only referenced variables.  Exclude variables
*************** rewrite_out_of_ssa (fndecl)
*** 1625,1639 ****
  	  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;
  	    }
  
--- 1647,1662 ----
  	  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;
  	    }
  
*************** rewrite_out_of_ssa (fndecl)
*** 1663,1668 ****
--- 1686,1694 ----
    /* If any copies were inserted on edges, actually insert them now.  */
    bsi_commit_edge_inserts (0, NULL);
  
+   if (tree_ssa_dump_file && (tree_ssa_dump_flags & TDF_DETAILS))
+     dump_tree_cfg (tree_ssa_dump_file, tree_ssa_dump_flags & ~TDF_DETAILS);
+ 
    /* Do some cleanups which reduce the amount of data the
       tree->rtl expanders deal with.  */
    do
*************** void
*** 1738,1744 ****
  dump_tree_ssa_stats (file)
       FILE *file;
  {
!   long tmp, n_exprs;
  
    fprintf (file, "Total number of statements:                   %6ld\n\n",
  	   ssa_stats.num_stmts);
--- 1764,1773 ----
  dump_tree_ssa_stats (file)
       FILE *file;
  {
!   long n_exprs;
! #ifdef NO_UNSSA
!   long tmp;
! #endif
  
    fprintf (file, "Total number of statements:                   %6ld\n\n",
  	   ssa_stats.num_stmts);
*************** dump_tree_ssa_stats (file)
*** 1759,1766 ****
  	   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));
--- 1788,1794 ----
  	   ssa_stats.num_re, PERCENT (ssa_stats.num_re,
  				      n_exprs));
  
! #ifdef NO_UNSSA
    fprintf (file, "    Optimizations blocked by lack of unSSA:   %6ld (%.0f%%)\n",
  	   ssa_stats.blocked_optimizations,
  	   PERCENT (ssa_stats.blocked_optimizations, n_exprs));
*************** insert_phi_nodes_for (var, dfs, def_maps
*** 1956,1962 ****
  }
  
  
! /* 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
--- 1984,1991 ----
  }
  
  
! /* Rewrite the statement pointed by iterator SI into SSA form.  Return 1 if
!    the stmt kis 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
*** 2002,2008 ****
        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;
--- 2031,2037 ----
        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
*** 2016,2022 ****
  
    stmt = bsi_stmt (si);
    if (IS_EMPTY_STMT (stmt))
!     return;
  
    ann = stmt_ann (stmt);
    ssa_stats.num_stmts++;
--- 2045,2051 ----
  
    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
*** 2063,2073 ****
        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++;
--- 2092,2098 ----
        val = get_value_for (*op_p, const_and_copies);
        if (val)
  	{
! #ifdef NO_UNSSA
  	  if (TREE_CODE (val) == SSA_NAME && !var_is_live (val, ann->bb))
  	    {
  	      ssa_stats.blocked_optimizations++;
*************** rewrite_stmt (si, block_defs_p, block_av
*** 2107,2115 ****
      fold_stmt (stmt);
  
    /* Step 2.  Check for redundant computations.  Do this optimization only
!      for assignments that make no calls and have no aliased stores
!      nor volatile references and no side effects (i.e., no VDEFs).  */
!   may_optimize_p = !ann->makes_aliased_stores
  		   && !ann->has_volatile_ops
  		   && vdefs == NULL;
  
--- 2132,2141 ----
      fold_stmt (stmt);
  
    /* Step 2.  Check for redundant computations.  Do this optimization only
!      for assignments that make no calls and have no aliased nor volatile
!      references and no side effects (i.e., no VDEFs).  */
!   may_optimize_p = !ann->makes_aliased_loads
! 		   && !ann->makes_aliased_stores
  		   && !ann->has_volatile_ops
  		   && vdefs == NULL;
  
*************** rewrite_stmt (si, block_defs_p, block_av
*** 2133,2159 ****
  	      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)
  	    {
  	      /* 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);
--- 2159,2178 ----
  	      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;
  	    }
+ 
+ #ifndef NO_UNSSA
+ 	  ssa_stats.num_re++;
+ 	  TREE_OPERAND (stmt, 1) = cached_lhs;
+ 	  ann->modified = 1;
+ #else
  	  if (var_is_live (cached_lhs, ann->bb))
  	    {
  	      register_new_def (*def_p, cached_lhs, block_defs_p);
*************** rewrite_stmt (si, block_defs_p, block_av
*** 2196,2201 ****
--- 2215,2222 ----
        register_new_def (SSA_NAME_VAR (VDEF_RESULT (vdef)), 
  			VDEF_RESULT (vdef), block_defs_p);
      }
+ 
+   return 0;
  }
  
  
*************** avail_expr_hash (p)
*** 2603,2609 ****
        if (TREE_CODE (op) == SSA_NAME)
  	val = iterative_hash_object (SSA_NAME_VERSION (op), val);
        else
! 	val = iterative_hash_expr (op, val);
      }
  
    /* Add the SSA version numbers of every vuse operand.  This is important
--- 2624,2630 ----
        if (TREE_CODE (op) == SSA_NAME)
  	val = iterative_hash_object (SSA_NAME_VERSION (op), val);
        else
! 	val = iterative_hash_object (op, val);
      }
  
    /* Add the SSA version numbers of every vuse operand.  This is important
*************** get_def_blocks_for (var)
*** 2670,2682 ****
    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)
--- 2691,2700 ----
    return (struct def_blocks_d *) htab_find (def_blocks, (void *) &dm);
  }
  
! #ifdef NO_UNSSA
  /* 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.  */
  
  static bool
  var_is_live (var, bb)


More information about the Gcc-patches mailing list