diff options
author | Richard Biener <rguenther@suse.de> | 2014-10-24 11:00:08 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2014-10-24 11:00:08 +0000 |
commit | e0ee10ed5af17d90ea7621d4270a50284ad76c45 (patch) | |
tree | 826b57b3cced839600a97bf9bbdd9105348dfd6e /gcc/gimple-fold.c | |
parent | 77efea31205aab4e4fa0d2760d2fa6108d4a56f3 (diff) | |
download | gcc-e0ee10ed5af17d90ea7621d4270a50284ad76c45.zip gcc-e0ee10ed5af17d90ea7621d4270a50284ad76c45.tar.gz gcc-e0ee10ed5af17d90ea7621d4270a50284ad76c45.tar.bz2 |
genmatch.c (expr::gen_transform): Use fold_buildN_loc and build_call_expr_loc.
2014-10-24 Richard Biener <rguenther@suse.de>
* genmatch.c (expr::gen_transform): Use fold_buildN_loc
and build_call_expr_loc.
(dt_simplify::gen): Drop non_lvalue for GIMPLE, use
non_lvalue_loc to build it for GENERIC.
(decision_tree::gen_generic): Add location argument to
generic_simplify prototype.
(capture_info): New class.
(capture_info::capture_info): New constructor.
(capture_info::walk_match): New method.
(capture_info::walk_result): New method.
(capture_info::walk_c_expr): New method.
(dt_simplify::gen): Handle preserving side-effects for
GENERIC code generation.
(decision_tree::gen_generic): Do not reject operands
with TREE_SIDE_EFFECTS.
* generic-match.h: New file.
* generic-match-head.c: Include generic-match.h, not gimple-match.h.
* match.pd: Add some constant folding patterns from fold-const.c.
* fold-const.c: Include generic-match.h.
(fold_unary_loc): Dispatch to generic_simplify.
(fold_ternary_loc): Likewise.
(fold_binary_loc): Likewise. Remove patterns now implemented
by generic_simplify.
* gimple-fold.c (replace_stmt_with_simplification): New function.
(fold_stmt_1): Add valueize parameter, dispatch to gimple_simplify.
(no_follow_ssa_edges): New function.
(fold_stmt): New overload with valueization hook. Use
no_follow_ssa_edges for the overload without hook.
(fold_stmt_inplace): Likewise.
* gimple-fold.h (no_follow_ssa_edges): Declare.
From-SVN: r216631
Diffstat (limited to 'gcc/gimple-fold.c')
-rw-r--r-- | gcc/gimple-fold.c | 156 |
1 files changed, 153 insertions, 3 deletions
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 5b47cbc..b262719 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -61,6 +61,8 @@ along with GCC; see the file COPYING3. If not see #include "dbgcnt.h" #include "builtins.h" #include "output.h" +#include "tree-eh.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. @@ -2792,6 +2794,121 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) return changed; } + +/* Worker for fold_stmt_1 dispatch to pattern based folding with + gimple_simplify. + + Replaces *GSI with the simplification result in RCODE and OPS + and the associated statements in *SEQ. Does the replacement + according to INPLACE and returns true if the operation succeeded. */ + +static bool +replace_stmt_with_simplification (gimple_stmt_iterator *gsi, + code_helper rcode, tree *ops, + gimple_seq *seq, bool inplace) +{ + gimple stmt = gsi_stmt (*gsi); + + /* Play safe and do not allow abnormals to be mentioned in + newly created statements. See also maybe_push_res_to_seq. */ + 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; + + 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. */ + && (!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) + return false; + gimple_cond_set_condition (stmt, NE_EXPR, res, + build_zero_cst (TREE_TYPE (res))); + } + else + return false; + 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); + return true; + } + else if (is_gimple_assign (stmt) + && rcode.is_tree_code ()) + { + if (!inplace + || gimple_num_ops (stmt) <= get_gimple_rhs_num_ops (rcode)) + { + maybe_build_generic_op (rcode, + TREE_TYPE (gimple_assign_lhs (stmt)), + &ops[0], ops[1], ops[2]); + gimple_assign_set_rhs_with_ops_1 (gsi, rcode, + ops[0], ops[1], ops[2]); + 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); + return true; + } + } + else if (!inplace) + { + if (gimple_has_lhs (stmt)) + { + tree lhs = gimple_get_lhs (stmt); + maybe_push_res_to_seq (rcode, TREE_TYPE (lhs), + ops, seq, lhs); + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "gimple_simplified to "); + print_gimple_seq (dump_file, *seq, 0, TDF_SLIM); + } + gsi_replace_with_seq_vops (gsi, *seq); + return true; + } + else + gcc_unreachable (); + } + + return false; +} + /* Canonicalize MEM_REFs invariant address operand after propagation. */ static bool @@ -2878,7 +2995,7 @@ maybe_canonicalize_mem_ref_addr (tree *t) distinguishes both cases. */ static bool -fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace) +fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree)) { bool changed = false; gimple stmt = gsi_stmt (*gsi); @@ -2956,6 +3073,25 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace) default:; } + /* Dispatch to pattern-based folding. */ + if (!inplace + || 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 (replace_stmt_with_simplification (gsi, rcode, ops, &seq, inplace)) + changed = true; + else + gimple_seq_discard (seq); + } + } + + stmt = gsi_stmt (*gsi); + /* Fold the main computation performed by the statement. */ switch (gimple_code (stmt)) { @@ -3095,6 +3231,14 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace) return changed; } +/* Valueziation callback that ends up not following SSA edges. */ + +tree +no_follow_ssa_edges (tree) +{ + return NULL_TREE; +} + /* Fold the statement pointed to by GSI. In some cases, this function may replace the whole statement with a new one. Returns true iff folding makes any changes. @@ -3105,7 +3249,13 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace) bool fold_stmt (gimple_stmt_iterator *gsi) { - return fold_stmt_1 (gsi, false); + return fold_stmt_1 (gsi, false, no_follow_ssa_edges); +} + +bool +fold_stmt (gimple_stmt_iterator *gsi, tree (*valueize) (tree)) +{ + return fold_stmt_1 (gsi, false, valueize); } /* Perform the minimal folding on statement *GSI. Only operations like @@ -3120,7 +3270,7 @@ bool fold_stmt_inplace (gimple_stmt_iterator *gsi) { gimple stmt = gsi_stmt (*gsi); - bool changed = fold_stmt_1 (gsi, true); + bool changed = fold_stmt_1 (gsi, true, no_follow_ssa_edges); gcc_assert (gsi_stmt (*gsi) == stmt); return changed; } |