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 <rguent...@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. 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 <rguent...@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 */