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]

[lno] Fix spec compilation failures on ppc


Hello,

this patch should fix the spec compilation failures on ppc reported by
Dorit.  To do this it also makes us remove the unused induction
variables directly, without having to rely on dce doing it.

Zdenek

Index: ChangeLog.lno
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/ChangeLog.lno,v
retrieving revision 1.1.2.101
diff -c -3 -p -r1.1.2.101 ChangeLog.lno
*** ChangeLog.lno	23 Mar 2004 08:32:22 -0000	1.1.2.101
--- ChangeLog.lno	23 Mar 2004 11:26:43 -0000
***************
*** 1,5 ****
--- 1,26 ----
  2004-03-23  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
  
+ 	* tree-flow.h (tree_ssa_dce_no_cfg_changes): Declaration removed.
+ 	* tree-ssa-dce.c (remove_dead_stmt): Invalidate dominators if we
+ 	thread the edge.
+ 	(tree_ssa_dce_no_cfg_changes): Removed.
+ 	(perform_tree_ssa_dce, tree_ssa_dce, perform_tree_ssa_dce): Remove
+ 	no cfg changes mode.
+ 	* tree-ssa-loop-ivopts.c (force_gimple_operand): Handle overflowed
+ 	constants.
+ 	(find_interesting_uses_outer_or_nonlin): New.
+ 	(find_interesting_uses_op, find_interesting_uses_outer): Use it.
+ 	(find_interesting_uses_cond, idx_record_use,
+ 	find_interesting_uses_stmt): Changed due to find_interesting_uses_op
+ 	change.
+ 	(create_new_iv, remove_statement, rewrite_use_nonlinear_expr,
+ 	rewrite_use_outer, tree_ssa_iv_optimize): Handle direct removal of
+ 	unused ivs.
+ 	(remove_unused_ivs): New.
+ 	(tree_ssa_iv_optimize_loop): Call it.
+ 
+ 2004-03-23  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
+ 
  	* Makefile.in (SCEV_H): New.
  	(tree-ssa-loop-ivcanon.o, tree-ssa-loop-ivopts.o,
  	tree-scalar-evolution.o, tree-data-ref.o, tree-dg.o,
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.177.2.18
diff -c -3 -p -r1.1.4.177.2.18 tree-flow.h
*** tree-flow.h	21 Mar 2004 13:34:20 -0000	1.1.4.177.2.18
--- tree-flow.h	23 Mar 2004 11:26:43 -0000
*************** extern void replace_exp (tree *, tree);
*** 590,598 ****
  extern bool cprop_into_stmt (tree, varray_type);
  extern void cprop_into_successor_phis (basic_block, varray_type);
  
- /* In tree-ssa-dce.c.  */
- void tree_ssa_dce_no_cfg_changes (void);
- 
  /* In tree-ssa-loop*.c  */
  struct loops *tree_loop_optimizer_init (FILE *);
  void tree_ssa_lim (struct loops *loops);
--- 590,595 ----
Index: tree-ssa-dce.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dce.c,v
retrieving revision 1.1.2.72.2.4
diff -c -3 -p -r1.1.2.72.2.4 tree-ssa-dce.c
*** tree-ssa-dce.c	21 Mar 2004 03:20:21 -0000	1.1.2.72.2.4
--- tree-ssa-dce.c	23 Mar 2004 11:26:44 -0000
*************** remove_dead_stmt (block_stmt_iterator *i
*** 697,702 ****
--- 697,705 ----
        redirect_edge_and_branch (bb->succ, post_dom_bb);
        PENDING_STMT (bb->succ) = NULL;
  
+       /* Dominators are wrong now.  */
+       free_dominance_info (CDI_DOMINATORS);
+ 
        /* The edge is no longer associated with a conditional, so it does
  	 not have TRUE/FALSE flags.  */
        bb->succ->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
*************** tree_dce_done (bool aggressive)
*** 798,805 ****
     In aggressive mode, control dependences are taken into account, which
     results in more dead code elimination, but at the cost of some time.
  
-    If NO_CFG_CHANGES is true, avoid changing cfg.
- 
     FIXME: Aggressive mode before PRE doesn't work currently because
  	  the dominance info is not invalidated after DCE1.  This is
  	  not an issue right now because we only run aggressive DCE
--- 801,806 ----
*************** tree_dce_done (bool aggressive)
*** 807,819 ****
  	  start experimenting with pass ordering.  */
  
  static void
! perform_tree_ssa_dce (bool aggressive, bool no_cfg_changes)
  {
    struct edge_list *el = NULL;
  
-   if (no_cfg_changes && aggressive)
-     abort ();
- 
    tree_dce_init (aggressive);
  
    if (aggressive)
--- 808,817 ----
  	  start experimenting with pass ordering.  */
  
  static void
! perform_tree_ssa_dce (bool aggressive)
  {
    struct edge_list *el = NULL;
  
    tree_dce_init (aggressive);
  
    if (aggressive)
*************** perform_tree_ssa_dce (bool aggressive, b
*** 835,842 ****
    if (aggressive)
      free_dominance_info (CDI_POST_DOMINATORS);
  
!   if (!no_cfg_changes)
!     cleanup_tree_cfg ();
  
    /* Debugging dumps.  */
    if (dump_file)
--- 833,839 ----
    if (aggressive)
      free_dominance_info (CDI_POST_DOMINATORS);
  
!   cleanup_tree_cfg ();
  
    /* Debugging dumps.  */
    if (dump_file)
*************** perform_tree_ssa_dce (bool aggressive, b
*** 848,872 ****
    tree_dce_done (aggressive);
  }
  
- /* Cleanup the dead code, but avoid cfg changes.  */
- 
- void
- tree_ssa_dce_no_cfg_changes (void)
- {
-   perform_tree_ssa_dce (false, true);
- }
- 
  /* Pass entry points.  */
  static void
  tree_ssa_dce (void)
  {
!   perform_tree_ssa_dce (/*aggressive=*/false, false);
  }
  
  static void
  tree_ssa_cd_dce (void)
  {
!   perform_tree_ssa_dce (/*aggressive=*/optimize >= 2, false);
  }
  
  static bool
--- 845,861 ----
    tree_dce_done (aggressive);
  }
  
  /* Pass entry points.  */
  static void
  tree_ssa_dce (void)
  {
!   perform_tree_ssa_dce (/*aggressive=*/false);
  }
  
  static void
  tree_ssa_cd_dce (void)
  {
!   perform_tree_ssa_dce (/*aggressive=*/optimize >= 2);
  }
  
  static bool
Index: tree-ssa-loop-ivopts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-loop-ivopts.c,v
retrieving revision 1.1.2.18
diff -c -3 -p -r1.1.2.18 tree-ssa-loop-ivopts.c
*** tree-ssa-loop-ivopts.c	22 Mar 2004 06:35:52 -0000	1.1.2.18
--- tree-ssa-loop-ivopts.c	23 Mar 2004 11:26:44 -0000
*************** force_gimple_operand (tree expr, tree *s
*** 761,768 ****
        break;
      }
  
!   if (TREE_CODE (expr) == ADDR_EXPR)
      {
        stmt = build (MODIFY_EXPR, void_type_node, var, expr);
        name = make_ssa_name (var, stmt);
        TREE_OPERAND (stmt, 0) = name;
--- 761,770 ----
        break;
      }
  
!   /* Some specially handled codes:  */
!   switch (TREE_CODE (expr))
      {
+     case ADDR_EXPR:
        stmt = build (MODIFY_EXPR, void_type_node, var, expr);
        name = make_ssa_name (var, stmt);
        TREE_OPERAND (stmt, 0) = name;
*************** force_gimple_operand (tree expr, tree *s
*** 778,786 ****
        update_addressable_flag (TREE_OPERAND (stmt, 1));
  
        return name;
-     }
  
!   abort ();
  }
  
  /* If TYPE is an array type, corresponding pointer type is returned,
--- 780,802 ----
        update_addressable_flag (TREE_OPERAND (stmt, 1));
  
        return name;
  
!     case INTEGER_CST:
!       if (!TREE_OVERFLOW (expr))
! 	abort ();
! 
!       stmt = build (MODIFY_EXPR, void_type_node, var, expr);
!       name = make_ssa_name (var, stmt);
!       TREE_OPERAND (stmt, 0) = name;
! 
!       *stmts = alloc_stmt_list ();
!       tsi = tsi_last (*stmts);
!       tsi_link_after (&tsi, stmt, TSI_CONTINUE_LINKING);
!       return name;
! 
!     default:
!       abort ();
!     }
  }
  
  /* If TYPE is an array type, corresponding pointer type is returned,
*************** record_invariant (struct ivopts_data *da
*** 1884,1970 ****
    bitmap_set_bit (data->relevant, SSA_NAME_VERSION (op));
  }
  
! /* Checks whether the use *OP_P is interesting and if so, records it.  */
  
! static void
! find_interesting_uses_op (struct ivopts_data *data, tree *op_p)
  {
    struct iv *iv;
    struct iv *civ;
  
!   if (TREE_CODE (*op_p) != SSA_NAME)
!     return;
  
!   iv = get_iv (data, *op_p);
    if (!iv)
!     return;
    
    if (iv->have_use_for)
      {
!       struct iv_use *use = iv_use (data, iv->use_id);
  
        if (use->type != USE_NONLINEAR_EXPR
  	  && use->type != USE_OUTER)
  	abort ();
  
!       use->type = USE_NONLINEAR_EXPR;
!       return;
      }
  
    if (zero_p (iv->step))
      {
!       record_invariant (data, *op_p, true);
!       return;
      }
    iv->have_use_for = true;
  
    civ = xmalloc (sizeof (struct iv));
    *civ = *iv;
  
!   iv->use_id = record_use (data, op_p, civ, SSA_NAME_DEF_STMT (*op_p),
! 			   USE_NONLINEAR_EXPR)->id;
! }
! 
! /* Records a definition of induction variable *OP_P that is used outside of the
!    loop.  */
! 
! static void
! find_interesting_uses_outer (struct ivopts_data *data, tree *op_p)
! {
!   struct iv *iv;
!   struct iv *civ;
!   tree stmt;
! 
!   if (TREE_CODE (*op_p) != SSA_NAME)
      abort ();
  
!   iv = get_iv (data, *op_p);
!   if (!iv)
!     abort ();
!   
!   if (iv->have_use_for)
!     {
!       struct iv_use *use = iv_use (data, iv->use_id);
  
!       if (use->type != USE_NONLINEAR_EXPR
! 	  && use->type != USE_OUTER)
! 	abort ();
  
!       return;
!     }
  
!   if (zero_p (iv->step))
!     {
!       record_invariant (data, *op_p, true);
!       return;
!     }
!   iv->have_use_for = true;
  
!   civ = xmalloc (sizeof (struct iv));
!   *civ = *iv;
  
!   stmt = SSA_NAME_DEF_STMT (*op_p);
!   iv->use_id = record_use (data, op_p, civ, stmt, USE_OUTER)->id;
  }
  
  /* Checks whether the condition *COND_P in STMT is interesting
--- 1900,1976 ----
    bitmap_set_bit (data->relevant, SSA_NAME_VERSION (op));
  }
  
! /* Checks whether the use OP is interesting and if so, records it
!    as TYPE.  */
  
! static struct iv_use *
! find_interesting_uses_outer_or_nonlin (struct ivopts_data *data, tree op,
! 				       enum use_type type)
  {
    struct iv *iv;
    struct iv *civ;
+   tree stmt, *op_p;
+   struct iv_use *use;
  
!   if (TREE_CODE (op) != SSA_NAME)
!     return NULL;
  
!   iv = get_iv (data, op);
    if (!iv)
!     return NULL;
    
    if (iv->have_use_for)
      {
!       use = iv_use (data, iv->use_id);
  
        if (use->type != USE_NONLINEAR_EXPR
  	  && use->type != USE_OUTER)
  	abort ();
  
!       if (type == USE_NONLINEAR_EXPR)
! 	use->type = USE_NONLINEAR_EXPR;
!       return use;
      }
  
    if (zero_p (iv->step))
      {
!       record_invariant (data, op, true);
!       return NULL;
      }
    iv->have_use_for = true;
  
    civ = xmalloc (sizeof (struct iv));
    *civ = *iv;
  
!   stmt = SSA_NAME_DEF_STMT (op);
!   if (TREE_CODE (stmt) == PHI_NODE)
!     op_p = &PHI_RESULT (stmt);
!   else if (TREE_CODE (stmt) == MODIFY_EXPR)
!     op_p = &TREE_OPERAND (stmt, 0);
!   else
      abort ();
  
!   use = record_use (data, op_p, civ, stmt, type);
!   iv->use_id = use->id;
  
!   return use;
! }
  
! /* Checks whether the use OP is interesting and if so, records it.  */
  
! static struct iv_use *
! find_interesting_uses_op (struct ivopts_data *data, tree op)
! {
!   return find_interesting_uses_outer_or_nonlin (data, op, USE_NONLINEAR_EXPR);
! }
  
! /* Records a definition of induction variable OP that is used outside of the
!    loop.  */
  
! static struct iv_use *
! find_interesting_uses_outer (struct ivopts_data *data, tree op)
! {
!   return find_interesting_uses_outer_or_nonlin (data, op, USE_OUTER);
  }
  
  /* Checks whether the condition *COND_P in STMT is interesting
*************** find_interesting_uses_cond (struct ivopt
*** 2013,2020 ****
  	 ??? TODO -- it is not really important to handle this case.  */
        || (!zero_p (iv0->step) && !zero_p (iv1->step)))
      {
!       find_interesting_uses_op (data, op0_p);
!       find_interesting_uses_op (data, op1_p);
        return;
      }
  
--- 2019,2026 ----
  	 ??? TODO -- it is not really important to handle this case.  */
        || (!zero_p (iv0->step) && !zero_p (iv1->step)))
      {
!       find_interesting_uses_op (data, *op0_p);
!       find_interesting_uses_op (data, *op1_p);
        return;
      }
  
*************** static bool
*** 2082,2088 ****
  idx_record_use (tree base ATTRIBUTE_UNUSED, tree *idx,
  		void *data)
  {
!   find_interesting_uses_op (data, idx);
    return true;
  }
  
--- 2088,2094 ----
  idx_record_use (tree base ATTRIBUTE_UNUSED, tree *idx,
  		void *data)
  {
!   find_interesting_uses_op (data, *idx);
    return true;
  }
  
*************** find_interesting_uses_stmt (struct ivopt
*** 2180,2186 ****
  
  	  iv = get_iv (data, lhs);
  
! 	  if (iv)
  	    {
  	      /* If the variable is used outside of the loop, we must either
  		 preserve it or express the final value in other way.  */
--- 2186,2192 ----
  
  	  iv = get_iv (data, lhs);
  
! 	  if (iv && !zero_p (iv->step))
  	    {
  	      /* If the variable is used outside of the loop, we must either
  		 preserve it or express the final value in other way.  */
*************** find_interesting_uses_stmt (struct ivopt
*** 2188,2194 ****
  	      if (loop
  		  && loop != data->current_loop
  		  && !flow_loop_nested_p (data->current_loop, loop))
! 		find_interesting_uses_outer (data, &TREE_OPERAND (stmt, 0));
  
  	      return;
  	    }
--- 2194,2200 ----
  	      if (loop
  		  && loop != data->current_loop
  		  && !flow_loop_nested_p (data->current_loop, loop))
! 		find_interesting_uses_outer (data, lhs);
  
  	      return;
  	    }
*************** find_interesting_uses_stmt (struct ivopt
*** 2202,2207 ****
--- 2208,2215 ----
  
  	case 'r':
  	  find_interesting_uses_address (data, stmt, &TREE_OPERAND (stmt, 1));
+ 	  if (TREE_CODE_CLASS (TREE_CODE (lhs)) == 'r')
+ 	    find_interesting_uses_address (data, stmt, &TREE_OPERAND (stmt, 0));
  	  return;
  
  	default: ;
*************** find_interesting_uses_stmt (struct ivopt
*** 2210,2216 ****
        if (TREE_CODE_CLASS (TREE_CODE (lhs)) == 'r')
  	{
  	  find_interesting_uses_address (data, stmt, &TREE_OPERAND (stmt, 0));
! 	  find_interesting_uses_op (data, &TREE_OPERAND (stmt, 1));
  	  return;
  	}
      }
--- 2218,2224 ----
        if (TREE_CODE_CLASS (TREE_CODE (lhs)) == 'r')
  	{
  	  find_interesting_uses_address (data, stmt, &TREE_OPERAND (stmt, 0));
! 	  find_interesting_uses_op (data, rhs);
  	  return;
  	}
      }
*************** find_interesting_uses_stmt (struct ivopt
*** 2221,2227 ****
        lhs = PHI_RESULT (stmt);
        iv = get_iv (data, lhs);
  
!       if (iv)
  	{
  	  /* If the variable is used outside of the loop, we must preserve it
  	     or express the final value in other way.  */
--- 2229,2235 ----
        lhs = PHI_RESULT (stmt);
        iv = get_iv (data, lhs);
  
!       if (iv && !zero_p (iv->step))
  	{
  	  /* If the variable is used outside of the loop, we must preserve it
  	     or express the final value in other way.  */
*************** find_interesting_uses_stmt (struct ivopt
*** 2230,2236 ****
  	  if (loop
  	      && loop != data->current_loop
  	      && !flow_loop_nested_p (data->current_loop, loop))
! 	    find_interesting_uses_outer (data, &PHI_RESULT (stmt));
  
  	  return;
  	}
--- 2238,2244 ----
  	  if (loop
  	      && loop != data->current_loop
  	      && !flow_loop_nested_p (data->current_loop, loop))
! 	    find_interesting_uses_outer (data, lhs);
  
  	  return;
  	}
*************** find_interesting_uses_stmt (struct ivopt
*** 2258,2264 ****
        if (!iv)
  	continue;
  
!       find_interesting_uses_op (data, op_p);
      }
  }
  
--- 2266,2272 ----
        if (!iv)
  	continue;
  
!       find_interesting_uses_op (data, *op_p);
      }
  }
  
*************** create_new_iv (struct ivopts_data *data,
*** 4474,4479 ****
--- 4482,4491 ----
        /* Mark that the iv is preserved.  */
        name_info (data, cand->var_before)->preserve_biv = true;
        name_info (data, cand->var_after)->preserve_biv = true;
+ 
+       /* Rewrite the increment so that it uses var_before directly.  */
+       find_interesting_uses_op (data, cand->var_after)->selected = cand;
+       
        return;
      }
   
*************** create_new_ivs (struct ivopts_data *data
*** 4501,4515 ****
      });
  }
  
! /* Removes statement STMT (real or a phi node).  */
  
  static void
! remove_statement (tree stmt)
  {
    if (TREE_CODE (stmt) == PHI_NODE)
      {
!       /* Prevent the ssa name defined by the statement from being removed.  */
!       PHI_RESULT (stmt) = NULL;
        remove_phi_node (stmt, NULL_TREE, bb_for_stmt (stmt));
      }
    else
--- 4513,4531 ----
      });
  }
  
! /* Removes statement STMT (real or a phi node).  If INCLUDING_DEFINED_NAME
!    is true, remove also the ssa name defined by the statement.  */
  
  static void
! remove_statement (tree stmt, bool including_defined_name)
  {
    if (TREE_CODE (stmt) == PHI_NODE)
      {
!       if (!including_defined_name)
! 	{
! 	  /* Prevent the ssa name defined by the statement from being removed.  */
! 	  PHI_RESULT (stmt) = NULL;
! 	}
        remove_phi_node (stmt, NULL_TREE, bb_for_stmt (stmt));
      }
    else
*************** rewrite_use_nonlinear_expr (struct ivopt
*** 4562,4568 ****
  	bsi_insert_after (&bsi, stmts, BSI_CONTINUE_LINKING);
        ass = build (MODIFY_EXPR, TREE_TYPE (tgt), tgt, op);
        bsi_insert_after (&bsi, ass, BSI_NEW_STMT);
!       remove_statement (use->stmt);
        SSA_NAME_DEF_STMT (tgt) = ass;
      }
    else
--- 4578,4584 ----
  	bsi_insert_after (&bsi, stmts, BSI_CONTINUE_LINKING);
        ass = build (MODIFY_EXPR, TREE_TYPE (tgt), tgt, op);
        bsi_insert_after (&bsi, ass, BSI_NEW_STMT);
!       remove_statement (use->stmt, false);
        SSA_NAME_DEF_STMT (tgt) = ass;
      }
    else
*************** rewrite_use_outer (struct ivopts_data *d
*** 4709,4715 ****
  	bsi_insert_on_edge (exit, stmts);
        ass = build (MODIFY_EXPR, type, tgt, op);
        bsi_insert_on_edge (exit, ass);
!       remove_statement (use->stmt);
        SSA_NAME_DEF_STMT (tgt) = ass;
        return;
      }
--- 4725,4731 ----
  	bsi_insert_on_edge (exit, stmts);
        ass = build (MODIFY_EXPR, type, tgt, op);
        bsi_insert_on_edge (exit, ass);
!       remove_statement (use->stmt, false);
        SSA_NAME_DEF_STMT (tgt) = ass;
        return;
      }
*************** rewrite_uses (struct ivopts_data *data)
*** 4768,4773 ****
--- 4784,4810 ----
      }
  }
  
+ /* Removes the ivs that are not used after rewriting.  */
+ 
+ static void
+ remove_unused_ivs (struct ivopts_data *data)
+ {
+   unsigned j;
+ 
+   EXECUTE_IF_SET_IN_BITMAP (data->relevant, 0, j,
+     {
+       struct version_info *info;
+ 
+       info = ver_info (data, j);
+       if (info->iv
+ 	  && !zero_p (info->iv->step)
+ 	  && !info->inv_id
+ 	  && !info->iv->have_use_for
+ 	  && !info->preserve_biv)
+ 	remove_statement (SSA_NAME_DEF_STMT (info->iv->ssa_name), true);
+     });
+ }
+ 
  /* Frees data allocated by the optimization of a single loop.  */
  
  static void
*************** tree_ssa_iv_optimize_loop (struct ivopts
*** 4909,4914 ****
--- 4946,4955 ----
    
    /* Rewrite the uses (item 4, part 2).  */
    rewrite_uses (data);
+ 
+   /* Remove the ivs that are unused after rewriting.  */
+   remove_unused_ivs (data);
+ 
    loop_commit_inserts ();
  
    BITMAP_XFREE (iv_set);
*************** finish:
*** 4923,4929 ****
  void
  tree_ssa_iv_optimize (struct loops *loops)
  {
-   bool run_dce = false;
    struct loop *loop;
    struct ivopts_data data;
  
--- 4964,4969 ----
*************** tree_ssa_iv_optimize (struct loops *loop
*** 4938,4944 ****
    /* Scan the loops, inner ones first.  */
    while (loop != loops->tree_root)
      {
!       run_dce |= tree_ssa_iv_optimize_loop (&data, loop);
  
        if (loop->next)
  	{
--- 4978,4989 ----
    /* Scan the loops, inner ones first.  */
    while (loop != loops->tree_root)
      {
!       if (tree_ssa_iv_optimize_loop (&data, loop))
! 	{
! #ifdef ENABLE_CHECKING
! 	  verify_ssa ();
! #endif
! 	}
  
        if (loop->next)
  	{
*************** tree_ssa_iv_optimize (struct loops *loop
*** 4951,4960 ****
      }
  
    tree_ssa_iv_optimize_finalize (loops, &data);
- 
-   /* Cleanup the now unused variables.  */
-   if (run_dce)
-     tree_ssa_dce_no_cfg_changes ();
  
    timevar_pop (TV_TREE_LOOP_IVOPTS);
  }
--- 4996,5001 ----


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