diff mbox

[match-and-simplify] Refactor the deprecated APIs

Message ID alpine.LSU.2.11.1408151425270.20733@zhemvz.fhfr.qr
State New
Headers show

Commit Message

Richard Biener Aug. 15, 2014, 12:26 p.m. UTC
This removes the deprecated APIs and inlines them into their single
caller.  This exposes publically the 'code_helper' class which will
also be needed for manually written simplifiers (that's next).

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

Richard.

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

	* gimple-match.h: New file.
	* gimple-fold.c: Include gimple-match.h.
	(fold_stmt_1): Use stmt-based gimple_simplify API.
	(gimple_fold_stmt_to_constant_1): Likewise.
	* gimple-match-head.c: Include gimple-match.h.
	(class code_helper): Move to gimple-match.h.
	(maybe_push_res_to_seq): Export.
	(gimple_simplify): Likewise.
	(gimple_simplify): New overload for functions with tree arguments.
	(gimple_simplify): Remove gsi and SSA name overloads.
	* gimple-fold.h (gimple_simplify): Remove gsi and SSA name
	overloads.
diff mbox

Patch

Index: gcc/gimple-fold.c
===================================================================
--- gcc/gimple-fold.c	(revision 214012)
+++ gcc/gimple-fold.c	(working copy)
@@ -55,6 +55,8 @@  along with GCC; see the file COPYING3.
 #include "dbgcnt.h"
 #include "builtins.h"
 #include "output.h"
+#include "gimple-match.h"
+
 
 /* Return true when DECL can be referenced from current unit.
    FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
@@ -2698,15 +2700,62 @@  fold_stmt_1 (gimple_stmt_iterator *gsi,
 
   /* Dispatch to pattern-based folding.
      ???  Do this after the previous stuff as fold_stmt is used to make
-     stmts valid gimple again via maybe_fold_reference of ops.
-     ???  Use a lower-level API using a NULL sequence for inplace
-     operation, basically inline gimple_simplify (gsi)
-     as we are the only caller.  */
-  if (!inplace
-      && gimple_simplify (gsi, valueize))
-    changed = true;
+     stmts valid gimple again via maybe_fold_reference of ops.  */
+  /* ???  Change "inplace" semantics to allow replacing a stmt if
+     no further stmts need to be inserted (basically disallow
+     creating of new SSA names).  */
+  if (inplace
+      && !is_gimple_assign (stmt))
+    return changed;
 
-  return changed;
+  gimple_seq seq = NULL;
+  code_helper rcode;
+  tree ops[3] = {};
+  if (!gimple_simplify (stmt, &rcode, ops, inplace ? NULL : &seq, valueize))
+    return changed;
+
+  if (is_gimple_assign (stmt)
+      && rcode.is_tree_code ())
+    {
+      if (inplace
+	  && gimple_num_ops (stmt) <= get_gimple_rhs_num_ops (rcode))
+	return changed;
+      /* Play safe and do not allow abnormals to be mentioned in
+         newly created statements.  */
+      if ((TREE_CODE (ops[0]) == SSA_NAME
+	   && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[0]))
+	  || (ops[1]
+	      && TREE_CODE (ops[1]) == SSA_NAME
+	      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[1]))
+	  || (ops[2]
+	      && TREE_CODE (ops[2]) == SSA_NAME
+	      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[2])))
+	return changed;
+      gimple_assign_set_rhs_with_ops_1 (gsi, rcode, ops[0], ops[1], ops[2]);
+    }
+  else
+    {
+      if (inplace)
+	return changed;
+      if (gimple_has_lhs (stmt))
+	{
+	  gimple_seq tail = NULL;
+	  tree lhs = gimple_get_lhs (stmt);
+	  maybe_push_res_to_seq (rcode, TREE_TYPE (lhs),
+				 ops, &tail, lhs);
+	  gcc_assert (gimple_seq_singleton_p (tail));
+	  gimple with = gimple_seq_first_stmt (tail);
+	  gimple_set_vdef (with, gimple_vdef (stmt));
+	  gimple_set_vuse (with, gimple_vuse (stmt));
+	  gsi_replace (gsi, with, false);
+	}
+      else
+	gcc_unreachable ();
+    }
+
+  if (!inplace)
+    gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT);
+  return true;
 }
 
 /* Fold the statement pointed to by GSI.  In some cases, this function may
@@ -4103,24 +4152,29 @@  gimple_fold_stmt_to_constant_2 (gimple s
 tree
 gimple_fold_stmt_to_constant_1 (gimple stmt, tree (*valueize) (tree))
 {
-  tree lhs = gimple_get_lhs (stmt);
-  if (lhs)
-    {
-      tree res = gimple_simplify (lhs, NULL, valueize);
-      if (res)
-	{
-	  if (dump_file && dump_flags & TDF_DETAILS)
-	    {
-	      fprintf (dump_file, "Match-and-simplified ");
-	      print_gimple_expr (dump_file, stmt, 0, TDF_SLIM);
-	      fprintf (dump_file, " to ");
-	      print_generic_expr (dump_file, res, 0);
-	      fprintf (dump_file, "\n");
-	    }
-	  return res;
-	}
-    }
-  /* ???  For now, to avoid regressions.  */
+  code_helper rcode;
+  tree ops[3] = {};
+  if (gimple_simplify (stmt, &rcode, ops, NULL, valueize)
+      && rcode.is_tree_code ()
+      && (TREE_CODE_LENGTH ((tree_code) rcode) == 0
+	  || ((tree_code) rcode) == ADDR_EXPR)
+      && is_gimple_val (ops[0]))
+    {
+      tree res = ops[0];
+      if (dump_file && dump_flags & TDF_DETAILS)
+	{
+	  fprintf (dump_file, "Match-and-simplified ");
+	  print_gimple_expr (dump_file, stmt, 0, TDF_SLIM);
+	  fprintf (dump_file, " to ");
+	  print_generic_expr (dump_file, res, 0);
+	  fprintf (dump_file, "\n");
+	}
+      return res;
+    }
+
+  /* ???  For now, to avoid regressions.  Notably gimple_simplfy
+     doesn't "simplify" s_1 = constant; or s_1 = name_2; by
+     returning a valueized RHS.  */
   return gimple_fold_stmt_to_constant_2 (stmt, valueize);
 }
 
Index: gcc/gimple-fold.h
===================================================================
--- gcc/gimple-fold.h	(revision 214012)
+++ gcc/gimple-fold.h	(working copy)
@@ -118,9 +118,7 @@  tree gimple_simplify (enum built_in_func
 		      gimple_seq *, tree (*)(tree));
 tree gimple_simplify (enum built_in_function, tree, tree, tree,
 		      gimple_seq *, tree (*)(tree));
-/* The following two APIs are an artifact and should vanish in favor
-   of the existing gimple_fold_stmt_to_constant and fold_stmt APIs.  */
-tree gimple_simplify (tree, gimple_seq *, tree (*)(tree));
-bool gimple_simplify (gimple_stmt_iterator *, tree (*)(tree));
+tree gimple_simplify (enum built_in_function, tree, tree, tree, tree,
+		      gimple_seq *, tree (*)(tree));
 
 #endif  /* GCC_GIMPLE_FOLD_H */
Index: gcc/gimple-match-head.c
===================================================================
--- gcc/gimple-match-head.c	(revision 214012)
+++ gcc/gimple-match-head.c	(working copy)
@@ -38,28 +38,13 @@  along with GCC; see the file COPYING3.
 #include "expr.h"
 #include "tree-dfa.h"
 #include "builtins.h"
+#include "gimple-match.h"
 
 #define INTEGER_CST_P(node) (TREE_CODE(node) == INTEGER_CST)
 #define integral_op_p(node) INTEGRAL_TYPE_P(TREE_TYPE(node))
 #define REAL_CST_P(node) (TREE_CODE(node) == REAL_CST)
 
 
-/* Helper to transparently allow tree codes and builtin function codes
-   exist in one storage entity.  */
-class code_helper
-{
-public:
-  code_helper () {}
-  code_helper (tree_code code) : rep ((int) code) {}
-  code_helper (built_in_function fn) : rep (-(int) fn) {}
-  operator tree_code () const { return (tree_code) rep; }
-  operator built_in_function () const { return (built_in_function) -rep; }
-  bool is_tree_code () const { return rep > 0; }
-  bool is_fn_code () const { return rep < 0; }
-private:
-  int rep;
-};
-
 /* Forward declarations of the private auto-generated matchers.
    They expect valueized operands in canonical order and do not
    perform simplification of all-constant operands.  */
@@ -290,9 +275,9 @@  gimple_resimplify3 (gimple_seq *seq,
    then the result will be always RES and even gimple values are
    pushed to SEQ.  */
 
-static tree
+tree
 maybe_push_res_to_seq (code_helper rcode, tree type, tree *ops,
-		       gimple_seq *seq, tree res = NULL_TREE)
+		       gimple_seq *seq, tree res)
 {
   if (rcode.is_tree_code ())
     {
@@ -350,6 +335,18 @@  maybe_push_res_to_seq (code_helper rcode
     }
 }
 
+
+/* Public API overloads follow for operation being tree_code or
+   built_in_function and for one to three operands or arguments.
+   They return NULL_TREE if nothing could be simplified or
+   the resulting simplified value with parts pushed to SEQ.
+   If SEQ is NULL then if the simplification needs to create
+   new stmts it will fail.  If VALUEIZE is non-NULL then all
+   SSA names will be valueized using that hook prior to
+   applying simplifications.  */
+
+/* Unary ops.  */
+
 tree
 gimple_simplify (enum tree_code code, tree type,
 		 tree op0,
@@ -371,10 +368,12 @@  gimple_simplify (enum tree_code code, tr
   return maybe_push_res_to_seq (rcode, type, ops, seq);
 }
 
+/* Binary ops.  */
+
 tree
 gimple_simplify (enum tree_code code, tree type,
-			   tree op0, tree op1,
-			   gimple_seq *seq, tree (*valueize)(tree))
+		 tree op0, tree op1,
+		 gimple_seq *seq, tree (*valueize)(tree))
 {
   if (constant_for_folding (op0) && constant_for_folding (op1))
     {
@@ -402,6 +401,8 @@  gimple_simplify (enum tree_code code, tr
   return maybe_push_res_to_seq (rcode, type, ops, seq);
 }
 
+/* Ternary ops.  */
+
 tree
 gimple_simplify (enum tree_code code, tree type,
 		 tree op0, tree op1, tree op2,
@@ -434,6 +435,8 @@  gimple_simplify (enum tree_code code, tr
   return maybe_push_res_to_seq (rcode, type, ops, seq);
 }
 
+/* Builtin function with one argument.  */
+
 tree
 gimple_simplify (enum built_in_function fn, tree type,
 		 tree arg0,
@@ -464,6 +467,8 @@  gimple_simplify (enum built_in_function
   return maybe_push_res_to_seq (rcode, type, ops, seq);
 }
 
+/* Builtin function with two arguments.  */
+
 tree
 gimple_simplify (enum built_in_function fn, tree type,
 		 tree arg0, tree arg1,
@@ -498,7 +503,49 @@  gimple_simplify (enum built_in_function
   return maybe_push_res_to_seq (rcode, type, ops, seq);
 }
 
-static bool
+/* Builtin function with three arguments.  */
+
+tree
+gimple_simplify (enum built_in_function fn, tree type,
+		 tree arg0, tree arg1, tree arg2,
+		 gimple_seq *seq, tree (*valueize)(tree))
+{
+  if (constant_for_folding (arg0)
+      && constant_for_folding (arg1)
+      && constant_for_folding (arg2))
+    {
+      tree decl = builtin_decl_implicit (fn);
+      if (decl)
+	{
+	  tree args[3];
+	  args[0] = arg0;
+	  args[1] = arg1;
+	  args[2] = arg2;
+	  tree res = fold_builtin_n (UNKNOWN_LOCATION, decl, args, 3, false);
+	  if (res)
+	    {
+	      /* fold_builtin_n wraps the result inside a NOP_EXPR.  */
+	      STRIP_NOPS (res);
+	      res = fold_convert (type, res);
+	      if (CONSTANT_CLASS_P (res))
+		return res;
+	    }
+	}
+    }
+
+  code_helper rcode;
+  tree ops[3] = {};
+  if (!gimple_simplify (&rcode, ops, seq, valueize,
+			fn, type, arg0, arg1, arg2))
+    return NULL_TREE;
+  return maybe_push_res_to_seq (rcode, type, ops, seq);
+}
+
+
+/* The main STMT based simplification entry.  It is used by the fold_stmt
+   and the fold_stmt_to_constant APIs.  */
+
+bool
 gimple_simplify (gimple stmt,
 		 code_helper *rcode, tree *ops,
 		 gimple_seq *seq, tree (*valueize)(tree))
@@ -686,92 +733,7 @@  gimple_simplify (gimple stmt,
 }
 
 
-/* Match and simplify on the defining statement of NAME using VALUEIZE
-   if not NULL to valueize SSA names in expressions.  NAME is expected
-   to be valueized already.  Appends statements for complex expression
-   results to SEQ or fails if that would be required and SEQ is NULL.
-   Returns the simplified value (which might be defined by stmts in
-   SEQ) or NULL_TREE if no simplification was possible.  */
-
-tree
-gimple_simplify (tree name, gimple_seq *seq, tree (*valueize)(tree))
-{
-  if (TREE_CODE (name) != SSA_NAME)
-    return NULL_TREE;
-
-  /* This function is supposed to return a valueization of name, thus
-     also allow simply returning an unsimplified RHS of its definition
-     statement.  */
-  gimple stmt = SSA_NAME_DEF_STMT (name);
-  if (gimple_assign_single_p (stmt))
-    {
-      tree rhs = gimple_assign_rhs1 (stmt);
-      if (TREE_CODE (rhs) == SSA_NAME)
-	{
-	  if (valueize)
-	    rhs = valueize (rhs);
-	  return rhs;
-	}
-      else if (is_gimple_min_invariant (rhs))
-	return rhs;
-    }
-
-  code_helper rcode;
-  tree ops[3] = {};
-  if (!gimple_simplify (stmt, &rcode, ops, seq, valueize))
-    return NULL_TREE;
-  return maybe_push_res_to_seq (rcode, TREE_TYPE (name), ops, seq);
-}
-
-/* Match and simplify on *GSI and replace that with the simplified stmt
-   sequence.  */
-
-bool
-gimple_simplify (gimple_stmt_iterator *gsi, tree (*valueize)(tree))
-{
-  gimple stmt = gsi_stmt (*gsi);
-  gimple_seq seq = NULL;
-  code_helper rcode;
-  tree ops[3] = {};
-  if (!gimple_simplify (stmt, &rcode, ops, &seq, valueize))
-    return false;
-
-  if (is_gimple_assign (stmt)
-      && rcode.is_tree_code ())
-    {
-      /* Play safe and do not allow abnormals to be mentioned in
-         newly created statements.  */
-      if ((TREE_CODE (ops[0]) == SSA_NAME
-	   && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[0]))
-	  || (ops[1]
-	      && TREE_CODE (ops[1]) == SSA_NAME
-	      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[1]))
-	  || (ops[2]
-	      && TREE_CODE (ops[2]) == SSA_NAME
-	      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[2])))
-	return false;
-      gimple_assign_set_rhs_with_ops_1 (gsi, rcode, ops[0], ops[1], ops[2]);
-      update_stmt (gsi_stmt (*gsi));
-    }
-  else if (gimple_has_lhs (stmt))
-    {
-      gimple_seq tail = NULL;
-      tree lhs = gimple_get_lhs (stmt);
-      maybe_push_res_to_seq (rcode, TREE_TYPE (lhs),
-			     ops, &tail, lhs);
-      gcc_assert (gimple_seq_singleton_p (tail));
-      gimple with = gimple_seq_first_stmt (tail);
-      gimple_set_vdef (with, gimple_vdef (stmt));
-      gimple_set_vuse (with, gimple_vuse (stmt));
-      gsi_replace (gsi, with, false);
-    }
-  else
-    /* Handle for example GIMPLE_COND, etc.  */
-    gcc_unreachable ();
-
-  gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT);
-  return true;
-}
+/* Helper for the autogenerated code, valueize OP.  */
 
 static tree 
 do_valueize (tree (*valueize)(tree), tree op)
Index: gcc/gimple-match.h
===================================================================
--- gcc/gimple-match.h	(revision 0)
+++ gcc/gimple-match.h	(working copy)
@@ -0,0 +1,48 @@ 
+/* Gimple simplify definitions.
+
+   Copyright (C) 2011-2014 Free Software Foundation, Inc.
+   Contributed by Richard Guenther <rguenther@suse.de>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_GIMPLE_MATCH_H
+#define GCC_GIMPLE_MATCH_H
+
+
+/* Helper to transparently allow tree codes and builtin function codes
+   exist in one storage entity.  */
+class code_helper
+{
+public:
+  code_helper () {}
+  code_helper (tree_code code) : rep ((int) code) {}
+  code_helper (built_in_function fn) : rep (-(int) fn) {}
+  operator tree_code () const { return (tree_code) rep; }
+  operator built_in_function () const { return (built_in_function) -rep; }
+  bool is_tree_code () const { return rep > 0; }
+  bool is_fn_code () const { return rep < 0; }
+private:
+  int rep;
+};
+
+bool gimple_simplify (gimple, code_helper *, tree *, gimple_seq *,
+		      tree (*)(tree));
+tree maybe_push_res_to_seq (code_helper, tree, tree *,
+			    gimple_seq *, tree res = NULL_TREE);
+
+
+#endif  /* GCC_GIMPLE_MATCH_H */