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]

[tcb] Various fixes



Some speedup fixes to copy propagation and incremental SSA update. In copy propagation we now limit the maximum length of copy-of chains we are willing to traverse. More than 82% of all copy-of chains are shorter than 5 (across cc1-i-files, DLV, TRAMP3D and MICO), so I left it at that.


There's a new flag used during SSA renaming. If a statement is only interesting in the names that it generates, and we are not interested in renaming its use operands, then it can be marked with REGISTER_DEFS_IN_STMT.

There are various other fixes for bugs I ran into while re-arranging the order of the optimization passes. This patch still doesn't include the re-scheduled passes because I still haven't fixed all the bugs, but the patch was getting too big, so I'll leave the reordering for later.

Bootstrapped and tested x86, x86-64, alpha, ppc and ia64.


Diego.
2005-02-14  Diego Novillo  <dnovillo@redhat.com>

	* tree-into-ssa.c (REGISTER_DEFS_IN_STMT): Define.
	(insert_phi_nodes_for): Mark with REGISTER_DEFS_IN_STMT.
	(rewrite_update_init_block): Only register the LHS of PHI
	nodes marked with REGISTER_DEFS_IN_STMT.
	(rewrite_update_stmt): Likewise.
	Do not update use operands of statements that are not marked
	with REWRITE_THIS_STMT.
	(prepare_block_for_update): Mark with REGISTER_DEFS_IN_STMT
	statements that define new names.
	Only mark statements with REWRITE_THIS_STMT if they reference
	old names and do not define new names.
	* tree-ssa-copy.c (get_last_copy_of): Limit the amount of
	copy-of traversal.
	(copy_prop_visit_assignment): Get the copy-of value from the
	RHS to avoid creating long copy-of chains.
	(copy_prop_visit_phi_node): Do the opposite.  Use the
	arguments themselves as the initial link in the copy-of chain.
	(fini_copy_prop): Fix comment.
	* tree-ssa-dom.c (tree_ssa_dominator_optimize): Add getenv
	hackery to allow disabling DOM at compile time.
	(propagate_to_outgoing_edges): Likewise.
	(simplify_cond_and_lookup_avail_expr): Guard for NULL low and
	high.
	* tree-ssa-pre.c (phi_translate): Handle tcc_comparison.
	(valid_in_set): Likewise.
	(find_or_generate_expression): Likewise.
	(create_expression_by_pieces): Likewise.
	(insert_into_preds_of_block): Likewise.
	(insert_aux): Likewise.
	(create_value_expr_from): Likewise.
	(compute_avail): Likewise.
	Handle TREE_INVARIANT values.  Re-order checks to check for
	expressions first.
	(execute_pre): Change formatting of stats messages.
	* tree-vn.c (set_value_handle): Handle TREE_INVARIANT.
	(get_value_handle): Likewise.
	* tree-vrp.c (expr_computes_nonnull): Recognize address of
	references.
	(extract_range_from_assert): Don't build unnecessary
	constants.
	(extract_range_from_binary_expr): Pointer arithmetic may
	include operations other than + or -.
	(extract_range_from_unary_expr): Set cast operations of
	anti-ranges to VARYING.
	(build_assert_expr_for): Fix comments.
	(maybe_add_assert_expr): When a predicate involves more than
	one name, only add assertions for the first one.
	(vrp_finalize): Support TDF_STATS.

testsuite/ChangeLog.tcb

	* gcc.dg/tree-ssa/20031022-1.c: Adjust dump file to scan.
	* gcc.dg/tree-ssa/ssa-pre-1.c: Adjust expected pattern.

Index: tree-into-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-into-ssa.c,v
retrieving revision 2.21.2.11
diff -d -u -p -r2.21.2.11 tree-into-ssa.c
--- tree-into-ssa.c	6 Feb 2005 14:11:20 -0000	2.21.2.11
+++ tree-into-ssa.c	14 Feb 2005 12:29:34 -0000
@@ -185,6 +185,15 @@ enum rewrite_mode {
    statements will be processed.  This is decided in mark_def_sites.  */
 #define REWRITE_THIS_STMT(T)	TREE_VISITED (T)
 
+/* Use TREE_ADDRESSABLE to keep track of which statements we want to
+   visit when marking new definition sites.  This is slightly
+   different than REWRITE_THIS_STMT: it's used by update_ssa to
+   distinguish statements that need to have both uses and defs
+   processed from those that only need to have their defs processed.
+   Statements that define new SSA names only need to have their defs
+   registered, but they don't need to have their uses renamed.  */
+#define REGISTER_DEFS_IN_THIS_STMT(T)	TREE_ADDRESSABLE (T)
+
 
 /* Get the information associated with NAME.  */
 
@@ -727,6 +736,7 @@ insert_phi_nodes_for (tree var, bitmap p
 
       /* Mark this PHI node as interesting for the rename process.  */
       REWRITE_THIS_STMT (phi) = 1;
+      REGISTER_DEFS_IN_THIS_STMT (phi) = 1;
     }
 }
 
@@ -1336,7 +1346,7 @@ rewrite_update_init_block (struct dom_wa
     {
       tree lhs;
 
-      if (!REWRITE_THIS_STMT (phi))
+      if (!REGISTER_DEFS_IN_THIS_STMT (phi))
 	continue;
       
       lhs = PHI_RESULT (phi);
@@ -1406,28 +1416,30 @@ rewrite_update_stmt (struct dom_walk_dat
     }
 
   /* Only update marked statements.  */
-  if (!REWRITE_THIS_STMT (stmt))
+  if (!REWRITE_THIS_STMT (stmt) && !REGISTER_DEFS_IN_THIS_STMT (stmt))
     return;
 
   get_stmt_operands (stmt);
 
   /* Rewrite USES included in OLD_SSA_NAMES.  */
-  FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
-    {
-      tree use = USE_FROM_PTR (use_p);
-      if (pointer_set_contains (old_ssa_names, use))
-	SET_USE (use_p, get_reaching_def (use));
-    }
+  if (REWRITE_THIS_STMT (stmt))
+    FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
+      {
+	tree use = USE_FROM_PTR (use_p);
+	if (pointer_set_contains (old_ssa_names, use))
+	  SET_USE (use_p, get_reaching_def (use));
+      }
 
   /* Register definitions of names in NEW_SSA_NAMES and OLD_SSA_NAMES.  */
-  FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_ALL_DEFS)
-    {
-      tree def = DEF_FROM_PTR (def_p);
-      if (pointer_set_contains (new_ssa_names, def))
-	register_new_update (name_replaced_by (def, new_to_old), def);
-      else if (pointer_set_contains (old_ssa_names, def))
-	register_new_update (def, def);
-    }
+  if (REGISTER_DEFS_IN_THIS_STMT (stmt))
+    FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_ALL_DEFS)
+      {
+	tree def = DEF_FROM_PTR (def_p);
+	if (pointer_set_contains (new_ssa_names, def))
+	  register_new_update (name_replaced_by (def, new_to_old), def);
+	else if (pointer_set_contains (old_ssa_names, def))
+	  register_new_update (def, def);
+      }
 }
 
 
@@ -1767,6 +1779,7 @@ prepare_block_for_update (basic_block bb
       tree lhs = PHI_RESULT (phi);
 
       REWRITE_THIS_STMT (phi) = 0;
+      REGISTER_DEFS_IN_THIS_STMT (phi) = 0;
 
       /* If this PHI creates one of the names in OLD_SSA_NAMES, mark
 	 it as interesting to the renamer so that it can properly set
@@ -1774,7 +1787,7 @@ prepare_block_for_update (basic_block bb
       if (pointer_set_contains (old_ssa_names, lhs))
 	{
 	  set_def_block (lhs, bb, true, true);
-	  REWRITE_THIS_STMT (phi) = 1;
+	  REGISTER_DEFS_IN_THIS_STMT (phi) = 1;
 	}
 
       /* If any of the arguments uses one of the names in
@@ -1798,10 +1811,13 @@ prepare_block_for_update (basic_block bb
       ssa_op_iter i;
       use_operand_p use_p;
       def_operand_p def_p;
+      bool defines_new_name_p;
       
       stmt = bsi_stmt (si);
       get_stmt_operands (stmt);
       REWRITE_THIS_STMT (stmt) = 0;
+      REGISTER_DEFS_IN_THIS_STMT (stmt) = 0;
+      defines_new_name_p = false;
 
       FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, i, SSA_OP_DEF)
 	{
@@ -1811,15 +1827,16 @@ prepare_block_for_update (basic_block bb
 	    {
 	      /* If DEF is a new name, then this is a definition site
 		 for the name replaced by DEF.  */
-	      REWRITE_THIS_STMT (stmt) = 1;
+	      REGISTER_DEFS_IN_THIS_STMT (stmt) = 1;
 	      set_def_block (name_replaced_by (def, new_to_old), bb, false,
 			     true);
+	      defines_new_name_p = true;
 	    }
 	  else if (pointer_set_contains (old_ssa_names, def))
 	    {
 	      /* If DEF is an old name, this is a definition site for
 		 DEF.  */
-	      REWRITE_THIS_STMT (stmt) = 1;
+	      REGISTER_DEFS_IN_THIS_STMT (stmt) = 1;
 	      set_def_block (def, bb, false, true);
 	    }
 	}
@@ -1827,7 +1844,13 @@ prepare_block_for_update (basic_block bb
       FOR_EACH_SSA_USE_OPERAND (use_p, stmt, i, SSA_OP_USE)
 	{
 	  tree use = USE_FROM_PTR (use_p);
-	  if (pointer_set_contains (old_ssa_names, use))
+
+	  /* If STMT is a definition site for one of the new names, we
+	     do not want to rewrite it because we assume that our
+	     caller has inserted the statements exactly as it wanted
+	     them to be.  */
+	  if (!defines_new_name_p
+	      && pointer_set_contains (old_ssa_names, use))
 	    {
 	      REWRITE_THIS_STMT (stmt) = 1;
 	      if (bb_for_stmt (stmt) != bb)
Index: tree-ssa-copy.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-copy.c,v
retrieving revision 2.15.2.12
diff -d -u -p -r2.15.2.12 tree-ssa-copy.c
--- tree-ssa-copy.c	2 Feb 2005 02:44:00 -0000	2.15.2.12
+++ tree-ssa-copy.c	14 Feb 2005 12:29:34 -0000
@@ -404,15 +404,34 @@ static tree
 get_last_copy_of (tree var)
 {
   tree last;
+  int i;
 
   /* Traverse COPY_OF starting at VAR until we get to the last
-     link in the chain.  */
+     link in the chain.  Since it is possible to have cycles in PHI
+     nodes, the copy-of chain may also contain cycles.
+     
+     To avoid infinite loops and to avoid traversing lengthy copy-of
+     chains, we artificially limit the maximum number of chains we are
+     willing to traverse.
+
+     The value 5 was taken from a compiler and runtime library
+     bootstrap and a mixture of C and C++ code from various sources.
+     More than 82% of all copy-of chains were shorter than 5 links.  */
+#define LIMIT	5
+
   last = var;
-  while (copy_of[SSA_NAME_VERSION (last)].value
-         && copy_of[SSA_NAME_VERSION (last)].value != last)
-    last = copy_of[SSA_NAME_VERSION (last)].value;
+  for (i = 0; i < LIMIT; i++)
+    {
+      tree copy = copy_of[SSA_NAME_VERSION (last)].value;
+      if (copy == NULL_TREE || copy == last)
+	break;
+      last = copy;
+    }
 
-  return last;
+  /* If we have reached the limit, then we are either in a copy-of
+     cycle or the copy-of chain is too long.  In this case, just
+     return VAR so that it is not considered a copy of anything.  */
+  return (i < LIMIT ? last : var);
 }
 
 
@@ -504,21 +523,30 @@ static enum ssa_prop_result
 copy_prop_visit_assignment (tree stmt, tree *result_p)
 {
   tree lhs, rhs;
+  prop_value_t *rhs_val;
 
   lhs = TREE_OPERAND (stmt, 0);
   rhs = TREE_OPERAND (stmt, 1);
 
   gcc_assert (TREE_CODE (rhs) == SSA_NAME);
 
+  rhs_val = get_copy_of_val (rhs);
+
   if (TREE_CODE (lhs) == SSA_NAME)
     {
-      /* Straight copy between to SSA names.  First, make sure that we
-	 can propagate the RHS into uses of LHS.  */
+      /* Straight copy between two SSA names.  First, make sure that
+	 we can propagate the RHS into uses of LHS.  */
       if (!may_propagate_copy (lhs, rhs))
 	return SSA_PROP_VARYING;
 
+      /* Notice that in the case of assignments, we make the LHS be a
+	 copy of RHS's value, not of RHS itself.  This avoids keeping
+	 unnecessary copy-of chains (assignments cannot be in a cycle
+	 like PHI nodes), speeding up the propagation process.
+	 This is different from what we do in copy_prop_visit_phi_node. 
+	 In those cases, we are interested in the copy-of chains.  */
       *result_p = lhs;
-      if (set_copy_of_val (*result_p, rhs, NULL_TREE))
+      if (set_copy_of_val (*result_p, rhs_val->value, rhs_val->mem_ref))
 	return SSA_PROP_INTERESTING;
       else
 	return SSA_PROP_NOT_INTERESTING;
@@ -531,12 +559,13 @@ copy_prop_visit_assignment (tree stmt, t
       tree vdef;
       bool changed;
 
+      /* This should only be executed when doing store copy-prop.  */
       gcc_assert (do_store_copy_prop);
 
-      /* Set the value of every VDEF to VAL.  */
+      /* Set the value of every VDEF to RHS_VAL.  */
       changed = false;
       FOR_EACH_SSA_TREE_OPERAND (vdef, stmt, i, SSA_OP_VIRTUAL_DEFS)
-	changed |= set_copy_of_val (vdef, rhs, lhs);
+	changed |= set_copy_of_val (vdef, rhs_val->value, lhs);
       
       /* Note that for propagation purposes, we are only interested in
 	 visiting statements that load the exact same memory reference
@@ -711,11 +740,9 @@ copy_prop_visit_phi_node (tree phi)
       /* Constants in the argument list never generate a useful copy.
 	 Similarly, names that flow through abnormal edges cannot be
 	 used to derive copies.  */
-      if (TREE_CODE (arg) != SSA_NAME
-	  || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (arg))
+      if (TREE_CODE (arg) != SSA_NAME || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (arg))
 	{
 	  phi_val.value = lhs;
-	  phi_val.mem_ref = NULL_TREE;
 	  break;
 	}
 
@@ -734,10 +761,13 @@ copy_prop_visit_phi_node (tree phi)
       arg_val = get_copy_of_val (arg);
 
       /* If the LHS didn't have a value yet, make it a copy of the
-	 first argument we find.  */
+	 first argument we find.  Notice that while we make the LHS be
+	 a copy of the argument itself, we take the memory reference
+	 from the argument's value so that we can compare it to the
+	 memory reference of all the other arguments.  */
       if (phi_val.value == NULL_TREE)
 	{
-	  phi_val.value = arg_val->value;
+	  phi_val.value = arg;
 	  phi_val.mem_ref = arg_val->mem_ref;
 	  continue;
 	}
@@ -747,7 +777,7 @@ copy_prop_visit_phi_node (tree phi)
 	 copy propagating stores and these two arguments came from
 	 different memory references, they cannot be considered
 	 copies.  */
-      if (get_last_copy_of (phi_val.value) != get_last_copy_of (arg_val->value)
+      if (get_last_copy_of (phi_val.value) != get_last_copy_of (arg)
 	  || (do_store_copy_prop
 	      && phi_val.mem_ref
 	      && arg_val->mem_ref
@@ -935,25 +965,25 @@ fini_copy_prop (void)
    which variable that may be).
    
    Propagation would then proceed as follows (the notation a -> b
-   means that is a copy-of b):
+   means that a is a copy-of b):
 
    Visit #1: x_54 = PHI <x_53, x_52>
 		x_53 -> x_53
 		x_52 -> x_53
 		Result: x_54 -> x_53.  Value changed.  Add SSA edges.
 
-   Visit #2: x_53 = PHI <x_898, x_54>
+   Visit #1: x_53 = PHI <x_898, x_54>
    		x_898 -> x_898
 		x_54 -> x_53
 		Result: x_53 -> x_898.  Value changed.  Add SSA edges.
 
-   Visit #1: x_54 = PHI <x_53, x_52>
+   Visit #2: x_54 = PHI <x_53, x_52>
    		x_53 -> x_898
 		x_52 -> x_53 -> x_898
 		Result: x_54 -> x_898.  Value changed.  Add SSA edges.
 
    Visit #2: x_53 = PHI <x_898, x_54>
-   		x_53 -> x_898
+   		x_898 -> x_898
 		x_54 -> x_898
 		Result: x_53 -> x_898.  Value didn't change.  Stable state
 
Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-dom.c,v
retrieving revision 2.44.2.13
diff -d -u -p -r2.44.2.13 tree-ssa-dom.c
--- tree-ssa-dom.c	6 Feb 2005 14:14:56 -0000	2.44.2.13
+++ tree-ssa-dom.c	14 Feb 2005 12:29:34 -0000
@@ -419,7 +419,10 @@ tree_ssa_dominator_optimize (void)
   walk_data.dom_direction = CDI_DOMINATORS;
   walk_data.initialize_block_local_data = NULL;
   walk_data.before_dom_children_before_stmts = dom_opt_initialize_block;
-  walk_data.before_dom_children_walk_stmts = optimize_stmt;
+  if (getenv ("DISABLE_DOM"))
+    walk_data.before_dom_children_walk_stmts = NULL;
+  else
+    walk_data.before_dom_children_walk_stmts = optimize_stmt;
   walk_data.before_dom_children_after_stmts = propagate_to_outgoing_edges;
   walk_data.after_dom_children_before_stmts = NULL;
   walk_data.after_dom_children_walk_stmts = NULL;
@@ -455,6 +458,8 @@ tree_ssa_dominator_optimize (void)
 	 duplication and CFG manipulation.  */
       if (!bitmap_empty_p (vars_to_rename))
 	{
+	  if (getenv ("DISABLE_DOM"))
+	    gcc_unreachable ();
 	  rewrite_into_ssa (false);
 	  bitmap_clear (vars_to_rename);
 	}
@@ -468,6 +473,8 @@ tree_ssa_dominator_optimize (void)
 	 such edges from the CFG as needed.  */
       if (!bitmap_empty_p (need_eh_cleanup))
 	{
+	  if (getenv ("DISABLE_DOM"))
+	    gcc_unreachable ();
 	  cfg_altered |= tree_purge_all_dead_eh_edges (need_eh_cleanup);
 	  bitmap_zero (need_eh_cleanup);
 	}
@@ -478,6 +485,9 @@ tree_ssa_dominator_optimize (void)
 
       rewrite_ssa_into_ssa ();
 
+      if (getenv ("DISABLE_DOM"))
+	continue;
+
       /* Reinitialize the various tables.  */
       bitmap_clear (nonzero_vars);
       htab_empty (avail_exprs);
@@ -2156,9 +2166,9 @@ simplify_cond_and_lookup_avail_expr (tre
 		     Similarly the high value for the merged range is the
 		     minimum of the previous high value and the high value of
 		     this record.  */
-		  low = (tree_int_cst_compare (low, tmp_low) == 1
+		  low = (low && tree_int_cst_compare (low, tmp_low) == 1
 			 ? low : tmp_low);
-		  high = (tree_int_cst_compare (high, tmp_high) == -1
+		  high = (high && tree_int_cst_compare (high, tmp_high) == -1
 			  ? high : tmp_high);
 		}
 
@@ -2557,6 +2567,8 @@ propagate_to_outgoing_edges (struct dom_
 {
   
   record_edge_info (bb);
+  if (getenv ("DISABLE_DOM"))
+    return;
   cprop_into_successor_phis (bb, nonzero_vars);
 }
 
Index: tree-ssa-pre.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-pre.c,v
retrieving revision 2.36.2.11
diff -d -u -p -r2.36.2.11 tree-ssa-pre.c
--- tree-ssa-pre.c	2 Feb 2005 02:44:05 -0000	2.36.2.11
+++ tree-ssa-pre.c	14 Feb 2005 12:29:34 -0000
@@ -871,6 +871,7 @@ phi_translate (tree expr, value_set_t se
       return NULL;
 
     case tcc_binary:
+    case tcc_comparison:
       {
 	tree oldop1 = TREE_OPERAND (expr, 0);
 	tree oldop2 = TREE_OPERAND (expr, 1);
@@ -1057,6 +1058,7 @@ valid_in_set (value_set_t set, tree expr
   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
     {
     case tcc_binary:
+    case tcc_comparison:
       {
 	tree op1 = TREE_OPERAND (expr, 0);
 	tree op2 = TREE_OPERAND (expr, 1);
@@ -1309,6 +1311,7 @@ find_or_generate_expression (basic_block
       genop = VALUE_HANDLE_EXPR_SET (expr)->head->expr;
       gcc_assert (UNARY_CLASS_P (genop)
 		  || BINARY_CLASS_P (genop)
+		  || COMPARISON_CLASS_P (genop)
 		  || REFERENCE_CLASS_P (genop));
       genop = create_expression_by_pieces (block, genop, stmts);
     }
@@ -1340,6 +1343,7 @@ create_expression_by_pieces (basic_block
   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
     {
     case tcc_binary:
+    case tcc_comparison:
       {
 	tree_stmt_iterator tsi;
 	tree genop1, genop2;
@@ -1474,6 +1478,7 @@ insert_into_preds_of_block (basic_block 
       bprime = pred->src;
       eprime = avail[bprime->index];
       if (BINARY_CLASS_P (eprime)
+	  || COMPARISON_CLASS_P (eprime)
 	  || UNARY_CLASS_P (eprime))
 	{
 	  builtexpr = create_expression_by_pieces (bprime,
@@ -1587,6 +1592,7 @@ insert_aux (basic_block block)
 		   node = node->next)
 		{
 		  if (BINARY_CLASS_P (node->expr)
+		      || COMPARISON_CLASS_P (node->expr)
 		      || UNARY_CLASS_P (node->expr))
 		    {
 		      tree *avail;
@@ -1790,6 +1796,7 @@ create_value_expr_from (tree expr, basic
 
   gcc_assert (TREE_CODE_CLASS (code) == tcc_unary
 	      || TREE_CODE_CLASS (code) == tcc_binary
+	      || TREE_CODE_CLASS (code) == tcc_comparison
 	      || TREE_CODE_CLASS (code) == tcc_reference);
 
   if (TREE_CODE_CLASS (code) == tcc_unary)
@@ -1928,24 +1935,10 @@ compute_avail (void)
 	      vuse_optype vuses = STMT_VUSE_OPS (stmt);
 
 	      STRIP_USELESS_TYPE_CONVERSION (rhs);
-	      if (TREE_CODE (rhs) == SSA_NAME
-		  || is_gimple_min_invariant (rhs)
-		  || DECL_P (rhs))
-		{
-		  /* Compute a value number for the RHS of the statement
-		     and add its value to the AVAIL_OUT set for the block.
-		     Add the LHS to TMP_GEN.  */
-		  add_to_sets (lhs, rhs, vuses, TMP_GEN (block), 
-			       AVAIL_OUT (block));
-		  
-		  if (TREE_CODE (rhs) == SSA_NAME
-		      && !is_undefined_value (rhs))
-		    value_insert_into_set (EXP_GEN (block), rhs);
-		  continue;
-		}	   
-	      else if (UNARY_CLASS_P (rhs)
-		       || BINARY_CLASS_P (rhs)
-		       || TREE_CODE_CLASS (TREE_CODE (rhs)) == tcc_reference)
+	      if (UNARY_CLASS_P (rhs)
+		  || BINARY_CLASS_P (rhs)
+		  || COMPARISON_CLASS_P (rhs)
+		  || REFERENCE_CLASS_P (rhs))
 		{
 		  /* For binary, unary, and reference expressions,
 		     create a duplicate expression with the operands
@@ -1960,6 +1953,23 @@ compute_avail (void)
 		      continue;
 		    }
 		}
+	      else if (TREE_CODE (rhs) == SSA_NAME
+		       || is_gimple_min_invariant (rhs)
+		       || TREE_INVARIANT (rhs)
+		       || TREE_CODE (rhs) == ADDR_EXPR
+		       || DECL_P (rhs))
+		{
+		  /* Compute a value number for the RHS of the statement
+		     and add its value to the AVAIL_OUT set for the block.
+		     Add the LHS to TMP_GEN.  */
+		  add_to_sets (lhs, rhs, vuses, TMP_GEN (block), 
+			       AVAIL_OUT (block));
+		  
+		  if (TREE_CODE (rhs) == SSA_NAME
+		      && !is_undefined_value (rhs))
+		    value_insert_into_set (EXP_GEN (block), rhs);
+		  continue;
+		}	   
 	    }
 
 	  /* For any other statement that we don't recognize, simply
@@ -2320,10 +2330,10 @@ execute_pre (bool do_fre)
 
   if (dump_file && (dump_flags & TDF_STATS))
     {
-      fprintf (dump_file, "Insertions:%d\n", pre_stats.insertions);
-      fprintf (dump_file, "New PHIs:%d\n", pre_stats.phis);
-      fprintf (dump_file, "Eliminated:%d\n", pre_stats.eliminations);
-      fprintf (dump_file, "Constified:%d\n", pre_stats.constified);
+      fprintf (dump_file, "Insertions: %d\n", pre_stats.insertions);
+      fprintf (dump_file, "New PHIs: %d\n", pre_stats.phis);
+      fprintf (dump_file, "Eliminated: %d\n", pre_stats.eliminations);
+      fprintf (dump_file, "Constified: %d\n", pre_stats.constified);
     }
   
   bsi_commit_edge_inserts ();
Index: tree-vn.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-vn.c,v
retrieving revision 2.5.2.1
diff -d -u -p -r2.5.2.1 tree-vn.c
--- tree-vn.c	30 Sep 2004 18:42:40 -0000	2.5.2.1
+++ tree-vn.c	14 Feb 2005 12:29:34 -0000
@@ -176,7 +176,7 @@ set_value_handle (tree e, tree v)
     get_tree_ann (e)->common.value_handle = v;
   else
     /* Do nothing.  Constants are their own value handles.  */
-    gcc_assert (is_gimple_min_invariant (e));
+    gcc_assert (TREE_INVARIANT (e) || is_gimple_min_invariant (e));
 }
 
 
@@ -281,7 +281,7 @@ get_value_handle (tree expr)
     }
   else
     {
-      gcc_assert (is_gimple_min_invariant (expr));
+      gcc_assert (TREE_INVARIANT (expr) || is_gimple_min_invariant (expr));
       return expr;
     }
 }
Index: tree-vrp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-vrp.c,v
retrieving revision 1.1.2.3
diff -d -u -p -r1.1.2.3 tree-vrp.c
--- tree-vrp.c	6 Feb 2005 14:14:56 -0000	1.1.2.3
+++ tree-vrp.c	14 Feb 2005 12:29:34 -0000
@@ -186,8 +186,10 @@ expr_computes_nonnull (tree expr)
      guarantees that the value is non-NULL.  */
   return (alloca_call_p (expr)
           || (TREE_CODE (expr) == ADDR_EXPR
-               && DECL_P (TREE_OPERAND (expr, 0))
-	       && !DECL_WEAK (TREE_OPERAND (expr, 0))));
+              && DECL_P (TREE_OPERAND (expr, 0))
+	      && !DECL_WEAK (TREE_OPERAND (expr, 0)))
+	  || (TREE_CODE (expr) == ADDR_EXPR
+	      && REFERENCE_CLASS_P (TREE_OPERAND (expr, 0))));
 }
 
 
@@ -287,7 +289,7 @@ compare_values (tree val1, tree val2)
 static void
 extract_range_from_assert (value_range *vr_p, tree expr)
 {
-  tree var, cond, limit, one, type;
+  tree var, cond, limit, type;
 
   var = ASSERT_EXPR_VAR (expr);
   cond = ASSERT_EXPR_COND (expr);
@@ -297,7 +299,6 @@ extract_range_from_assert (value_range *
   /* Find VAR in the ASSERT_EXPR conditional.  */
   limit = get_opposite_operand (cond, var);
   type = TREE_TYPE (limit);
-  one = build_int_cst (type, 1);
 
   gcc_assert (limit != var);
 
@@ -316,14 +317,20 @@ extract_range_from_assert (value_range *
   else if (TREE_CODE (cond) == LE_EXPR)
     set_value_range (vr_p, VR_RANGE, TYPE_MIN_VALUE (type), limit);
   else if (TREE_CODE (cond) == LT_EXPR)
-    set_value_range (vr_p, VR_RANGE, TYPE_MIN_VALUE (type),
-		     fold (build (MINUS_EXPR, type, limit, one)));
+    {
+      tree one = build_int_cst (type, 1);
+      set_value_range (vr_p, VR_RANGE, TYPE_MIN_VALUE (type),
+		       fold (build (MINUS_EXPR, type, limit, one)));
+    }
   else if (TREE_CODE (cond) == GE_EXPR)
     set_value_range (vr_p, VR_RANGE, limit, TYPE_MAX_VALUE (type));
   else if (TREE_CODE (cond) == GT_EXPR)
-    set_value_range (vr_p, VR_RANGE,
-		     fold (build (PLUS_EXPR, type, limit, one)),
-		     TYPE_MAX_VALUE (type));
+    {
+      tree one = build_int_cst (type, 1);
+      set_value_range (vr_p, VR_RANGE,
+		       fold (build (PLUS_EXPR, type, limit, one)),
+		       TYPE_MAX_VALUE (type));
+    }
   else
     gcc_unreachable ();
 }
@@ -414,9 +421,10 @@ extract_range_from_binary_expr (value_ra
       || POINTER_TYPE_P (TREE_TYPE (op1)))
     {
       /* For pointer types, we are really only interested in asserting
-	 whether the expression evaluates to non-NULL.  */
-      gcc_assert (code == PLUS_EXPR || code == MINUS_EXPR);
-
+	 whether the expression evaluates to non-NULL.  FIXME.  We
+	 used to gcc_assert (code == PLUS_EXPR || code == MINUS_EXPR),
+	 but ivopts is generating expressions with pointer
+	 multiplication in them.  */
       if (code == PLUS_EXPR)
 	{
 	  /* Assume that pointers can never wrap around.  FIXME, Is
@@ -558,6 +566,20 @@ extract_range_from_unary_expr (value_ran
     }
   else if (TREE_CODE (expr) == NOP_EXPR || TREE_CODE (expr) == CONVERT_EXPR)
     {
+      /* If VR0 is an anti-range and the type of EXPR is of a
+	 different size than the type of VR0's operands, then set the
+	 resulting range to VARYING.  Things like sign extensions and
+	 precision loss may change the range.  For instance, if x_3 is
+	 of type 'long long int' and 'y_5 = (unsigned short) x_3', if
+	 x_3 is ~[0, 0], it is impossible to know at compile time
+	 whether y_5 will be ~[0, 0].  */
+      if (vr0.type == VR_ANTI_RANGE
+	  && TYPE_SIZE (TREE_TYPE (vr0.min)) != TYPE_SIZE (TREE_TYPE (expr)))
+	{
+	  set_value_range (vr, VR_VARYING, NULL_TREE, NULL_TREE);
+	  return;
+	}
+
       /* If this is a cast operation and either limit in VR0 is set to
 	 VR0's type min/max values, set the corresponding limits in VR
 	 to EXPR's type min/max values.  */
@@ -1003,14 +1025,14 @@ build_assert_expr_for (tree cond, tree v
     }
   else if (TREE_CODE (cond) == TRUTH_NOT_EXPR)
     {
-      /* Given !V, build the assignment V = false.  */
+      /* Given !V, build the assignment N = false.  */
       tree op0 = TREE_OPERAND (cond, 0);
       gcc_assert (op0 == v);
       assertion = build (MODIFY_EXPR, TREE_TYPE (v), n, boolean_false_node);
     }
   else if (TREE_CODE (cond) == SSA_NAME)
     {
-      /* Given V, build the assignment V = true.  */
+      /* Given V, build the assignment N = true.  */
       gcc_assert (v == cond);
       assertion = build (MODIFY_EXPR, TREE_TYPE (v), n, boolean_true_node);
     }
@@ -1179,6 +1201,7 @@ maybe_add_assert_expr (basic_block bb)
   block_stmt_iterator si;
   tree last;
   bool added;
+  use_optype uses;
 
   /* Step 1.  Mark all the SSA names used in BB in bitmap FOUND.  */
   added = false;
@@ -1248,25 +1271,28 @@ maybe_add_assert_expr (basic_block bb)
 
   /* Step 3.  If BB's last statement is a conditional expression
      involving integer operands, recurse into each of the sub-graphs
-     rooted at BB to determine if we need to add ASSERT_EXPRs.  */
+     rooted at BB to determine if we need to add ASSERT_EXPRs.
+     Notice that we only care about the first operand of the
+     conditional.  Adding assertions for both operands may actually 
+     hinder VRP.  FIXME, add example.  */
   if (last
       && TREE_CODE (last) == COND_EXPR
-      && !fp_predicate (COND_EXPR_COND (last)))
+      && !fp_predicate (COND_EXPR_COND (last))
+      && NUM_USES (uses = STMT_USE_OPS (last)) > 0)
     {
       edge e;
       edge_iterator ei;
-      ssa_op_iter i;
       tree op, cond;
       
       cond = COND_EXPR_COND (last);
 
-      /* Remove the COND_EXPR operands from the FOUND bitmap.
+      /* Remove the COND_EXPR operand from the FOUND bitmap.
 	 Otherwise, when we finish traversing each of the sub-graphs,
 	 we won't know whether the variables were found in the
 	 sub-graphs or if they had been found in a block upstream from
 	 BB.  */
-      FOR_EACH_SSA_TREE_OPERAND (op, last, i, SSA_OP_USE)
-	RESET_BIT (found, SSA_NAME_VERSION (op));
+      op = USE_OP (uses, 0);
+      RESET_BIT (found, SSA_NAME_VERSION (op));
 
       /* Look for uses of the operands in each of the sub-graphs
 	 rooted at BB.  We need to check each of the outgoing edges
@@ -1283,32 +1309,28 @@ maybe_add_assert_expr (basic_block bb)
 	  /* Once we traversed the sub-graph, check if any block inside
 	     used either of the predicate's operands.  If so, add the
 	     appropriate ASSERT_EXPR.  */
-	  FOR_EACH_SSA_TREE_OPERAND (op, last, i, SSA_OP_USE)
+	  if (TEST_BIT (found, SSA_NAME_VERSION (op)))
 	    {
-	      if (TEST_BIT (found, SSA_NAME_VERSION (op)))
-		{
-		  /* We found a use of OP in the sub-graph rooted at
-		     E->DEST.  Add an ASSERT_EXPR according to whether
-		     E goes to THEN_CLAUSE or ELSE_CLAUSE.  */
-		  tree c, t;
+	      /* We found a use of OP in the sub-graph rooted at
+		 E->DEST.  Add an ASSERT_EXPR according to whether
+		 E goes to THEN_CLAUSE or ELSE_CLAUSE.  */
+	      tree c, t;
 
-		  if (e->flags & EDGE_TRUE_VALUE)
-		    c = unshare_expr (cond);
-		  else if (e->flags & EDGE_FALSE_VALUE)
-		    c = invert_truthvalue (cond);
-		  else
-		    gcc_unreachable ();
+	      if (e->flags & EDGE_TRUE_VALUE)
+		c = unshare_expr (cond);
+	      else if (e->flags & EDGE_FALSE_VALUE)
+		c = invert_truthvalue (cond);
+	      else
+		gcc_unreachable ();
 
-		  t = build_assert_expr_for (c, op);
-		  bsi_insert_on_edge (e, t);
-		  added = true;
-		}
+	      t = build_assert_expr_for (c, op);
+	      bsi_insert_on_edge (e, t);
+	      added = true;
 	    }
 	}
 
       /* Finally, mark all the COND_EXPR operands as found.  */
-      FOR_EACH_SSA_TREE_OPERAND (op, last, i, SSA_OP_USE)
-	SET_BIT (found, SSA_NAME_VERSION (op));
+      SET_BIT (found, SSA_NAME_VERSION (op));
     }
   else
     {
@@ -1940,6 +1962,7 @@ static void
 vrp_finalize (void)
 {
   basic_block bb;
+  int num_pred_folded = 0;
 
   if (dump_file)
     {
@@ -1965,10 +1988,15 @@ vrp_finalize (void)
 		  fprintf (dump_file, "\n");
 		}
 
+	      num_pred_folded++;
 	      COND_EXPR_COND (last) = val;
 	    }
 	}
     }
+
+  if (dump_file && (dump_flags & TDF_STATS))
+    fprintf (dump_file, "\nNumber of predicates folded: %d\n\n",
+	     num_pred_folded);
 }
 
 
Index: testsuite/gcc.dg/tree-ssa/20031022-1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/tree-ssa/20031022-1.c,v
retrieving revision 1.4
diff -d -u -p -r1.4 20031022-1.c
--- testsuite/gcc.dg/tree-ssa/20031022-1.c	28 Jul 2004 12:15:20 -0000	1.4
+++ testsuite/gcc.dg/tree-ssa/20031022-1.c	14 Feb 2005 12:29:52 -0000
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-dom1" } */
+/* { dg-options "-O1 -fdump-tree-dce1" } */
  
 typedef struct edge_def
 {
@@ -24,4 +24,4 @@ blah (int arf)
 }
 
 /* There should be one load from entry_exit_blocks[1].pred.  */
-/* { dg-final { scan-tree-dump-times "entry_exit_blocks.1..pred" 1 "dom1"} } */
+/* { dg-final { scan-tree-dump-times "entry_exit_blocks.1..pred" 1 "dce1"} } */
Index: testsuite/gcc.dg/tree-ssa/ssa-pre-1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-1.c,v
retrieving revision 1.4
diff -d -u -p -r1.4 ssa-pre-1.c
--- testsuite/gcc.dg/tree-ssa/ssa-pre-1.c	3 Aug 2004 08:22:25 -0000	1.4
+++ testsuite/gcc.dg/tree-ssa/ssa-pre-1.c	14 Feb 2005 12:29:52 -0000
@@ -17,4 +17,4 @@ int main(int argc, char **argv)
 }
 /* We should eliminate one evaluation of b + c along the main path, 
    causing one reload. */
-/* { dg-final { scan-tree-dump-times "Eliminated:1" 1 "pre"} } */
+/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */

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