diff options
author | Li Jia He <helijia@linux.ibm.com> | 2019-09-16 14:21:20 +0000 |
---|---|---|
committer | Martin Liska <marxin@gcc.gnu.org> | 2019-09-16 14:21:20 +0000 |
commit | 5f487a349de62613d7fa429bcbfbeeafbfc94f3a (patch) | |
tree | d63d3e1bb2210eb3e25095d2dc0deab2b5ccf72a /gcc/gimple-fold.c | |
parent | 10f30ac9cda947d117e50f0cbd4cf94ee70a944f (diff) | |
download | gcc-5f487a349de62613d7fa429bcbfbeeafbfc94f3a.zip gcc-5f487a349de62613d7fa429bcbfbeeafbfc94f3a.tar.gz gcc-5f487a349de62613d7fa429bcbfbeeafbfc94f3a.tar.bz2 |
Auto-generate maybe_fold_and/or_comparisons from match.pd
2019-09-16 Li Jia He <helijia@linux.ibm.com>
Martin Liska <mliska@suse.cz>
* gimple-fold.c (and_comparisons_1): Add type as first
argument.
(and_var_with_comparison): Likewise.
(and_var_with_comparison_1): Likewise.
(or_comparisons_1): Likewise.
(or_var_with_comparison): Likewise.
(or_var_with_comparison_1): Likewise.
(maybe_fold_and_comparisons): Call maybe_fold_comparisons_from_match_pd.
(maybe_fold_or_comparisons): Likewise.
(maybe_fold_comparisons_from_match_pd): New.
* gimple-fold.h (maybe_fold_and_comparisons): Add type argument.
(maybe_fold_or_comparisons): Likewise.
* gimple.c (gimple_size): Make it public and add num_ops argument.
(gimple_init): New function.
(gimple_alloc): Call gimple_init.
* gimple.h (gimple_size): New.
(gimple_init): Likewise.
* tree-if-conv.c (fold_or_predicates): Pass type.
* tree-ssa-ifcombine.c (ifcombine_ifandif): Likewise.
* tree-ssa-reassoc.c (eliminate_redundant_comparison): Likewise.
(optimize_vec_cond_expr): Likewise.
(ovce_extract_ops): Return type of conditional expression.
* tree-ssanames.c (init_ssa_name_imm_use): New.
(make_ssa_name_fn): Use init_ssa_name_imm_use.
* tree-ssanames.h (init_ssa_name_imm_use): New.
Co-Authored-By: Martin Liska <mliska@suse.cz>
From-SVN: r275748
Diffstat (limited to 'gcc/gimple-fold.c')
-rw-r--r-- | gcc/gimple-fold.c | 170 |
1 files changed, 129 insertions, 41 deletions
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index fcffb98..6d9ba36 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -5371,22 +5371,22 @@ same_bool_result_p (const_tree op1, const_tree op2) /* Forward declarations for some mutually recursive functions. */ static tree -and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, +and_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b, enum tree_code code2, tree op2a, tree op2b); static tree -and_var_with_comparison (tree var, bool invert, +and_var_with_comparison (tree type, tree var, bool invert, enum tree_code code2, tree op2a, tree op2b); static tree -and_var_with_comparison_1 (gimple *stmt, +and_var_with_comparison_1 (tree type, gimple *stmt, enum tree_code code2, tree op2a, tree op2b); static tree -or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, +or_comparisons_1 (tree, enum tree_code code1, tree op1a, tree op1b, enum tree_code code2, tree op2a, tree op2b); static tree -or_var_with_comparison (tree var, bool invert, +or_var_with_comparison (tree, tree var, bool invert, enum tree_code code2, tree op2a, tree op2b); static tree -or_var_with_comparison_1 (gimple *stmt, +or_var_with_comparison_1 (tree, gimple *stmt, enum tree_code code2, tree op2a, tree op2b); /* Helper function for and_comparisons_1: try to simplify the AND of the @@ -5395,7 +5395,7 @@ or_var_with_comparison_1 (gimple *stmt, Return NULL_EXPR if we can't simplify this to a single expression. */ static tree -and_var_with_comparison (tree var, bool invert, +and_var_with_comparison (tree type, tree var, bool invert, enum tree_code code2, tree op2a, tree op2b) { tree t; @@ -5409,11 +5409,11 @@ and_var_with_comparison (tree var, bool invert, !var AND (op2a code2 op2b) => !(var OR !(op2a code2 op2b)) Then we only have to consider the simpler non-inverted cases. */ if (invert) - t = or_var_with_comparison_1 (stmt, + t = or_var_with_comparison_1 (type, stmt, invert_tree_comparison (code2, false), op2a, op2b); else - t = and_var_with_comparison_1 (stmt, code2, op2a, op2b); + t = and_var_with_comparison_1 (type, stmt, code2, op2a, op2b); return canonicalize_bool (t, invert); } @@ -5422,7 +5422,7 @@ and_var_with_comparison (tree var, bool invert, Return NULL_EXPR if we can't simplify this to a single expression. */ static tree -and_var_with_comparison_1 (gimple *stmt, +and_var_with_comparison_1 (tree type, gimple *stmt, enum tree_code code2, tree op2a, tree op2b) { tree var = gimple_assign_lhs (stmt); @@ -5453,7 +5453,7 @@ and_var_with_comparison_1 (gimple *stmt, /* If the definition is a comparison, recurse on it. */ if (TREE_CODE_CLASS (innercode) == tcc_comparison) { - tree t = and_comparisons_1 (innercode, + tree t = and_comparisons_1 (type, innercode, gimple_assign_rhs1 (stmt), gimple_assign_rhs2 (stmt), code2, @@ -5489,18 +5489,20 @@ and_var_with_comparison_1 (gimple *stmt, else if (inner1 == false_test_var) return (is_and ? boolean_false_node - : and_var_with_comparison (inner2, false, code2, op2a, op2b)); + : and_var_with_comparison (type, inner2, false, code2, op2a, + op2b)); else if (inner2 == false_test_var) return (is_and ? boolean_false_node - : and_var_with_comparison (inner1, false, code2, op2a, op2b)); + : and_var_with_comparison (type, inner1, false, code2, op2a, + op2b)); /* Next, redistribute/reassociate the AND across the inner tests. Compute the first partial result, (inner1 AND (op2a code op2b)) */ if (TREE_CODE (inner1) == SSA_NAME && is_gimple_assign (s = SSA_NAME_DEF_STMT (inner1)) && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison - && (t = maybe_fold_and_comparisons (gimple_assign_rhs_code (s), + && (t = maybe_fold_and_comparisons (type, gimple_assign_rhs_code (s), gimple_assign_rhs1 (s), gimple_assign_rhs2 (s), code2, op2a, op2b))) @@ -5532,7 +5534,7 @@ and_var_with_comparison_1 (gimple *stmt, if (TREE_CODE (inner2) == SSA_NAME && is_gimple_assign (s = SSA_NAME_DEF_STMT (inner2)) && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison - && (t = maybe_fold_and_comparisons (gimple_assign_rhs_code (s), + && (t = maybe_fold_and_comparisons (type, gimple_assign_rhs_code (s), gimple_assign_rhs1 (s), gimple_assign_rhs2 (s), code2, op2a, op2b))) @@ -5588,7 +5590,7 @@ and_var_with_comparison_1 (gimple *stmt, in the first comparison but not the second. */ static tree -and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, +and_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b, enum tree_code code2, tree op2a, tree op2b) { tree truth_type = truth_type_for (TREE_TYPE (op1a)); @@ -5762,7 +5764,8 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, { case GIMPLE_ASSIGN: /* Try to simplify by copy-propagating the definition. */ - return and_var_with_comparison (op1a, invert, code2, op2a, op2b); + return and_var_with_comparison (type, op1a, invert, code2, op2a, + op2b); case GIMPLE_PHI: /* If every argument to the PHI produces the same result when @@ -5812,7 +5815,7 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, gimple_bb (def_stmt), gimple_bb (stmt))) return NULL_TREE; - temp = and_var_with_comparison (arg, invert, code2, + temp = and_var_with_comparison (type, arg, invert, code2, op2a, op2b); if (!temp) return NULL_TREE; @@ -5834,6 +5837,73 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, return NULL_TREE; } +/* Helper function for maybe_fold_and_comparisons and maybe_fold_or_comparisons + : try to simplify the AND/OR of the ssa variable VAR with the comparison + specified by (OP2A CODE2 OP2B) from match.pd. Return NULL_EXPR if we can't + simplify this to a single expression. As we are going to lower the cost + of building SSA names / gimple stmts significantly, we need to allocate + them ont the stack. This will cause the code to be a bit ugly. */ + +static tree +maybe_fold_comparisons_from_match_pd (tree type, enum tree_code code, + enum tree_code code1, + tree op1a, tree op1b, + enum tree_code code2, tree op2a, + tree op2b) +{ + /* Allocate gimple stmt1 on the stack. */ + gassign *stmt1 + = (gassign *) XALLOCAVEC (char, gimple_size (GIMPLE_ASSIGN, 3)); + gimple_init (stmt1, GIMPLE_ASSIGN, 3); + gimple_assign_set_rhs_code (stmt1, code1); + gimple_assign_set_rhs1 (stmt1, op1a); + gimple_assign_set_rhs2 (stmt1, op1b); + + /* Allocate gimple stmt2 on the stack. */ + gassign *stmt2 + = (gassign *) XALLOCAVEC (char, gimple_size (GIMPLE_ASSIGN, 3)); + gimple_init (stmt2, GIMPLE_ASSIGN, 3); + gimple_assign_set_rhs_code (stmt2, code2); + gimple_assign_set_rhs1 (stmt2, op2a); + gimple_assign_set_rhs2 (stmt2, op2b); + + /* Allocate SSA names(lhs1) on the stack. */ + tree lhs1 = (tree)XALLOCA (tree_ssa_name); + memset (lhs1, 0, sizeof (tree_ssa_name)); + TREE_SET_CODE (lhs1, SSA_NAME); + TREE_TYPE (lhs1) = type; + init_ssa_name_imm_use (lhs1); + + /* Allocate SSA names(lhs2) on the stack. */ + tree lhs2 = (tree)XALLOCA (tree_ssa_name); + memset (lhs2, 0, sizeof (tree_ssa_name)); + TREE_SET_CODE (lhs2, SSA_NAME); + TREE_TYPE (lhs2) = type; + init_ssa_name_imm_use (lhs2); + + gimple_assign_set_lhs (stmt1, lhs1); + gimple_assign_set_lhs (stmt2, lhs2); + + gimple_match_op op (gimple_match_cond::UNCOND, code, + type, gimple_assign_lhs (stmt1), + gimple_assign_lhs (stmt2)); + if (op.resimplify (NULL, follow_all_ssa_edges)) + { + if (gimple_simplified_result_is_gimple_val (&op)) + { + tree res = op.ops[0]; + if (res == lhs1) + return build2 (code1, type, op1a, op1b); + else if (res == lhs2) + return build2 (code2, type, op2a, op2b); + else + return res; + } + } + + return NULL_TREE; +} + /* Try to simplify the AND of two comparisons, specified by (OP1A CODE1 OP1B) and (OP2B CODE2 OP2B), respectively. If this can be simplified to a single expression (without requiring @@ -5842,14 +5912,22 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, If the result expression is non-null, it has boolean type. */ tree -maybe_fold_and_comparisons (enum tree_code code1, tree op1a, tree op1b, +maybe_fold_and_comparisons (tree type, + enum tree_code code1, tree op1a, tree op1b, enum tree_code code2, tree op2a, tree op2b) { - tree t = and_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b); - if (t) + if (tree t = and_comparisons_1 (type, code1, op1a, op1b, code2, op2a, op2b)) return t; - else - return and_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b); + + if (tree t = and_comparisons_1 (type, code2, op2a, op2b, code1, op1a, op1b)) + return t; + + if (tree t = maybe_fold_comparisons_from_match_pd (type, BIT_AND_EXPR, code1, + op1a, op1b, code2, op2a, + op2b)) + return t; + + return NULL_TREE; } /* Helper function for or_comparisons_1: try to simplify the OR of the @@ -5858,7 +5936,7 @@ maybe_fold_and_comparisons (enum tree_code code1, tree op1a, tree op1b, Return NULL_EXPR if we can't simplify this to a single expression. */ static tree -or_var_with_comparison (tree var, bool invert, +or_var_with_comparison (tree type, tree var, bool invert, enum tree_code code2, tree op2a, tree op2b) { tree t; @@ -5872,11 +5950,11 @@ or_var_with_comparison (tree var, bool invert, !var OR (op2a code2 op2b) => !(var AND !(op2a code2 op2b)) Then we only have to consider the simpler non-inverted cases. */ if (invert) - t = and_var_with_comparison_1 (stmt, + t = and_var_with_comparison_1 (type, stmt, invert_tree_comparison (code2, false), op2a, op2b); else - t = or_var_with_comparison_1 (stmt, code2, op2a, op2b); + t = or_var_with_comparison_1 (type, stmt, code2, op2a, op2b); return canonicalize_bool (t, invert); } @@ -5885,7 +5963,7 @@ or_var_with_comparison (tree var, bool invert, Return NULL_EXPR if we can't simplify this to a single expression. */ static tree -or_var_with_comparison_1 (gimple *stmt, +or_var_with_comparison_1 (tree type, gimple *stmt, enum tree_code code2, tree op2a, tree op2b) { tree var = gimple_assign_lhs (stmt); @@ -5916,7 +5994,7 @@ or_var_with_comparison_1 (gimple *stmt, /* If the definition is a comparison, recurse on it. */ if (TREE_CODE_CLASS (innercode) == tcc_comparison) { - tree t = or_comparisons_1 (innercode, + tree t = or_comparisons_1 (type, innercode, gimple_assign_rhs1 (stmt), gimple_assign_rhs2 (stmt), code2, @@ -5952,18 +6030,20 @@ or_var_with_comparison_1 (gimple *stmt, else if (inner1 == false_test_var) return (is_or ? boolean_true_node - : or_var_with_comparison (inner2, false, code2, op2a, op2b)); + : or_var_with_comparison (type, inner2, false, code2, op2a, + op2b)); else if (inner2 == false_test_var) return (is_or ? boolean_true_node - : or_var_with_comparison (inner1, false, code2, op2a, op2b)); + : or_var_with_comparison (type, inner1, false, code2, op2a, + op2b)); /* Next, redistribute/reassociate the OR across the inner tests. Compute the first partial result, (inner1 OR (op2a code op2b)) */ if (TREE_CODE (inner1) == SSA_NAME && is_gimple_assign (s = SSA_NAME_DEF_STMT (inner1)) && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison - && (t = maybe_fold_or_comparisons (gimple_assign_rhs_code (s), + && (t = maybe_fold_or_comparisons (type, gimple_assign_rhs_code (s), gimple_assign_rhs1 (s), gimple_assign_rhs2 (s), code2, op2a, op2b))) @@ -5995,7 +6075,7 @@ or_var_with_comparison_1 (gimple *stmt, if (TREE_CODE (inner2) == SSA_NAME && is_gimple_assign (s = SSA_NAME_DEF_STMT (inner2)) && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison - && (t = maybe_fold_or_comparisons (gimple_assign_rhs_code (s), + && (t = maybe_fold_or_comparisons (type, gimple_assign_rhs_code (s), gimple_assign_rhs1 (s), gimple_assign_rhs2 (s), code2, op2a, op2b))) @@ -6052,7 +6132,7 @@ or_var_with_comparison_1 (gimple *stmt, in the first comparison but not the second. */ static tree -or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, +or_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b, enum tree_code code2, tree op2a, tree op2b) { tree truth_type = truth_type_for (TREE_TYPE (op1a)); @@ -6226,7 +6306,8 @@ or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, { case GIMPLE_ASSIGN: /* Try to simplify by copy-propagating the definition. */ - return or_var_with_comparison (op1a, invert, code2, op2a, op2b); + return or_var_with_comparison (type, op1a, invert, code2, op2a, + op2b); case GIMPLE_PHI: /* If every argument to the PHI produces the same result when @@ -6276,7 +6357,7 @@ or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, gimple_bb (def_stmt), gimple_bb (stmt))) return NULL_TREE; - temp = or_var_with_comparison (arg, invert, code2, + temp = or_var_with_comparison (type, arg, invert, code2, op2a, op2b); if (!temp) return NULL_TREE; @@ -6306,16 +6387,23 @@ or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, If the result expression is non-null, it has boolean type. */ tree -maybe_fold_or_comparisons (enum tree_code code1, tree op1a, tree op1b, +maybe_fold_or_comparisons (tree type, + enum tree_code code1, tree op1a, tree op1b, enum tree_code code2, tree op2a, tree op2b) { - tree t = or_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b); - if (t) + if (tree t = or_comparisons_1 (type, code1, op1a, op1b, code2, op2a, op2b)) return t; - else - return or_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b); -} + if (tree t = or_comparisons_1 (type, code2, op2a, op2b, code1, op1a, op1b)) + return t; + + if (tree t = maybe_fold_comparisons_from_match_pd (type, BIT_IOR_EXPR, code1, + op1a, op1b, code2, op2a, + op2b)) + return t; + + return NULL_TREE; +} /* Fold STMT to a constant using VALUEIZE to valueize SSA names. |