aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-fold.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2018-05-24 08:02:35 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2018-05-24 08:02:35 +0000
commit5d75ad95aa808d6767afc0cdadd3b62e831c5cdf (patch)
tree0cc9a5a00b0c8f56cb996dc8818b9bfa42ed5005 /gcc/gimple-fold.c
parente29ea4832560f961c00e19fca923f325a08761d6 (diff)
downloadgcc-5d75ad95aa808d6767afc0cdadd3b62e831c5cdf.zip
gcc-5d75ad95aa808d6767afc0cdadd3b62e831c5cdf.tar.gz
gcc-5d75ad95aa808d6767afc0cdadd3b62e831c5cdf.tar.bz2
Add a class to represent a gimple match result
Gimple match results are represented by a code_helper for the operation, a tree for the type, and an array of three trees for the operands. This patch wraps them up in a class so that they don't need to be passed around individually. The main reason for doing this is to make it easier to increase the number of operands (for calls) or to support more complicated kinds of operation. But passing around fewer operands also helps to reduce the size of gimple-match.o (about 7% for development builds and 4% for release builds). 2018-05-24 Richard Sandiford <richard.sandiford@linaro.org> gcc/ * gimple-match.h (gimple_match_op): New class. (mprts_hook): Replace parameters with a gimple_match_op *. (maybe_build_generic_op): Likewise. (gimple_simplified_result_is_gimple_val): Replace parameters with a const gimple_match_op *. (gimple_simplify): Replace code_helper * and tree * parameters with a gimple_match_op * parameter. (gimple_resimplify1): Replace code_helper *, tree and tree * parameters with a gimple_match_op * parameter. (gimple_resimplify2): Likewise. (gimple_resimplify3): Likewise. (maybe_push_res_to_seq): Replace code_helper, tree and tree * parameters with a gimple_match_op * parameter. * gimple-match-head.c (gimple_simplify): Change prototypes of auto-generated functions to take a gimple_match_op * instead of separate code_helper * and tree * parameters. Make the same change in the top-level overload and update calls to the gimple_resimplify routines. Update calls to the auto-generated functions and to maybe_push_res_to_seq in the publicly-facing operation-specific gimple_simplify overloads. (gimple_match_op::MAX_NUM_OPS): Define. (gimple_resimplify1): Replace rcode and ops with a single res_op parameter. Update call to gimple_simplify. (gimple_resimplify2): Likewise. (gimple_resimplify3): Likewise. (mprts_hook): Replace parameters with a gimple_match_op *. (maybe_build_generic_op): Likewise. (build_call_internal): Replace type, nargs and ops with a gimple_match_op *. (maybe_push_res_to_seq): Replace res_code, type and ops parameters with a single gimple_match_op *. Update calls to mprts_hook, build_call_internal and gimple_simplified_result_is_gimple_val. Factor out code that is common to the tree_code and combined_fn cases. * genmatch.c (expr::gen_transform): Replace tem_code and tem_ops with a gimple_match_op called tem_op. Update calls to the gimple_resimplify functions and maybe_push_res_to_seq. (dt_simplify::gen_1): Manipulate res_op instead of res_code and res_ops. Update call to the gimple_resimplify functions. (dt_simplify::gen): Pass res_op instead of res_code and res_ops. (decision_tree::gen): Make the functions take a gimple_match_op * called res_op instead of separate res_code and res_ops parameters. Update call accordingly. * gimple-fold.c (replace_stmt_with_simplification): Replace rcode and ops with a single res_op parameter. Update calls to maybe_build_generic_op and maybe_push_res_to_seq. (fold_stmt_1): Update calls to gimple_simplify and replace_stmt_with_simplification. (gimple_fold_stmt_to_constant_1): Update calls to gimple_simplify and gimple_simplified_result_is_gimple_val. * tree-cfgcleanup.c (cleanup_control_expr_graph): Update call to gimple_simplify. * tree-ssa-sccvn.c (vn_lookup_simplify_result): Replace parameters with a gimple_match_op *. (vn_nary_build_or_lookup): Likewise. Update call to vn_nary_build_or_lookup_1. (vn_nary_build_or_lookup_1): Replace rcode, type and ops with a gimple_match_op *. Update calls to the gimple_resimplify routines and to gimple_simplified_result_is_gimple_val. (vn_nary_simplify): Update call to vn_nary_build_or_lookup_1. Use gimple_match_op::MAX_NUM_OPS instead of a hard-coded 3. (vn_reference_lookup_3): Update call to vn_nary_build_or_lookup. (visit_nary_op): Likewise. (visit_reference_op_load): Likewise. From-SVN: r260634
Diffstat (limited to 'gcc/gimple-fold.c')
-rw-r--r--gcc/gimple-fold.c98
1 files changed, 43 insertions, 55 deletions
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index b45798c..cd1ab80 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -4360,34 +4360,29 @@ has_use_on_stmt (tree name, gimple *stmt)
static bool
replace_stmt_with_simplification (gimple_stmt_iterator *gsi,
- code_helper rcode, tree *ops,
+ gimple_match_op *res_op,
gimple_seq *seq, bool inplace)
{
gimple *stmt = gsi_stmt (*gsi);
+ tree *ops = res_op->ops;
+ unsigned int num_ops = res_op->num_ops;
/* Play safe and do not allow abnormals to be mentioned in
newly created statements. See also maybe_push_res_to_seq.
As an exception allow such uses if there was a use of the
same SSA name on the old stmt. */
- if ((TREE_CODE (ops[0]) == SSA_NAME
- && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[0])
- && !has_use_on_stmt (ops[0], stmt))
- || (ops[1]
- && TREE_CODE (ops[1]) == SSA_NAME
- && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[1])
- && !has_use_on_stmt (ops[1], stmt))
- || (ops[2]
- && TREE_CODE (ops[2]) == SSA_NAME
- && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[2])
- && !has_use_on_stmt (ops[2], stmt))
- || (COMPARISON_CLASS_P (ops[0])
- && ((TREE_CODE (TREE_OPERAND (ops[0], 0)) == SSA_NAME
- && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (ops[0], 0))
- && !has_use_on_stmt (TREE_OPERAND (ops[0], 0), stmt))
- || (TREE_CODE (TREE_OPERAND (ops[0], 1)) == SSA_NAME
- && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (ops[0], 1))
- && !has_use_on_stmt (TREE_OPERAND (ops[0], 1), stmt)))))
- return false;
+ for (unsigned int i = 0; i < num_ops; ++i)
+ if (TREE_CODE (ops[i]) == SSA_NAME
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[i])
+ && !has_use_on_stmt (ops[i], stmt))
+ return false;
+
+ if (num_ops > 0 && COMPARISON_CLASS_P (ops[0]))
+ for (unsigned int i = 0; i < 2; ++i)
+ if (TREE_CODE (TREE_OPERAND (ops[0], i)) == SSA_NAME
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (ops[0], i))
+ && !has_use_on_stmt (TREE_OPERAND (ops[0], i), stmt))
+ return false;
/* Don't insert new statements when INPLACE is true, even if we could
reuse STMT for the final statement. */
@@ -4396,19 +4391,19 @@ replace_stmt_with_simplification (gimple_stmt_iterator *gsi,
if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
{
- gcc_assert (rcode.is_tree_code ());
- if (TREE_CODE_CLASS ((enum tree_code)rcode) == tcc_comparison
+ gcc_assert (res_op->code.is_tree_code ());
+ if (TREE_CODE_CLASS ((enum tree_code) res_op->code) == tcc_comparison
/* GIMPLE_CONDs condition may not throw. */
&& (!flag_exceptions
|| !cfun->can_throw_non_call_exceptions
- || !operation_could_trap_p (rcode,
+ || !operation_could_trap_p (res_op->code,
FLOAT_TYPE_P (TREE_TYPE (ops[0])),
false, NULL_TREE)))
- gimple_cond_set_condition (cond_stmt, rcode, ops[0], ops[1]);
- else if (rcode == SSA_NAME)
+ gimple_cond_set_condition (cond_stmt, res_op->code, ops[0], ops[1]);
+ else if (res_op->code == SSA_NAME)
gimple_cond_set_condition (cond_stmt, NE_EXPR, ops[0],
build_zero_cst (TREE_TYPE (ops[0])));
- else if (rcode == INTEGER_CST)
+ else if (res_op->code == INTEGER_CST)
{
if (integer_zerop (ops[0]))
gimple_cond_make_false (cond_stmt);
@@ -4417,8 +4412,7 @@ replace_stmt_with_simplification (gimple_stmt_iterator *gsi,
}
else if (!inplace)
{
- tree res = maybe_push_res_to_seq (rcode, boolean_type_node,
- ops, seq);
+ tree res = maybe_push_res_to_seq (res_op, seq);
if (!res)
return false;
gimple_cond_set_condition (cond_stmt, NE_EXPR, res,
@@ -4438,14 +4432,16 @@ replace_stmt_with_simplification (gimple_stmt_iterator *gsi,
return true;
}
else if (is_gimple_assign (stmt)
- && rcode.is_tree_code ())
+ && res_op->code.is_tree_code ())
{
if (!inplace
- || gimple_num_ops (stmt) > get_gimple_rhs_num_ops (rcode))
+ || gimple_num_ops (stmt) > get_gimple_rhs_num_ops (res_op->code))
{
- maybe_build_generic_op (rcode,
- TREE_TYPE (gimple_assign_lhs (stmt)), ops);
- gimple_assign_set_rhs_with_ops (gsi, rcode, ops[0], ops[1], ops[2]);
+ maybe_build_generic_op (res_op);
+ gimple_assign_set_rhs_with_ops (gsi, res_op->code,
+ res_op->op_or_null (0),
+ res_op->op_or_null (1),
+ res_op->op_or_null (2));
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "gimple_simplified to ");
@@ -4458,17 +4454,12 @@ replace_stmt_with_simplification (gimple_stmt_iterator *gsi,
return true;
}
}
- else if (rcode.is_fn_code ()
- && gimple_call_combined_fn (stmt) == rcode)
+ else if (res_op->code.is_fn_code ()
+ && gimple_call_combined_fn (stmt) == res_op->code)
{
- unsigned i;
- for (i = 0; i < gimple_call_num_args (stmt); ++i)
- {
- gcc_assert (ops[i] != NULL_TREE);
- gimple_call_set_arg (stmt, i, ops[i]);
- }
- if (i < 3)
- gcc_assert (ops[i] == NULL_TREE);
+ gcc_assert (num_ops == gimple_call_num_args (stmt));
+ for (unsigned int i = 0; i < num_ops; ++i)
+ gimple_call_set_arg (stmt, i, ops[i]);
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "gimple_simplified to ");
@@ -4484,8 +4475,7 @@ replace_stmt_with_simplification (gimple_stmt_iterator *gsi,
if (gimple_has_lhs (stmt))
{
tree lhs = gimple_get_lhs (stmt);
- if (!maybe_push_res_to_seq (rcode, TREE_TYPE (lhs),
- ops, seq, lhs))
+ if (!maybe_push_res_to_seq (res_op, seq, lhs))
return false;
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -4751,12 +4741,11 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree))
|| gimple_code (stmt) == GIMPLE_COND)
{
gimple_seq seq = NULL;
- code_helper rcode;
- tree ops[3] = {};
- if (gimple_simplify (stmt, &rcode, ops, inplace ? NULL : &seq,
+ gimple_match_op res_op;
+ if (gimple_simplify (stmt, &res_op, inplace ? NULL : &seq,
valueize, valueize))
{
- if (replace_stmt_with_simplification (gsi, rcode, ops, &seq, inplace))
+ if (replace_stmt_with_simplification (gsi, &res_op, &seq, inplace))
changed = true;
else
gimple_seq_discard (seq);
@@ -6106,19 +6095,18 @@ tree
gimple_fold_stmt_to_constant_1 (gimple *stmt, tree (*valueize) (tree),
tree (*gvalueize) (tree))
{
- code_helper rcode;
- tree ops[3] = {};
+ gimple_match_op res_op;
/* ??? The SSA propagators do not correctly deal with following SSA use-def
edges if there are intermediate VARYING defs. For this reason
do not follow SSA edges here even though SCCVN can technically
just deal fine with that. */
- if (gimple_simplify (stmt, &rcode, ops, NULL, gvalueize, valueize))
+ if (gimple_simplify (stmt, &res_op, NULL, gvalueize, valueize))
{
tree res = NULL_TREE;
- if (gimple_simplified_result_is_gimple_val (rcode, ops))
- res = ops[0];
+ if (gimple_simplified_result_is_gimple_val (&res_op))
+ res = res_op.ops[0];
else if (mprts_hook)
- res = mprts_hook (rcode, gimple_expr_type (stmt), ops);
+ res = mprts_hook (&res_op);
if (res)
{
if (dump_file && dump_flags & TDF_DETAILS)