Patchwork Fix call stmt verification, fix invalid gimple from nested function lowering and profiling

login
register
mail settings
Submitter Richard Guenther
Date July 7, 2010, 12:04 p.m.
Message ID <alpine.LNX.2.00.1007071402380.1429@zhemvz.fhfr.qr>
Download mbox | patch
Permalink /patch/58105/
State New
Headers show

Comments

Richard Guenther - July 7, 2010, 12:04 p.m.
It turns out we produce a lot of invalid gimple calls from nested
function lowering and profiling (which in turn will cause missed CSE
and possibly wrong code).  I figured this out when fixing call stmt
verification.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2010-07-07  Richard Guenther  <rguenther@suse.de>

	* tree-ssa-propagate.h (valid_gimple_call_p): Remove.
	* tree-ssa-propagate.c (valid_gimple_call_p): Make static.  Fix.
	* gimple.h (is_gimple_operand): Remove.
	* gimple.c (is_gimple_operand): Likewise.
	(walk_gimple_op): Fix wi->val_only setting for calls.
	* tree-cfg.c (verify_gimple_call): Fix argument validation.
	* tree-profile.c (tree_gen_ic_func_profiler): Do not create
	invalid gimple calls.

Patch

Index: gcc/tree-ssa-propagate.h
===================================================================
--- gcc/tree-ssa-propagate.h	(revision 161870)
+++ gcc/tree-ssa-propagate.h	(working copy)
@@ -116,7 +116,6 @@  typedef bool (*ssa_prop_fold_stmt_fn) (g
 /* In tree-ssa-propagate.c  */
 void ssa_propagate (ssa_prop_visit_stmt_fn, ssa_prop_visit_phi_fn);
 bool valid_gimple_rhs_p (tree);
-bool valid_gimple_call_p (tree);
 void move_ssa_defining_stmt_for_defs (gimple, gimple);
 bool update_call_from_tree (gimple_stmt_iterator *, tree);
 bool stmt_makes_single_store (gimple);
Index: gcc/tree-ssa-propagate.c
===================================================================
--- gcc/tree-ssa-propagate.c	(revision 161870)
+++ gcc/tree-ssa-propagate.c	(working copy)
@@ -639,7 +639,7 @@  valid_gimple_rhs_p (tree expr)
    as a single GIMPLE_CALL statement.  If the arguments require
    further gimplification, return false.  */
 
-bool
+static bool
 valid_gimple_call_p (tree expr)
 {
   unsigned i, nargs;
@@ -649,8 +649,17 @@  valid_gimple_call_p (tree expr)
 
   nargs = call_expr_nargs (expr);
   for (i = 0; i < nargs; i++)
-    if (! is_gimple_operand (CALL_EXPR_ARG (expr, i)))
-      return false;
+    {
+      tree arg = CALL_EXPR_ARG (expr, i);
+      if (is_gimple_reg_type (arg))
+	{
+	  if (!is_gimple_val (arg))
+	    return false;
+	}
+      else
+	if (!is_gimple_lvalue (arg))
+	  return false;
+    }
 
   return true;
 }
Index: gcc/gimple.h
===================================================================
--- gcc/gimple.h	(revision 161870)
+++ gcc/gimple.h	(working copy)
@@ -879,7 +879,6 @@  tree gimple_get_lhs (const_gimple);
 void gimple_set_lhs (gimple, tree);
 void gimple_replace_lhs (gimple, tree);
 gimple gimple_copy (gimple);
-bool is_gimple_operand (const_tree);
 void gimple_set_modified (gimple, bool);
 void gimple_cond_get_ops_from_tree (tree, enum tree_code *, tree *, tree *);
 gimple gimple_build_cond_from_tree (tree, tree, tree);
Index: gcc/gimple.c
===================================================================
--- gcc/gimple.c	(revision 161870)
+++ gcc/gimple.c	(working copy)
@@ -1383,7 +1383,10 @@  walk_gimple_op (gimple stmt, walk_tree_f
 
     case GIMPLE_CALL:
       if (wi)
-	wi->is_lhs = false;
+	{
+	  wi->is_lhs = false;
+	  wi->val_only = true;
+	}
 
       ret = walk_tree (gimple_call_chain_ptr (stmt), callback_op, wi, pset);
       if (ret)
@@ -1395,21 +1398,32 @@  walk_gimple_op (gimple stmt, walk_tree_f
 
       for (i = 0; i < gimple_call_num_args (stmt); i++)
 	{
+	  if (wi)
+	    wi->val_only = is_gimple_reg_type (gimple_call_arg (stmt, i));
 	  ret = walk_tree (gimple_call_arg_ptr (stmt, i), callback_op, wi,
 			   pset);
 	  if (ret)
 	    return ret;
 	}
 
-      if (wi)
-	wi->is_lhs = true;
+      if (gimple_call_lhs (stmt))
+	{
+	  if (wi)
+	    {
+	      wi->is_lhs = true;
+	      wi->val_only = is_gimple_reg_type (gimple_call_lhs (stmt));
+	    }
 
-      ret = walk_tree (gimple_call_lhs_ptr (stmt), callback_op, wi, pset);
-      if (ret)
-	return ret;
+	  ret = walk_tree (gimple_call_lhs_ptr (stmt), callback_op, wi, pset);
+	  if (ret)
+	    return ret;
+	}
 
       if (wi)
-	wi->is_lhs = false;
+	{
+	  wi->is_lhs = false;
+	  wi->val_only = true;
+	}
       break;
 
     case GIMPLE_CATCH:
@@ -2538,15 +2552,6 @@  const unsigned char gimple_rhs_class_tab
 
 /* Validation of GIMPLE expressions.  */
 
-/* Return true if OP is an acceptable tree node to be used as a GIMPLE
-   operand.  */
-
-bool
-is_gimple_operand (const_tree op)
-{
-  return op && get_gimple_rhs_class (TREE_CODE (op)) == GIMPLE_SINGLE_RHS;
-}
-
 /* Returns true iff T is a valid RHS for an assignment to a renamed
    user -- or front-end generated artificial -- variable.  */
 
Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c	(revision 161870)
+++ gcc/tree-cfg.c	(working copy)
@@ -3114,7 +3114,10 @@  verify_gimple_call (gimple stmt)
   for (i = 0; i < gimple_call_num_args (stmt); ++i)
     {
       tree arg = gimple_call_arg (stmt, i);
-      if (!is_gimple_operand (arg))
+      if ((is_gimple_reg_type (TREE_TYPE (arg))
+	   && !is_gimple_val (arg))
+	  || (!is_gimple_reg_type (TREE_TYPE (arg))
+	      && !is_gimple_lvalue (arg)))
 	{
 	  error ("invalid argument to gimple call");
 	  debug_generic_expr (arg);
Index: gcc/tree-profile.c
===================================================================
--- gcc/tree-profile.c	(revision 161870)
+++ gcc/tree-profile.c	(working copy)
@@ -340,7 +340,7 @@  tree_gen_ic_func_profiler (void)
   basic_block bb;
   edge_iterator ei;
   gimple stmt1, stmt2;
-  tree tree_uid, cur_func;
+  tree tree_uid, cur_func, counter_ptr, ptr_var;
 
   if (cgraph_only_called_directly_p (c_node))
     return;
@@ -358,13 +358,16 @@  tree_gen_ic_func_profiler (void)
 					   build_addr (current_function_decl,
 						       current_function_decl),
 					   true, NULL_TREE,
-					   true, GSI_SAME_STMT);
+					   true, GSI_NEW_STMT);
+      counter_ptr = force_gimple_operand_gsi (&gsi, ic_gcov_type_ptr_var,
+					      true, NULL_TREE, false,
+					      GSI_NEW_STMT);
+      ptr_var = force_gimple_operand_gsi (&gsi, ic_void_ptr_var,
+					  true, NULL_TREE, false,
+					  GSI_NEW_STMT);
       tree_uid = build_int_cst (gcov_type_node, c_node->pid);
       stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4,
-				 ic_gcov_type_ptr_var,
-				 tree_uid,
-				 cur_func,
-				 ic_void_ptr_var);
+				 counter_ptr, tree_uid, cur_func, ptr_var);
       gsi_insert_after (&gsi, stmt1, GSI_NEW_STMT);
       gcc_assert (EDGE_COUNT (bb->succs) == 1);
       bb = split_edge (EDGE_I (bb->succs, 0));