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]

[tuples] Fix up regimplification


Hi!

This patch fixes
FAIL: gcc.dg/gomp/complex-1.c (internal compiler error)
FAIL: gcc.dg/gomp/complex-1.c (test for excess errors)
WARNING: program timed out.
FAIL: libgomp.c/collapse-1.c execution test
FAIL: libgomp.c/critical-2.c execution test
FAIL: libgomp.c/private-1.c execution test
FAIL: libgomp.c/task-1.c execution test
FAIL: libgomp.c++/task-1.C  -O  execution test
FAIL: libgomp.c++/task-6.C  -O  execution test

I've moved the omp-low.c regimplification code into the generic
gimple_regimplify_operands routine and am now handling there even changed
LHS requiring simpler RHS.

Bootstrapped/regtested on x86_64-linux.  Does this look ok?
I admit the repeating of a few is_gimple_reg_or_call_rhs
and is_gimple_mem_or_call_rhs is ugly, but they aren't really
identical (and can't be, because e.g. for calls we don't have
a CALL_EXPR we could throw at it).

2008-07-17  Jakub Jelinek  <jakub@redhat.com>

	* gimple.c (gimple_regimplify_operands): Moved to...
	* gimplify.c (gimple_regimplify_operands): ... here.  Rework using
	lower_omp_1 regimplification code, if regimplified LHS of
	GIMPLE_ASSIGN or GIMPLE_CALL requires simpler RHS, create a temporary.
	* omp-low.c (gimple_regimplify_operands): Use
	gimple_regimplify_operands.

--- gcc/gimple.c.jj	2008-07-17 13:10:27.000000000 +0200
+++ gcc/gimple.c	2008-07-17 14:25:34.000000000 +0200
@@ -2456,38 +2456,6 @@ gimple_assign_rhs_could_trap_p (gimple s
 }
 
 
-/* Some transformations like inlining may invalidate the GIMPLE form
-   for operands.  This function traverses all the operands in STMT and
-   gimplifies anything that is not a valid gimple operand.  Any new
-   GIMPLE statements are inserted before *GSI_P.  */
-
-void
-gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
-{
-  unsigned i, num_ops = gimple_num_ops (stmt);
-
-  for (i = 0; i < num_ops; i++)
-    {
-      /* NOTE: We start gimplifying operands from last to first to
-	 make sure that side-effects on the RHS of calls, assignments
-	 and ASMs are executed before the LHS.  The ordering is not
-	 important for other statements.  */
-      tree op = gimple_op (stmt, num_ops - i - 1);
-
-      /* We probably don't want to touch inline asm operands.  */
-      if (gimple_code (stmt) == GIMPLE_ASM)
-	continue;
-
-      if (op && !is_gimple_operand (op))
-	{
-	  op = force_gimple_operand_gsi (gsi_p, op, true, NULL, true,
-					 GSI_SAME_STMT);
-	  gimple_set_op (stmt, num_ops - i - 1, op);
-	}
-    }
-}
-
-
 /* Print debugging information for gimple stmts generated.  */
 
 void
--- gcc/gimplify.c.jj	2008-07-17 13:10:27.000000000 +0200
+++ gcc/gimplify.c	2008-07-17 14:26:01.000000000 +0200
@@ -7288,6 +7288,203 @@ gimplify_function_tree (tree fndecl)
 }
 
 
+/* Some transformations like inlining may invalidate the GIMPLE form
+   for operands.  This function traverses all the operands in STMT and
+   gimplifies anything that is not a valid gimple operand.  Any new
+   GIMPLE statements are inserted before *GSI_P.  */
+
+void
+gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
+{
+  size_t i, num_ops;
+  tree orig_lhs = NULL_TREE, lhs, t;
+  gimple_seq pre = NULL;
+  gimple post_stmt = NULL;
+  struct gimplify_ctx gctx;
+
+  push_gimplify_context (&gctx);
+  gimplify_ctxp->into_ssa = gimple_in_ssa_p (cfun);
+
+  switch (gimple_code (stmt))
+    {
+    case GIMPLE_COND:
+      gimplify_expr (gimple_cond_lhs_ptr (stmt), &pre, NULL,
+		     is_gimple_val, fb_rvalue);
+      gimplify_expr (gimple_cond_rhs_ptr (stmt), &pre, NULL,
+		     is_gimple_val, fb_rvalue);
+      break;
+    case GIMPLE_OMP_ATOMIC_LOAD:
+      gimplify_expr (gimple_omp_atomic_load_rhs_ptr (stmt), &pre, NULL,
+		     is_gimple_val, fb_rvalue);
+      break;
+    case GIMPLE_ASM:
+      {
+	size_t i, noutputs = gimple_asm_noutputs (stmt);
+	const char *constraint, **oconstraints;
+	bool allows_mem, allows_reg, is_inout;
+
+	oconstraints
+	  = (const char **) alloca ((noutputs) * sizeof (const char *));
+	for (i = 0; i < noutputs; i++)
+	  {
+	    tree op = gimple_asm_output_op (stmt, i);
+	    constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
+	    oconstraints[i] = constraint;
+	    parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
+				     &allows_reg, &is_inout);
+	    gimplify_expr (&TREE_VALUE (op), &pre, NULL,
+			   is_inout ? is_gimple_min_lval : is_gimple_lvalue,
+			   fb_lvalue | fb_mayfail);
+	  }
+	for (i = 0; i < gimple_asm_ninputs (stmt); i++)
+	  {
+	    tree op = gimple_asm_input_op (stmt, i);
+	    constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
+	    parse_input_constraint (&constraint, 0, 0, noutputs, 0,
+				    oconstraints, &allows_mem, &allows_reg);
+	    if (TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (op))) && allows_mem)
+	      allows_reg = 0;
+	    if (!allows_reg && allows_mem)
+	      gimplify_expr (&TREE_VALUE (op), &pre, NULL,
+			     is_gimple_lvalue, fb_lvalue | fb_mayfail);
+	    else
+	      gimplify_expr (&TREE_VALUE (op), &pre, NULL,
+			     is_gimple_asm_val, fb_rvalue);
+	  }
+      }
+      break;
+    default:
+      /* NOTE: We start gimplifying operands from last to first to
+	 make sure that side-effects on the RHS of calls, assignments
+	 and ASMs are executed before the LHS.  The ordering is not
+	 important for other statements.  */
+      num_ops = gimple_num_ops (stmt);
+      orig_lhs = gimple_get_lhs (stmt);
+      for (i = num_ops; i > 0; i--)
+	{
+	  tree op = gimple_op (stmt, i - 1);
+	  if (op == NULL_TREE)
+	    continue;
+	  if (i == 1 && (is_gimple_call (stmt) || is_gimple_assign (stmt)))
+	    gimplify_expr (&op, &pre, NULL, is_gimple_lvalue, fb_lvalue);
+	  else if (i == 2
+		   && is_gimple_assign (stmt)
+		   && num_ops == 2
+		   && get_gimple_rhs_class (gimple_expr_code (stmt))
+		      == GIMPLE_SINGLE_RHS)
+	    gimplify_expr (&op, &pre, NULL,
+			   rhs_predicate_for (gimple_assign_lhs (stmt)),
+			   fb_rvalue);
+	  else if (i == 2 && is_gimple_call (stmt))
+	    {
+	      if (TREE_CODE (op) == FUNCTION_DECL)
+		continue;
+	      gimplify_expr (&op, &pre, NULL, is_gimple_call_addr, fb_rvalue);
+	    }
+	  else
+	    gimplify_expr (&op, &pre, NULL, is_gimple_val, fb_rvalue);
+	  gimple_set_op (stmt, i - 1, op);
+	}
+
+      lhs = gimple_get_lhs (stmt);
+      /* If regimplification of the LHS changed it in a way that requires
+	 a simple RHS, create temporary.  */
+      if (orig_lhs != lhs && !is_gimple_formal_tmp_var (lhs))
+	{
+	  bool need_temp = false;
+
+	  if (is_gimple_assign (stmt)
+	      && num_ops == 2
+	      && get_gimple_rhs_class (gimple_expr_code (stmt))
+		 == GIMPLE_SINGLE_RHS)
+	    gimplify_expr (gimple_assign_rhs1_ptr (stmt), &pre, NULL,
+			   rhs_predicate_for (gimple_assign_lhs (stmt)),
+			   fb_rvalue);
+	  else if (is_gimple_reg (lhs))
+	    {
+	      if (is_gimple_reg_type (TREE_TYPE (lhs)))
+		{
+		  if (is_gimple_call (stmt))
+		    {
+		      i = gimple_call_flags (stmt);
+		      if ((i & ECF_LOOPING_CONST_OR_PURE)
+			  || !(i & (ECF_CONST | ECF_PURE)))
+			need_temp = true;
+		    }
+		  if (stmt_can_throw_internal (stmt))
+		    need_temp = true;
+		}
+	    }
+	  else
+	    {
+	      if (is_gimple_reg_type (TREE_TYPE (lhs)))
+		need_temp = true;
+	      else if (TYPE_MODE (TREE_TYPE (lhs)) != BLKmode)
+		{
+		  if (is_gimple_call (stmt))
+		    {
+		      tree fndecl = gimple_call_fndecl (stmt);
+
+		      if (!aggregate_value_p (TREE_TYPE (lhs), fndecl)
+			  && !(fndecl && DECL_RESULT (fndecl)
+			       && DECL_BY_REFERENCE (DECL_RESULT (fndecl))))
+			need_temp = true;
+		    }
+		  else
+		    need_temp = true;
+		}
+	    }
+	  if (need_temp)
+	    {
+	      tree temp = create_tmp_var (TREE_TYPE (lhs), NULL);
+
+	      DECL_GIMPLE_FORMAL_TEMP_P (temp) = 1;
+	      if (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE
+		  || TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE)
+		DECL_GIMPLE_REG_P (temp) = 1;
+	      if (TREE_CODE (orig_lhs) == SSA_NAME)
+		orig_lhs = SSA_NAME_VAR (orig_lhs);
+	      if (TREE_CODE (orig_lhs) == VAR_DECL
+		  && DECL_BASED_ON_RESTRICT_P (orig_lhs))
+		{
+		  DECL_BASED_ON_RESTRICT_P (temp) = 1;
+		  SET_DECL_RESTRICT_BASE (temp,
+					  DECL_GET_RESTRICT_BASE (orig_lhs));
+		}
+
+	      if (gimple_in_ssa_p (cfun))
+		temp = make_ssa_name (temp, NULL);
+	      gimple_set_lhs (stmt, temp);
+	      post_stmt = gimple_build_assign (lhs, temp);
+	      if (TREE_CODE (lhs) == SSA_NAME)
+		SSA_NAME_DEF_STMT (lhs) = post_stmt;
+	    }
+	}
+      break;
+    }
+
+  if (!gimple_seq_empty_p (pre))
+    {
+      if (gimple_in_ssa_p (cfun))
+	{
+	  gimple_stmt_iterator i;
+
+	  for (i = gsi_start (pre); !gsi_end_p (i); gsi_next (&i))
+	    mark_symbols_for_renaming (gsi_stmt (i));
+	}
+      gsi_insert_seq_before (gsi_p, pre, GSI_SAME_STMT);
+    }
+  if (post_stmt)
+    gsi_insert_after (gsi_p, post_stmt, GSI_NEW_STMT);
+
+  if (gimple_referenced_vars (cfun))
+    for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
+      add_referenced_var (t);
+
+  pop_gimplify_context (NULL);
+}
+
+
 /* Expands EXPR to list of gimple statements STMTS.  If SIMPLE is true,
    force the result to be either ssa_name or an invariant, otherwise
    just force it to be a rhs expression.  If VAR is not NULL, make the
--- gcc/omp-low.c.jj	2008-07-17 13:10:27.000000000 +0200
+++ gcc/omp-low.c	2008-07-17 13:37:37.000000000 +0200
@@ -6418,15 +6418,7 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p
 	      		 ctx ? NULL : &wi, NULL)
 	      || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
 			    ctx ? NULL : &wi, NULL)))
-	{
-	  gimple_seq pre = NULL;
-	  gimplify_expr (gimple_cond_lhs_ptr (stmt), &pre, NULL,
-			 is_gimple_val, fb_rvalue);
-	  gimplify_expr (gimple_cond_rhs_ptr (stmt), &pre, NULL,
-			 is_gimple_val, fb_rvalue);
-	  if (!gimple_seq_empty_p (pre))
-	    gsi_insert_seq_before (gsi_p, pre, GSI_SAME_STMT);
-	}
+	gimple_regimplify_operands (stmt, gsi_p);
       break;
     case GIMPLE_CATCH:
       lower_omp (gimple_catch_handler (stmt), ctx);
@@ -6477,110 +6469,16 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p
       lower_omp_critical (gsi_p, ctx);
       break;
     case GIMPLE_OMP_ATOMIC_LOAD:
-      {
-	tree addr = gimple_omp_atomic_load_rhs (stmt);
-	if ((ctx || task_shared_vars)
-	    && walk_tree (&addr, lower_omp_regimplify_p,
-			  ctx ? NULL : &wi, NULL))
-	  {
-	    gimple_seq pre = NULL;
-	    gimplify_expr (&addr, &pre, NULL, is_gimple_val, fb_rvalue);
-	    if (!gimple_seq_empty_p (pre))
-	      gsi_insert_seq_before (gsi_p, pre, GSI_SAME_STMT);
-	    gimple_omp_atomic_load_set_rhs (stmt, addr);
-	  }
-      }
-      break;
-    case GIMPLE_ASM:
       if ((ctx || task_shared_vars)
-	  && walk_gimple_op (stmt, lower_omp_regimplify_p,
-			     ctx ? NULL : &wi))
-	{
-	  gimple_seq pre = NULL;
-	  size_t i, noutputs = gimple_asm_noutputs (stmt);
-	  const char *constraint, **oconstraints;
-	  bool allows_mem, allows_reg, is_inout;
-
-	  oconstraints
-	    = (const char **) alloca ((noutputs) * sizeof (const char *));
-	  for (i = 0; i < noutputs; i++)
-	    {
-	      tree op = gimple_asm_output_op (stmt, i);
-	      constraint
-		= TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
-	      oconstraints[i] = constraint;
-	      parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
-				       &allows_reg, &is_inout);
-	      gimplify_expr (&TREE_VALUE (op), &pre, NULL,
-			     is_inout ? is_gimple_min_lval : is_gimple_lvalue,
-			     fb_lvalue | fb_mayfail);
-	    }
-	  for (i = 0; i < gimple_asm_ninputs (stmt); i++)
-	    {
-	      tree op = gimple_asm_input_op (stmt, i);
-	      constraint
-		= TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
-	      parse_input_constraint (&constraint, 0, 0, noutputs, 0,
-				      oconstraints, &allows_mem, &allows_reg);
-	      if (TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (op))) && allows_mem)
-		allows_reg = 0;
-	      if (!allows_reg && allows_mem)
-		gimplify_expr (&TREE_VALUE (op), &pre, NULL,
-			       is_gimple_lvalue, fb_lvalue | fb_mayfail);
-	      else
-		gimplify_expr (&TREE_VALUE (op), &pre, NULL,
-			       is_gimple_asm_val, fb_rvalue);
-	    }
-	  if (!gimple_seq_empty_p (pre))
-	    gsi_insert_seq_before (gsi_p, pre, GSI_SAME_STMT);
-	}
+	  && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
+			lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
+	gimple_regimplify_operands (stmt, gsi_p);
       break;
-
     default:
       if ((ctx || task_shared_vars)
 	  && walk_gimple_op (stmt, lower_omp_regimplify_p,
 			     ctx ? NULL : &wi))
-	{
-	  size_t i, num_ops;
-
-	  /* This is similar to gimple_regimplify_operands, but uses
-	     forcefully uses gimplify_expr with the right predicates
-	     on the operands.  is_gimple_val etc. don't look at
-	     DECL_HAS_VALUE_EXPR_P and all the operands already
-	     satisfy their predicates.  gimplify_expr will replace
-	     VAR_DECLs with DECL_HAS_VALUE_EXPR_P set with their
-	     replacements and regimplify.  */
-	  num_ops = gimple_num_ops (stmt);
-	  for (i = num_ops; i > 0; i--)
-	    {
-	      gimple_seq pre = NULL;
-	      tree op = gimple_op (stmt, i - 1);
-	      if (op == NULL_TREE)
-		continue;
-	      if (i == 1 && (is_gimple_call (stmt) || is_gimple_assign (stmt)))
-		gimplify_expr (&op, &pre, NULL, is_gimple_lvalue, fb_lvalue);
-	      else if (i == 2
-		       && is_gimple_assign (stmt)
-		       && num_ops == 2
-		       && get_gimple_rhs_class (gimple_expr_code (stmt))
-			  == GIMPLE_SINGLE_RHS)
-		gimplify_expr (&op, &pre, NULL,
-			       rhs_predicate_for (gimple_op (stmt, 0)),
-			       fb_rvalue);
-	      else if (i == 2 && is_gimple_call (stmt))
-		{
-		  if (TREE_CODE (op) == FUNCTION_DECL)
-		    continue;
-		  gimplify_expr (&op, &pre, NULL, is_gimple_call_addr,
-				 fb_rvalue);
-		}
-	      else
-		gimplify_expr (&op, &pre, NULL, is_gimple_val, fb_rvalue);
-	      if (!gimple_seq_empty_p (pre))
-		gsi_insert_seq_before (gsi_p, pre, GSI_SAME_STMT);
-	      gimple_set_op (stmt, i - 1, op);
-	    }
-	}
+	gimple_regimplify_operands (stmt, gsi_p);
       break;
     }
 }

	Jakub


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