[PATCH][match-and-simplify] Enable simplifying of GIMPLE_CONDs

Richard Biener rguenther@suse.de
Mon Sep 15 11:38:00 GMT 2014


To get desired transforms from tree-ssa-forwprop.c which uses
fold_stmt.

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

Richard.

2014-09-15  Richard Biener  <rguenther@suse.de>

	* gimple-fold.c: Include tree-eh.c.
	(fold_stmt_1): Handle GIMPLE_CONDs for gimple_simplify.
	* gimple-match-head.c (gimple_simplify): Likewise.
	* match-comparison.pd (bool != 0): Avoid some churn on
	GIMPLE and amend comment.

Index: gcc/gimple-fold.c
===================================================================
--- gcc/gimple-fold.c	(revision 215212)
+++ gcc/gimple-fold.c	(working copy)
@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3.
 #include "dbgcnt.h"
 #include "builtins.h"
 #include "output.h"
+#include "tree-eh.h"
 #include "gimple-match.h"
 
 
@@ -2881,15 +2882,67 @@ fold_stmt_1 (gimple_stmt_iterator *gsi,
      no further stmts need to be inserted (basically disallow
      creating of new SSA names).  */
   if (!inplace
-      || is_gimple_assign (stmt))
+      || is_gimple_assign (stmt)
+      || gimple_code (stmt) == GIMPLE_COND)
     {
       gimple_seq seq = NULL;
       code_helper rcode;
       tree ops[3] = {};
       if (gimple_simplify (stmt, &rcode, ops, inplace ? NULL : &seq, valueize))
 	{
-	  if (is_gimple_assign (stmt)
-	      && rcode.is_tree_code ())
+	  if (gimple_code (stmt) == GIMPLE_COND)
+	    {
+	      gcc_assert (rcode.is_tree_code ());
+	      if (TREE_CODE_CLASS ((enum tree_code)rcode) == tcc_comparison
+		  /* GIMPLE_CONDs condition may not throw.  */
+		  /* ???  Not sure how we want to deal with combining
+		     from possibly throwing statements.  Trivial
+		     simplifications may lead to DCEing an internal
+		     throw.  But we probably still want to simplify
+		     things to a constant for example?  Similar to
+		     abnormals we could discard the simplification
+		     result if we ever push a could-throw stmt to
+		     the sequence.  */
+		  && (!flag_exceptions
+		      || !cfun->can_throw_non_call_exceptions
+		      || !operation_could_trap_p (rcode, FLOAT_TYPE_P (TREE_TYPE (ops[0])), false, NULL_TREE)))
+		gimple_cond_set_condition (stmt, rcode, ops[0], ops[1]);
+	      else if (rcode == SSA_NAME)
+		gimple_cond_set_condition (stmt, NE_EXPR, ops[0],
+					   build_zero_cst (TREE_TYPE (ops[0])));
+	      else if (rcode == INTEGER_CST)
+		{
+		  if (integer_zerop (ops[0]))
+		    gimple_cond_make_false (stmt);
+		  else
+		    gimple_cond_make_true (stmt);
+		}
+	      else if (!inplace)
+		{
+		  tree res = maybe_push_res_to_seq (rcode, boolean_type_node,
+						    ops, &seq);
+		  if (!res)
+		    goto fail;
+		  gimple_cond_set_condition (stmt, NE_EXPR, res,
+					     build_zero_cst (TREE_TYPE (res)));
+		}
+	      else
+		goto fail;
+	      if (dump_file && (dump_flags & TDF_DETAILS))
+		{
+		  fprintf (dump_file, "gimple_simplified to ");
+		  if (!gimple_seq_empty_p (seq))
+		    print_gimple_seq (dump_file, seq, 0, TDF_SLIM);
+		  print_gimple_stmt (dump_file, gsi_stmt (*gsi),
+				     0, TDF_SLIM);
+		}
+	      gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT);
+	      changed = true;
+fail:
+	      ;
+	    }
+	  else if (is_gimple_assign (stmt)
+		   && rcode.is_tree_code ())
 	    {
 	      if ((!inplace
 		   || gimple_num_ops (stmt) <= get_gimple_rhs_num_ops (rcode))
Index: gcc/gimple-match-head.c
===================================================================
--- gcc/gimple-match-head.c	(revision 215212)
+++ gcc/gimple-match-head.c	(working copy)
@@ -573,213 +573,244 @@ gimple_simplify (gimple stmt,
 		 code_helper *rcode, tree *ops,
 		 gimple_seq *seq, tree (*valueize)(tree))
 {
-  if (is_gimple_assign (stmt))
+  switch (gimple_code (stmt))
     {
-      enum tree_code code = gimple_assign_rhs_code (stmt);
-      tree type = TREE_TYPE (gimple_assign_lhs (stmt));
-      switch (gimple_assign_rhs_class (stmt))
-	{
-	case GIMPLE_SINGLE_RHS:
-	  if (code == REALPART_EXPR
-	      || code == IMAGPART_EXPR
-	      || code == VIEW_CONVERT_EXPR)
+    case GIMPLE_ASSIGN:
+      {
+	enum tree_code code = gimple_assign_rhs_code (stmt);
+	tree type = TREE_TYPE (gimple_assign_lhs (stmt));
+	switch (gimple_assign_rhs_class (stmt))
+	  {
+	  case GIMPLE_SINGLE_RHS:
+	    if (code == REALPART_EXPR
+		|| code == IMAGPART_EXPR
+		|| code == VIEW_CONVERT_EXPR)
+	      {
+		tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
+		if (valueize && TREE_CODE (op0) == SSA_NAME)
+		  {
+		    op0 = valueize (op0);
+		    if (!op0)
+		      return false;
+		  }
+		*rcode = code;
+		ops[0] = op0;
+		return gimple_resimplify1 (seq, rcode, type, ops, valueize);
+	      }
+	    else if (code == BIT_FIELD_REF)
+	      {
+		tree rhs1 = gimple_assign_rhs1 (stmt);
+		tree op0 = TREE_OPERAND (rhs1, 0);
+		if (valueize && TREE_CODE (op0) == SSA_NAME)
+		  {
+		    op0 = valueize (op0);
+		    if (!op0)
+		      return false;
+		  }
+		*rcode = code;
+		ops[0] = op0;
+		ops[1] = TREE_OPERAND (rhs1, 1);
+		ops[2] = TREE_OPERAND (rhs1, 2);
+		return gimple_resimplify3 (seq, rcode, type, ops, valueize);
+	      }
+	    else if (code == SSA_NAME
+		     && valueize)
+	      {
+		tree op0 = gimple_assign_rhs1 (stmt);
+		tree valueized = valueize (op0);
+		if (!valueized || op0 == valueized)
+		  return false;
+		ops[0] = valueized;
+		*rcode = TREE_CODE (op0);
+		return true;
+	      }
+	    break;
+	  case GIMPLE_UNARY_RHS:
 	    {
-	      tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
-	      if (valueize && TREE_CODE (op0) == SSA_NAME)
+	      tree rhs1 = gimple_assign_rhs1 (stmt);
+	      if (valueize && TREE_CODE (rhs1) == SSA_NAME)
 		{
-		  op0 = valueize (op0);
-		  if (!op0)
+		  rhs1 = valueize (rhs1);
+		  if (!rhs1)
 		    return false;
 		}
 	      *rcode = code;
-	      ops[0] = op0;
+	      ops[0] = rhs1;
 	      return gimple_resimplify1 (seq, rcode, type, ops, valueize);
 	    }
-	  else if (code == BIT_FIELD_REF)
+	  case GIMPLE_BINARY_RHS:
 	    {
 	      tree rhs1 = gimple_assign_rhs1 (stmt);
-	      tree op0 = TREE_OPERAND (rhs1, 0);
-	      if (valueize && TREE_CODE (op0) == SSA_NAME)
+	      if (valueize && TREE_CODE (rhs1) == SSA_NAME)
 		{
-		  op0 = valueize (op0);
-		  if (!op0)
+		  rhs1 = valueize (rhs1);
+		  if (!rhs1)
+		    return false;
+		}
+	      tree rhs2 = gimple_assign_rhs2 (stmt);
+	      if (valueize && TREE_CODE (rhs2) == SSA_NAME)
+		{
+		  rhs2 = valueize (rhs2);
+		  if (!rhs2)
 		    return false;
 		}
 	      *rcode = code;
-	      ops[0] = op0;
-	      ops[1] = TREE_OPERAND (rhs1, 1);
-	      ops[2] = TREE_OPERAND (rhs1, 2);
-	      return gimple_resimplify3 (seq, rcode, type, ops, valueize);
+	      ops[0] = rhs1;
+	      ops[1] = rhs2;
+	      return gimple_resimplify2 (seq, rcode, type, ops, valueize);
 	    }
-	  else if (code == SSA_NAME
-		   && valueize)
+	  case GIMPLE_TERNARY_RHS:
 	    {
-	      tree op0 = gimple_assign_rhs1 (stmt);
-	      tree valueized = valueize (op0);
-	      if (!valueized || op0 == valueized)
-		return false;
-	      ops[0] = valueized;
-	      *rcode = TREE_CODE (op0);
-	      return true;
+	      tree rhs1 = gimple_assign_rhs1 (stmt);
+	      if (valueize && TREE_CODE (rhs1) == SSA_NAME)
+		{
+		  rhs1 = valueize (rhs1);
+		  if (!rhs1)
+		    return false;
+		}
+	      tree rhs2 = gimple_assign_rhs2 (stmt);
+	      if (valueize && TREE_CODE (rhs2) == SSA_NAME)
+		{
+		  rhs2 = valueize (rhs2);
+		  if (!rhs2)
+		    return false;
+		}
+	      tree rhs3 = gimple_assign_rhs3 (stmt);
+	      if (valueize && TREE_CODE (rhs3) == SSA_NAME)
+		{
+		  rhs3 = valueize (rhs3);
+		  if (!rhs3)
+		    return false;
+		}
+	      *rcode = code;
+	      ops[0] = rhs1;
+	      ops[1] = rhs2;
+	      ops[2] = rhs3;
+	      return gimple_resimplify3 (seq, rcode, type, ops, valueize);
 	    }
-	  break;
-	case GIMPLE_UNARY_RHS:
-	  {
-	    tree rhs1 = gimple_assign_rhs1 (stmt);
-	    if (valueize && TREE_CODE (rhs1) == SSA_NAME)
-	      {
-		rhs1 = valueize (rhs1);
-		if (!rhs1)
-		  return false;
-	      }
-	    *rcode = code;
-	    ops[0] = rhs1;
-	    return gimple_resimplify1 (seq, rcode, type, ops, valueize);
-	  }
-	case GIMPLE_BINARY_RHS:
-	  {
-	    tree rhs1 = gimple_assign_rhs1 (stmt);
-	    if (valueize && TREE_CODE (rhs1) == SSA_NAME)
-	      {
-		rhs1 = valueize (rhs1);
-		if (!rhs1)
-		  return false;
-	      }
-	    tree rhs2 = gimple_assign_rhs2 (stmt);
-	    if (valueize && TREE_CODE (rhs2) == SSA_NAME)
-	      {
-		rhs2 = valueize (rhs2);
-		if (!rhs2)
-		  return false;
-	      }
-	    *rcode = code;
-	    ops[0] = rhs1;
-	    ops[1] = rhs2;
-	    return gimple_resimplify2 (seq, rcode, type, ops, valueize);
-	  }
-	case GIMPLE_TERNARY_RHS:
-	  {
-	    tree rhs1 = gimple_assign_rhs1 (stmt);
-	    if (valueize && TREE_CODE (rhs1) == SSA_NAME)
-	      {
-		rhs1 = valueize (rhs1);
-		if (!rhs1)
-		  return false;
-	      }
-	    tree rhs2 = gimple_assign_rhs2 (stmt);
-	    if (valueize && TREE_CODE (rhs2) == SSA_NAME)
-	      {
-		rhs2 = valueize (rhs2);
-		if (!rhs2)
-		  return false;
-	      }
-	    tree rhs3 = gimple_assign_rhs3 (stmt);
-	    if (valueize && TREE_CODE (rhs3) == SSA_NAME)
-	      {
-		rhs3 = valueize (rhs3);
-		if (!rhs3)
-		  return false;
-	      }
-	    *rcode = code;
-	    ops[0] = rhs1;
-	    ops[1] = rhs2;
-	    ops[2] = rhs3;
-	    return gimple_resimplify3 (seq, rcode, type, ops, valueize);
+	  default:
+	    gcc_unreachable ();
 	  }
-	default:
-	  gcc_unreachable ();
-	}
-    }
-  else if (is_gimple_call (stmt)
-	   /* ???  This way we can't simplify calls with side-effects.  */
-	   && gimple_call_lhs (stmt) != NULL_TREE)
-    {
-      tree fn = gimple_call_fn (stmt);
-      /* ???  Internal function support missing.  */
-      if (!fn)
-	return false;
-      if (TREE_CODE (fn) == SSA_NAME
-	  && valueize)
-	fn = valueize (fn);
-      if (!fn
-	  || TREE_CODE (fn) != ADDR_EXPR
-	  || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL
-	  || DECL_BUILT_IN_CLASS (TREE_OPERAND (fn, 0)) != BUILT_IN_NORMAL
-	  || !builtin_decl_implicit (DECL_FUNCTION_CODE (TREE_OPERAND (fn, 0)))
-	  || !gimple_builtin_call_types_compatible_p (stmt,
-						      TREE_OPERAND (fn, 0)))
-	return false;
+	break;
+      }
 
-      tree decl = TREE_OPERAND (fn, 0);
-      tree type = TREE_TYPE (gimple_call_lhs (stmt));
-      switch (gimple_call_num_args (stmt))
+    case GIMPLE_CALL:
+      /* ???  This way we can't simplify calls with side-effects.  */
+      if (gimple_call_lhs (stmt) != NULL_TREE)
 	{
-	case 1:
-	  {
-	    tree arg1 = gimple_call_arg (stmt, 0);
-	    if (valueize && TREE_CODE (arg1) == SSA_NAME)
-	      {
-		arg1 = valueize (arg1);
-		if (!arg1)
-		  return false;
-	      }
-	    *rcode = DECL_FUNCTION_CODE (decl);
-	    ops[0] = arg1;
-	    return gimple_resimplify1 (seq, rcode, type, ops, valueize);
-	  }
-	case 2:
-	  {
-	    tree arg1 = gimple_call_arg (stmt, 0);
-	    if (valueize && TREE_CODE (arg1) == SSA_NAME)
-	      {
-		arg1 = valueize (arg1);
-		if (!arg1)
-		  return false;
-	      }
-	    tree arg2 = gimple_call_arg (stmt, 1);
-	    if (valueize && TREE_CODE (arg2) == SSA_NAME)
-	      {
-		arg2 = valueize (arg2);
-		if (!arg2)
-		  return false;
-	      }
-	    *rcode = DECL_FUNCTION_CODE (decl);
-	    ops[0] = arg1;
-	    ops[1] = arg2;
-	    return gimple_resimplify2 (seq, rcode, type, ops, valueize);
-	  }
-	case 3:
-	  {
-	    tree arg1 = gimple_call_arg (stmt, 0);
-	    if (valueize && TREE_CODE (arg1) == SSA_NAME)
-	      {
-		arg1 = valueize (arg1);
-		if (!arg1)
-		  return false;
-	      }
-	    tree arg2 = gimple_call_arg (stmt, 1);
-	    if (valueize && TREE_CODE (arg2) == SSA_NAME)
-	      {
-		arg2 = valueize (arg2);
-		if (!arg2)
-		  return false;
-	      }
-	    tree arg3 = gimple_call_arg (stmt, 2);
-	    if (valueize && TREE_CODE (arg3) == SSA_NAME)
+	  tree fn = gimple_call_fn (stmt);
+	  /* ???  Internal function support missing.  */
+	  if (!fn)
+	    return false;
+	  if (TREE_CODE (fn) == SSA_NAME
+	      && valueize)
+	    fn = valueize (fn);
+	  if (!fn
+	      || TREE_CODE (fn) != ADDR_EXPR
+	      || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL
+	      || DECL_BUILT_IN_CLASS (TREE_OPERAND (fn, 0)) != BUILT_IN_NORMAL
+	      || !builtin_decl_implicit (DECL_FUNCTION_CODE (TREE_OPERAND (fn, 0)))
+	      || !gimple_builtin_call_types_compatible_p (stmt,
+							  TREE_OPERAND (fn, 0)))
+	    return false;
+
+	  tree decl = TREE_OPERAND (fn, 0);
+	  tree type = TREE_TYPE (gimple_call_lhs (stmt));
+	  switch (gimple_call_num_args (stmt))
+	    {
+	    case 1:
 	      {
-		arg3 = valueize (arg3);
-		if (!arg3)
-		  return false;
+		tree arg1 = gimple_call_arg (stmt, 0);
+		if (valueize && TREE_CODE (arg1) == SSA_NAME)
+		  {
+		    arg1 = valueize (arg1);
+		    if (!arg1)
+		      return false;
+		  }
+		*rcode = DECL_FUNCTION_CODE (decl);
+		ops[0] = arg1;
+		return gimple_resimplify1 (seq, rcode, type, ops, valueize);
+	      }
+	    case 2:
+	      {
+		tree arg1 = gimple_call_arg (stmt, 0);
+		if (valueize && TREE_CODE (arg1) == SSA_NAME)
+		  {
+		    arg1 = valueize (arg1);
+		    if (!arg1)
+		      return false;
+		  }
+		tree arg2 = gimple_call_arg (stmt, 1);
+		if (valueize && TREE_CODE (arg2) == SSA_NAME)
+		  {
+		    arg2 = valueize (arg2);
+		    if (!arg2)
+		      return false;
+		  }
+		*rcode = DECL_FUNCTION_CODE (decl);
+		ops[0] = arg1;
+		ops[1] = arg2;
+		return gimple_resimplify2 (seq, rcode, type, ops, valueize);
+	      }
+	    case 3:
+	      {
+		tree arg1 = gimple_call_arg (stmt, 0);
+		if (valueize && TREE_CODE (arg1) == SSA_NAME)
+		  {
+		    arg1 = valueize (arg1);
+		    if (!arg1)
+		      return false;
+		  }
+		tree arg2 = gimple_call_arg (stmt, 1);
+		if (valueize && TREE_CODE (arg2) == SSA_NAME)
+		  {
+		    arg2 = valueize (arg2);
+		    if (!arg2)
+		      return false;
+		  }
+		tree arg3 = gimple_call_arg (stmt, 2);
+		if (valueize && TREE_CODE (arg3) == SSA_NAME)
+		  {
+		    arg3 = valueize (arg3);
+		    if (!arg3)
+		      return false;
+		  }
+		*rcode = DECL_FUNCTION_CODE (decl);
+		ops[0] = arg1;
+		ops[1] = arg2;
+		ops[2] = arg3;
+		return gimple_resimplify3 (seq, rcode, type, ops, valueize);
 	      }
-	    *rcode = DECL_FUNCTION_CODE (decl);
-	    ops[0] = arg1;
-	    ops[1] = arg2;
-	    ops[2] = arg3;
-	    return gimple_resimplify3 (seq, rcode, type, ops, valueize);
-	  }
-	default:
-	  return false;
+	    default:
+	      return false;
+	    }
 	}
+      break;
+
+    case GIMPLE_COND:
+      {
+	tree lhs = gimple_cond_lhs (stmt);
+	if (valueize && TREE_CODE (lhs) == SSA_NAME)
+	  {
+	    lhs = valueize (lhs);
+	    if (!lhs)
+	      return false;
+	  }
+	tree rhs = gimple_cond_rhs (stmt);
+	if (valueize && TREE_CODE (rhs) == SSA_NAME)
+	  {
+	    rhs = valueize (rhs);
+	    if (!rhs)
+	      return false;
+	  }
+	*rcode = gimple_cond_code (stmt);
+	ops[0] = lhs;
+	ops[1] = rhs;
+        return gimple_resimplify2 (seq, rcode, boolean_type_node, ops, valueize);
+      }
+
+    default:
+      break;
     }
 
   return false;
Index: gcc/match-comparison.pd
===================================================================
--- gcc/match-comparison.pd	(revision 215212)
+++ gcc/match-comparison.pd	(working copy)
@@ -1,10 +1,18 @@
 /* From fold_binary.  */
 
+/* On GIMPLE bool != 0 is simply the canonical way to express a
+   condition in COND_EXPRs and GIMPLE_CONDs.
+   ???  Of course for assignments we still may want to strip those...  */
 (simplify
  (ne @0 integer_zerop@1)
  (if (TREE_CODE (TREE_TYPE (@0)) == BOOLEAN_TYPE)
-  /* ???  In GENERIC the type of the comparison may be 'int'.  */
-  (convert @0)))
+  /* On GENERIC comparisons can have arbitrary integer types.  */
+  (if (GENERIC)
+    (convert @0))
+  /* On GIMPLE boolean types may have a precision != 1 thus the
+     comparison serves as a more canonical required conversion.  */
+  (if (GIMPLE && useless_type_conversion_p (type, TREE_TYPE (@0)))
+    @0)))
 
 /* Distribute operations in equality compares.  */
 (for op (eq ne)



More information about the Gcc-patches mailing list