aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-fold.c
diff options
context:
space:
mode:
authorLi Jia He <helijia@linux.ibm.com>2019-09-16 14:21:20 +0000
committerMartin Liska <marxin@gcc.gnu.org>2019-09-16 14:21:20 +0000
commit5f487a349de62613d7fa429bcbfbeeafbfc94f3a (patch)
treed63d3e1bb2210eb3e25095d2dc0deab2b5ccf72a /gcc/gimple-fold.c
parent10f30ac9cda947d117e50f0cbd4cf94ee70a944f (diff)
downloadgcc-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.c170
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.