aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-fold.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2014-10-24 11:00:08 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2014-10-24 11:00:08 +0000
commite0ee10ed5af17d90ea7621d4270a50284ad76c45 (patch)
tree826b57b3cced839600a97bf9bbdd9105348dfd6e /gcc/gimple-fold.c
parent77efea31205aab4e4fa0d2760d2fa6108d4a56f3 (diff)
downloadgcc-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.c156
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;
}