This extends folding to take an optional gimplifier (not a fan of the name
but it's what it was called before) to use during folding.
This allows you to specify which .pd file should be used during the fold.
Bootstrapped Regtested on aarch64-none-linux-gnu,
arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
-m32, -m64 and no issues.
Ok for master?
Thanks,
Tamar
gcc/ChangeLog:
* gimple-fold.cc (fold_stmt_1): Pass gimplifier along.
(fold_stmt): New.
(fold_stmt_inplace): Pass gimplifier along.
(and_comparisons_1, and_var_with_comparison, and_var_with_comparison_1,
or_comparisons_1, or_var_with_comparison, or_var_with_comparison_1,
(maybe_fold_comparisons_from_match_pd): Likewise.
(maybe_fold_or_comparisons): Likewise.
(maybe_fold_and_comparisons): New.
(gimple_fold_stmt_to_constant_1): New.
* gimple-fold.h (fold_stmt_inplace, fold_stmt): New.
(maybe_fold_and_comparisons, gimple_fold_stmt_to_constant_1): New.
---
diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index
d1da1f00f0fed7765c8785158a915cb9bb3c88c0..b642cd25c773b29076e0711b215d0b32d11ceef9
100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -6774,7 +6774,7 @@ maybe_canonicalize_mem_ref_addr (tree *t, bool is_debug =
false)
static bool
fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree),
- bitmap dce_worklist = nullptr)
+ gimple_match_simplify_fn simplifier, bitmap dce_worklist = nullptr)
{
bool changed = false;
gimple *stmt = gsi_stmt (*gsi);
@@ -6937,7 +6937,7 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace,
tree (*valueize) (tree),
{
gimple_seq seq = NULL;
gimple_match_op res_op;
- res_op.set_simplifier (gimple_simplify);
+ res_op.set_simplifier (simplifier);
if (gimple_simplify (stmt, &res_op, inplace ? NULL : &seq,
valueize, valueize)
&& replace_stmt_with_simplification (gsi, &res_op, &seq, inplace,
@@ -7094,13 +7094,28 @@ follow_all_ssa_edges (tree val)
bool
fold_stmt (gimple_stmt_iterator *gsi, bitmap dce_bitmap)
{
- return fold_stmt_1 (gsi, false, no_follow_ssa_edges, dce_bitmap);
+ return fold_stmt (gsi, gimple_simplify,dce_bitmap);
}
bool
fold_stmt (gimple_stmt_iterator *gsi, tree (*valueize) (tree), bitmap
dce_bitmap)
{
- return fold_stmt_1 (gsi, false, valueize, dce_bitmap);
+ return fold_stmt (gsi, valueize, gimple_simplify, dce_bitmap);
+}
+
+bool
+fold_stmt (gimple_stmt_iterator *gsi, gimple_match_simplify_fn simplifier,
+ bitmap dce_bitmap)
+{
+ return fold_stmt_1 (gsi, false, no_follow_ssa_edges, simplifier,
+ dce_bitmap);
+}
+
+bool
+fold_stmt (gimple_stmt_iterator *gsi, tree (*valueize) (tree),
+ gimple_match_simplify_fn simplifier, bitmap dce_bitmap)
+{
+ return fold_stmt_1 (gsi, false, valueize, simplifier, dce_bitmap);
}
/* Perform the minimal folding on statement *GSI. Only operations like
@@ -7112,10 +7127,11 @@ fold_stmt (gimple_stmt_iterator *gsi, tree (*valueize)
(tree), bitmap dce_bitmap
which can produce *&x = 0. */
bool
-fold_stmt_inplace (gimple_stmt_iterator *gsi, tree (*valueize) (tree))
+fold_stmt_inplace (gimple_stmt_iterator *gsi, tree (*valueize) (tree),
+ gimple_match_simplify_fn simplifier)
{
gimple *stmt = gsi_stmt (*gsi);
- bool changed = fold_stmt_1 (gsi, true, valueize);
+ bool changed = fold_stmt_1 (gsi, true, valueize, simplifier);
gcc_assert (gsi_stmt (*gsi) == stmt);
return changed;
}
@@ -7257,27 +7273,28 @@ same_bool_result_p (const_tree op1, const_tree op2)
static tree
and_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b,
- enum tree_code code2, tree op2a, tree op2b, basic_block);
+ enum tree_code code2, tree op2a, tree op2b, basic_block,
+ gimple_match_simplify_fn);
static tree
and_var_with_comparison (tree type, tree var, bool invert,
enum tree_code code2, tree op2a, tree op2b,
- basic_block);
+ basic_block, gimple_match_simplify_fn);
static tree
and_var_with_comparison_1 (tree type, gimple *stmt,
enum tree_code code2, tree op2a, tree op2b,
- basic_block);
+ basic_block, gimple_match_simplify_fn);
static tree
or_comparisons_1 (tree, enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b,
- basic_block);
+ basic_block, gimple_match_simplify_fn);
static tree
or_var_with_comparison (tree, tree var, bool invert,
enum tree_code code2, tree op2a, tree op2b,
- basic_block);
+ basic_block, gimple_match_simplify_fn);
static tree
or_var_with_comparison_1 (tree, gimple *stmt,
enum tree_code code2, tree op2a, tree op2b,
- basic_block);
+ basic_block, gimple_match_simplify_fn);
/* Helper function for and_comparisons_1: try to simplify the AND of the
ssa variable VAR with the comparison specified by (OP2A CODE2 OP2B).
@@ -7287,7 +7304,8 @@ or_var_with_comparison_1 (tree, gimple *stmt,
static tree
and_var_with_comparison (tree type, tree var, bool invert,
enum tree_code code2, tree op2a, tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
tree t;
gimple *stmt = SSA_NAME_DEF_STMT (var);
@@ -7302,10 +7320,10 @@ and_var_with_comparison (tree type, tree var, bool
invert,
if (invert)
t = or_var_with_comparison_1 (type, stmt,
invert_tree_comparison (code2, false),
- op2a, op2b, outer_cond_bb);
+ op2a, op2b, outer_cond_bb, simplifier);
else
t = and_var_with_comparison_1 (type, stmt, code2, op2a, op2b,
- outer_cond_bb);
+ outer_cond_bb, simplifier);
return canonicalize_bool (t, invert);
}
@@ -7316,7 +7334,8 @@ and_var_with_comparison (tree type, tree var, bool invert,
static tree
and_var_with_comparison_1 (tree type, gimple *stmt,
enum tree_code code2, tree op2a, tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
tree var = gimple_assign_lhs (stmt);
tree true_test_var = NULL_TREE;
@@ -7351,7 +7370,7 @@ and_var_with_comparison_1 (tree type, gimple *stmt,
gimple_assign_rhs2 (stmt),
code2,
op2a,
- op2b, outer_cond_bb);
+ op2b, outer_cond_bb, simplifier);
if (t)
return t;
}
@@ -7383,12 +7402,12 @@ and_var_with_comparison_1 (tree type, gimple *stmt,
return (is_and
? boolean_false_node
: and_var_with_comparison (type, inner2, false, code2, op2a,
- op2b, outer_cond_bb));
+ op2b, outer_cond_bb, simplifier));
else if (inner2 == false_test_var)
return (is_and
? boolean_false_node
: and_var_with_comparison (type, inner1, false, code2, op2a,
- op2b, outer_cond_bb));
+ op2b, outer_cond_bb, simplifier));
/* Next, redistribute/reassociate the AND across the inner tests.
Compute the first partial result, (inner1 AND (op2a code op2b)) */
@@ -7399,7 +7418,8 @@ and_var_with_comparison_1 (tree type, gimple *stmt,
gimple_assign_rhs1 (s),
gimple_assign_rhs2 (s),
code2, op2a, op2b,
- outer_cond_bb)))
+ outer_cond_bb,
+ simplifier)))
{
/* Handle the AND case, where we are reassociating:
(inner1 AND inner2) AND (op2a code2 op2b)
@@ -7432,7 +7452,8 @@ and_var_with_comparison_1 (tree type, gimple *stmt,
gimple_assign_rhs1 (s),
gimple_assign_rhs2 (s),
code2, op2a, op2b,
- outer_cond_bb)))
+ outer_cond_bb,
+ simplifier)))
{
/* Handle the AND case, where we are reassociating:
(inner1 AND inner2) AND (op2a code2 op2b)
@@ -7487,7 +7508,8 @@ and_var_with_comparison_1 (tree type, gimple *stmt,
static tree
and_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
tree truth_type = truth_type_for (TREE_TYPE (op1a));
@@ -7531,7 +7553,7 @@ and_comparisons_1 (tree type, enum tree_code code1, tree
op1a, tree op1b,
case GIMPLE_ASSIGN:
/* Try to simplify by copy-propagating the definition. */
return and_var_with_comparison (type, op1a, invert, code2, op2a,
- op2b, outer_cond_bb);
+ op2b, outer_cond_bb, simplifier);
case GIMPLE_PHI:
/* If every argument to the PHI produces the same result when
@@ -7583,7 +7605,8 @@ and_comparisons_1 (tree type, enum tree_code code1, tree
op1a, tree op1b,
return NULL_TREE;
temp = and_var_with_comparison (type, arg, invert, code2,
op2a, op2b,
- outer_cond_bb);
+ outer_cond_bb,
+ simplifier);
if (!temp)
return NULL_TREE;
else if (!result)
@@ -7648,7 +7671,8 @@ maybe_fold_comparisons_from_match_pd (tree type, enum
tree_code code,
tree op1a, tree op1b,
enum tree_code code2, tree op2a,
tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
/* Allocate gimple stmt1 on the stack. */
gassign *stmt1
@@ -7690,6 +7714,7 @@ maybe_fold_comparisons_from_match_pd (tree type, enum
tree_code code,
gimple_match_op op (gimple_match_cond::UNCOND, code,
type, gimple_assign_lhs (stmt1),
gimple_assign_lhs (stmt2));
+ op.set_simplifier (simplifier);
fosa_bb = outer_cond_bb;
auto_vec<std::pair<tree, flow_sensitive_info_storage>, 8> unwind_stack;
fosa_unwind = &unwind_stack;
@@ -9203,19 +9228,21 @@ tree
maybe_fold_and_comparisons (tree type,
enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
if (tree t = and_comparisons_1 (type, code1, op1a, op1b, code2, op2a, op2b,
- outer_cond_bb))
+ outer_cond_bb, simplifier))
return t;
if (tree t = and_comparisons_1 (type, code2, op2a, op2b, code1, op1a, op1b,
- outer_cond_bb))
+ outer_cond_bb, simplifier))
return t;
if (tree t = maybe_fold_comparisons_from_match_pd (type, BIT_AND_EXPR, code1,
op1a, op1b, code2, op2a,
- op2b, outer_cond_bb))
+ op2b, outer_cond_bb,
+ simplifier))
return t;
return NULL_TREE;
@@ -9229,7 +9256,8 @@ maybe_fold_and_comparisons (tree type,
static tree
or_var_with_comparison (tree type, tree var, bool invert,
enum tree_code code2, tree op2a, tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
tree t;
gimple *stmt = SSA_NAME_DEF_STMT (var);
@@ -9244,10 +9272,10 @@ or_var_with_comparison (tree type, tree var, bool
invert,
if (invert)
t = and_var_with_comparison_1 (type, stmt,
invert_tree_comparison (code2, false),
- op2a, op2b, outer_cond_bb);
+ op2a, op2b, outer_cond_bb, simplifier);
else
t = or_var_with_comparison_1 (type, stmt, code2, op2a, op2b,
- outer_cond_bb);
+ outer_cond_bb, simplifier);
return canonicalize_bool (t, invert);
}
@@ -9258,7 +9286,8 @@ or_var_with_comparison (tree type, tree var, bool invert,
static tree
or_var_with_comparison_1 (tree type, gimple *stmt,
enum tree_code code2, tree op2a, tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
tree var = gimple_assign_lhs (stmt);
tree true_test_var = NULL_TREE;
@@ -9291,7 +9320,8 @@ or_var_with_comparison_1 (tree type, gimple *stmt,
tree t = or_comparisons_1 (type, innercode,
gimple_assign_rhs1 (stmt),
gimple_assign_rhs2 (stmt),
- code2, op2a, op2b, outer_cond_bb);
+ code2, op2a, op2b, outer_cond_bb,
+ simplifier);
if (t)
return t;
}
@@ -9323,12 +9353,12 @@ or_var_with_comparison_1 (tree type, gimple *stmt,
return (is_or
? boolean_true_node
: or_var_with_comparison (type, inner2, false, code2, op2a,
- op2b, outer_cond_bb));
+ op2b, outer_cond_bb, simplifier));
else if (inner2 == false_test_var)
return (is_or
? boolean_true_node
: or_var_with_comparison (type, inner1, false, code2, op2a,
- op2b, outer_cond_bb));
+ op2b, outer_cond_bb, simplifier));
/* Next, redistribute/reassociate the OR across the inner tests.
Compute the first partial result, (inner1 OR (op2a code op2b)) */
@@ -9339,7 +9369,8 @@ or_var_with_comparison_1 (tree type, gimple *stmt,
gimple_assign_rhs1 (s),
gimple_assign_rhs2 (s),
code2, op2a, op2b,
- outer_cond_bb)))
+ outer_cond_bb,
+ simplifier)))
{
/* Handle the OR case, where we are reassociating:
(inner1 OR inner2) OR (op2a code2 op2b)
@@ -9372,7 +9403,8 @@ or_var_with_comparison_1 (tree type, gimple *stmt,
gimple_assign_rhs1 (s),
gimple_assign_rhs2 (s),
code2, op2a, op2b,
- outer_cond_bb)))
+ outer_cond_bb,
+ simplifier)))
{
/* Handle the OR case, where we are reassociating:
(inner1 OR inner2) OR (op2a code2 op2b)
@@ -9428,7 +9460,8 @@ or_var_with_comparison_1 (tree type, gimple *stmt,
static tree
or_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
tree truth_type = truth_type_for (TREE_TYPE (op1a));
@@ -9472,7 +9505,7 @@ or_comparisons_1 (tree type, enum tree_code code1, tree
op1a, tree op1b,
case GIMPLE_ASSIGN:
/* Try to simplify by copy-propagating the definition. */
return or_var_with_comparison (type, op1a, invert, code2, op2a,
- op2b, outer_cond_bb);
+ op2b, outer_cond_bb, simplifier);
case GIMPLE_PHI:
/* If every argument to the PHI produces the same result when
@@ -9523,7 +9556,8 @@ or_comparisons_1 (tree type, enum tree_code code1, tree
op1a, tree op1b,
gimple_bb (stmt)))
return NULL_TREE;
temp = or_var_with_comparison (type, arg, invert, code2,
- op2a, op2b, outer_cond_bb);
+ op2a, op2b, outer_cond_bb,
+ simplifier);
if (!temp)
return NULL_TREE;
else if (!result)
@@ -9555,19 +9589,21 @@ tree
maybe_fold_or_comparisons (tree type,
enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
if (tree t = or_comparisons_1 (type, code1, op1a, op1b, code2, op2a, op2b,
- outer_cond_bb))
+ outer_cond_bb, simplifier))
return t;
if (tree t = or_comparisons_1 (type, code2, op2a, op2b, code1, op1a, op1b,
- outer_cond_bb))
+ outer_cond_bb, simplifier))
return t;
if (tree t = maybe_fold_comparisons_from_match_pd (type, BIT_IOR_EXPR, code1,
op1a, op1b, code2, op2a,
- op2b, outer_cond_bb))
+ op2b, outer_cond_bb,
+ simplifier))
return t;
return NULL_TREE;
@@ -9584,10 +9620,11 @@ maybe_fold_or_comparisons (tree type,
tree
gimple_fold_stmt_to_constant_1 (gimple *stmt, tree (*valueize) (tree),
- tree (*gvalueize) (tree))
+ tree (*gvalueize) (tree),
+ gimple_match_simplify_fn simplifier)
{
gimple_match_op res_op;
- res_op.set_simplifier (gimple_simplify);
+ res_op.set_simplifier (simplifier);
/* ??? 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
diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h
index
ca7519c4c8904127ad5a80e1d39101550b397d91..211f8901461fe6dc20864cd9ba8c9277ff19dc99
100644
--- a/gcc/gimple-fold.h
+++ b/gcc/gimple-fold.h
@@ -36,17 +36,27 @@ extern tree follow_single_use_edges (tree);
extern tree follow_all_ssa_edges (tree);
extern bool fold_stmt (gimple_stmt_iterator *, bitmap = nullptr);
extern bool fold_stmt (gimple_stmt_iterator *, tree (*) (tree), bitmap =
nullptr);
-extern bool fold_stmt_inplace (gimple_stmt_iterator *, tree (*) (tree) =
no_follow_ssa_edges);
+extern bool fold_stmt (gimple_stmt_iterator *,
+ gimple_match_simplify_fn, bitmap = nullptr);
+extern bool fold_stmt (gimple_stmt_iterator *, tree (*) (tree),
+ gimple_match_simplify_fn, bitmap = nullptr);
+extern bool fold_stmt_inplace (gimple_stmt_iterator *,
+ tree (*) (tree) = no_follow_ssa_edges,
+ gimple_match_simplify_fn = gimple_simplify);
extern tree maybe_fold_and_comparisons (tree, enum tree_code, tree, tree,
enum tree_code, tree, tree,
- basic_block = nullptr);
+ basic_block = nullptr,
+ gimple_match_simplify_fn =
gimple_simplify);
extern tree maybe_fold_or_comparisons (tree, enum tree_code, tree, tree,
enum tree_code, tree, tree,
- basic_block = nullptr);
+ basic_block = nullptr,
+ gimple_match_simplify_fn =
gimple_simplify);
extern bool optimize_atomic_compare_exchange_p (gimple *);
extern void fold_builtin_atomic_compare_exchange (gimple_stmt_iterator *);
extern tree gimple_fold_stmt_to_constant_1 (gimple *, tree (*) (tree),
- tree (*) (tree) =
no_follow_ssa_edges);
+ tree (*) (tree) =
no_follow_ssa_edges,
+ gimple_match_simplify_fn
+ = gimple_simplify);
extern tree gimple_fold_stmt_to_constant (gimple *, tree (*) (tree));
extern tree fold_ctor_reference (tree, tree, const poly_uint64&,
const poly_uint64&, tree,
--
diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index d1da1f00f0fed7765c8785158a915cb9bb3c88c0..b642cd25c773b29076e0711b215d0b32d11ceef9 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -6774,7 +6774,7 @@ maybe_canonicalize_mem_ref_addr (tree *t, bool is_debug = false)
static bool
fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree),
- bitmap dce_worklist = nullptr)
+ gimple_match_simplify_fn simplifier, bitmap dce_worklist = nullptr)
{
bool changed = false;
gimple *stmt = gsi_stmt (*gsi);
@@ -6937,7 +6937,7 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree),
{
gimple_seq seq = NULL;
gimple_match_op res_op;
- res_op.set_simplifier (gimple_simplify);
+ res_op.set_simplifier (simplifier);
if (gimple_simplify (stmt, &res_op, inplace ? NULL : &seq,
valueize, valueize)
&& replace_stmt_with_simplification (gsi, &res_op, &seq, inplace,
@@ -7094,13 +7094,28 @@ follow_all_ssa_edges (tree val)
bool
fold_stmt (gimple_stmt_iterator *gsi, bitmap dce_bitmap)
{
- return fold_stmt_1 (gsi, false, no_follow_ssa_edges, dce_bitmap);
+ return fold_stmt (gsi, gimple_simplify,dce_bitmap);
}
bool
fold_stmt (gimple_stmt_iterator *gsi, tree (*valueize) (tree), bitmap dce_bitmap)
{
- return fold_stmt_1 (gsi, false, valueize, dce_bitmap);
+ return fold_stmt (gsi, valueize, gimple_simplify, dce_bitmap);
+}
+
+bool
+fold_stmt (gimple_stmt_iterator *gsi, gimple_match_simplify_fn simplifier,
+ bitmap dce_bitmap)
+{
+ return fold_stmt_1 (gsi, false, no_follow_ssa_edges, simplifier,
+ dce_bitmap);
+}
+
+bool
+fold_stmt (gimple_stmt_iterator *gsi, tree (*valueize) (tree),
+ gimple_match_simplify_fn simplifier, bitmap dce_bitmap)
+{
+ return fold_stmt_1 (gsi, false, valueize, simplifier, dce_bitmap);
}
/* Perform the minimal folding on statement *GSI. Only operations like
@@ -7112,10 +7127,11 @@ fold_stmt (gimple_stmt_iterator *gsi, tree (*valueize) (tree), bitmap dce_bitmap
which can produce *&x = 0. */
bool
-fold_stmt_inplace (gimple_stmt_iterator *gsi, tree (*valueize) (tree))
+fold_stmt_inplace (gimple_stmt_iterator *gsi, tree (*valueize) (tree),
+ gimple_match_simplify_fn simplifier)
{
gimple *stmt = gsi_stmt (*gsi);
- bool changed = fold_stmt_1 (gsi, true, valueize);
+ bool changed = fold_stmt_1 (gsi, true, valueize, simplifier);
gcc_assert (gsi_stmt (*gsi) == stmt);
return changed;
}
@@ -7257,27 +7273,28 @@ same_bool_result_p (const_tree op1, const_tree op2)
static tree
and_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b,
- enum tree_code code2, tree op2a, tree op2b, basic_block);
+ enum tree_code code2, tree op2a, tree op2b, basic_block,
+ gimple_match_simplify_fn);
static tree
and_var_with_comparison (tree type, tree var, bool invert,
enum tree_code code2, tree op2a, tree op2b,
- basic_block);
+ basic_block, gimple_match_simplify_fn);
static tree
and_var_with_comparison_1 (tree type, gimple *stmt,
enum tree_code code2, tree op2a, tree op2b,
- basic_block);
+ basic_block, gimple_match_simplify_fn);
static tree
or_comparisons_1 (tree, enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b,
- basic_block);
+ basic_block, gimple_match_simplify_fn);
static tree
or_var_with_comparison (tree, tree var, bool invert,
enum tree_code code2, tree op2a, tree op2b,
- basic_block);
+ basic_block, gimple_match_simplify_fn);
static tree
or_var_with_comparison_1 (tree, gimple *stmt,
enum tree_code code2, tree op2a, tree op2b,
- basic_block);
+ basic_block, gimple_match_simplify_fn);
/* Helper function for and_comparisons_1: try to simplify the AND of the
ssa variable VAR with the comparison specified by (OP2A CODE2 OP2B).
@@ -7287,7 +7304,8 @@ or_var_with_comparison_1 (tree, gimple *stmt,
static tree
and_var_with_comparison (tree type, tree var, bool invert,
enum tree_code code2, tree op2a, tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
tree t;
gimple *stmt = SSA_NAME_DEF_STMT (var);
@@ -7302,10 +7320,10 @@ and_var_with_comparison (tree type, tree var, bool invert,
if (invert)
t = or_var_with_comparison_1 (type, stmt,
invert_tree_comparison (code2, false),
- op2a, op2b, outer_cond_bb);
+ op2a, op2b, outer_cond_bb, simplifier);
else
t = and_var_with_comparison_1 (type, stmt, code2, op2a, op2b,
- outer_cond_bb);
+ outer_cond_bb, simplifier);
return canonicalize_bool (t, invert);
}
@@ -7316,7 +7334,8 @@ and_var_with_comparison (tree type, tree var, bool invert,
static tree
and_var_with_comparison_1 (tree type, gimple *stmt,
enum tree_code code2, tree op2a, tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
tree var = gimple_assign_lhs (stmt);
tree true_test_var = NULL_TREE;
@@ -7351,7 +7370,7 @@ and_var_with_comparison_1 (tree type, gimple *stmt,
gimple_assign_rhs2 (stmt),
code2,
op2a,
- op2b, outer_cond_bb);
+ op2b, outer_cond_bb, simplifier);
if (t)
return t;
}
@@ -7383,12 +7402,12 @@ and_var_with_comparison_1 (tree type, gimple *stmt,
return (is_and
? boolean_false_node
: and_var_with_comparison (type, inner2, false, code2, op2a,
- op2b, outer_cond_bb));
+ op2b, outer_cond_bb, simplifier));
else if (inner2 == false_test_var)
return (is_and
? boolean_false_node
: and_var_with_comparison (type, inner1, false, code2, op2a,
- op2b, outer_cond_bb));
+ op2b, outer_cond_bb, simplifier));
/* Next, redistribute/reassociate the AND across the inner tests.
Compute the first partial result, (inner1 AND (op2a code op2b)) */
@@ -7399,7 +7418,8 @@ and_var_with_comparison_1 (tree type, gimple *stmt,
gimple_assign_rhs1 (s),
gimple_assign_rhs2 (s),
code2, op2a, op2b,
- outer_cond_bb)))
+ outer_cond_bb,
+ simplifier)))
{
/* Handle the AND case, where we are reassociating:
(inner1 AND inner2) AND (op2a code2 op2b)
@@ -7432,7 +7452,8 @@ and_var_with_comparison_1 (tree type, gimple *stmt,
gimple_assign_rhs1 (s),
gimple_assign_rhs2 (s),
code2, op2a, op2b,
- outer_cond_bb)))
+ outer_cond_bb,
+ simplifier)))
{
/* Handle the AND case, where we are reassociating:
(inner1 AND inner2) AND (op2a code2 op2b)
@@ -7487,7 +7508,8 @@ and_var_with_comparison_1 (tree type, gimple *stmt,
static tree
and_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
tree truth_type = truth_type_for (TREE_TYPE (op1a));
@@ -7531,7 +7553,7 @@ and_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b,
case GIMPLE_ASSIGN:
/* Try to simplify by copy-propagating the definition. */
return and_var_with_comparison (type, op1a, invert, code2, op2a,
- op2b, outer_cond_bb);
+ op2b, outer_cond_bb, simplifier);
case GIMPLE_PHI:
/* If every argument to the PHI produces the same result when
@@ -7583,7 +7605,8 @@ and_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b,
return NULL_TREE;
temp = and_var_with_comparison (type, arg, invert, code2,
op2a, op2b,
- outer_cond_bb);
+ outer_cond_bb,
+ simplifier);
if (!temp)
return NULL_TREE;
else if (!result)
@@ -7648,7 +7671,8 @@ maybe_fold_comparisons_from_match_pd (tree type, enum tree_code code,
tree op1a, tree op1b,
enum tree_code code2, tree op2a,
tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
/* Allocate gimple stmt1 on the stack. */
gassign *stmt1
@@ -7690,6 +7714,7 @@ maybe_fold_comparisons_from_match_pd (tree type, enum tree_code code,
gimple_match_op op (gimple_match_cond::UNCOND, code,
type, gimple_assign_lhs (stmt1),
gimple_assign_lhs (stmt2));
+ op.set_simplifier (simplifier);
fosa_bb = outer_cond_bb;
auto_vec<std::pair<tree, flow_sensitive_info_storage>, 8> unwind_stack;
fosa_unwind = &unwind_stack;
@@ -9203,19 +9228,21 @@ tree
maybe_fold_and_comparisons (tree type,
enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
if (tree t = and_comparisons_1 (type, code1, op1a, op1b, code2, op2a, op2b,
- outer_cond_bb))
+ outer_cond_bb, simplifier))
return t;
if (tree t = and_comparisons_1 (type, code2, op2a, op2b, code1, op1a, op1b,
- outer_cond_bb))
+ outer_cond_bb, simplifier))
return t;
if (tree t = maybe_fold_comparisons_from_match_pd (type, BIT_AND_EXPR, code1,
op1a, op1b, code2, op2a,
- op2b, outer_cond_bb))
+ op2b, outer_cond_bb,
+ simplifier))
return t;
return NULL_TREE;
@@ -9229,7 +9256,8 @@ maybe_fold_and_comparisons (tree type,
static tree
or_var_with_comparison (tree type, tree var, bool invert,
enum tree_code code2, tree op2a, tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
tree t;
gimple *stmt = SSA_NAME_DEF_STMT (var);
@@ -9244,10 +9272,10 @@ or_var_with_comparison (tree type, tree var, bool invert,
if (invert)
t = and_var_with_comparison_1 (type, stmt,
invert_tree_comparison (code2, false),
- op2a, op2b, outer_cond_bb);
+ op2a, op2b, outer_cond_bb, simplifier);
else
t = or_var_with_comparison_1 (type, stmt, code2, op2a, op2b,
- outer_cond_bb);
+ outer_cond_bb, simplifier);
return canonicalize_bool (t, invert);
}
@@ -9258,7 +9286,8 @@ or_var_with_comparison (tree type, tree var, bool invert,
static tree
or_var_with_comparison_1 (tree type, gimple *stmt,
enum tree_code code2, tree op2a, tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
tree var = gimple_assign_lhs (stmt);
tree true_test_var = NULL_TREE;
@@ -9291,7 +9320,8 @@ or_var_with_comparison_1 (tree type, gimple *stmt,
tree t = or_comparisons_1 (type, innercode,
gimple_assign_rhs1 (stmt),
gimple_assign_rhs2 (stmt),
- code2, op2a, op2b, outer_cond_bb);
+ code2, op2a, op2b, outer_cond_bb,
+ simplifier);
if (t)
return t;
}
@@ -9323,12 +9353,12 @@ or_var_with_comparison_1 (tree type, gimple *stmt,
return (is_or
? boolean_true_node
: or_var_with_comparison (type, inner2, false, code2, op2a,
- op2b, outer_cond_bb));
+ op2b, outer_cond_bb, simplifier));
else if (inner2 == false_test_var)
return (is_or
? boolean_true_node
: or_var_with_comparison (type, inner1, false, code2, op2a,
- op2b, outer_cond_bb));
+ op2b, outer_cond_bb, simplifier));
/* Next, redistribute/reassociate the OR across the inner tests.
Compute the first partial result, (inner1 OR (op2a code op2b)) */
@@ -9339,7 +9369,8 @@ or_var_with_comparison_1 (tree type, gimple *stmt,
gimple_assign_rhs1 (s),
gimple_assign_rhs2 (s),
code2, op2a, op2b,
- outer_cond_bb)))
+ outer_cond_bb,
+ simplifier)))
{
/* Handle the OR case, where we are reassociating:
(inner1 OR inner2) OR (op2a code2 op2b)
@@ -9372,7 +9403,8 @@ or_var_with_comparison_1 (tree type, gimple *stmt,
gimple_assign_rhs1 (s),
gimple_assign_rhs2 (s),
code2, op2a, op2b,
- outer_cond_bb)))
+ outer_cond_bb,
+ simplifier)))
{
/* Handle the OR case, where we are reassociating:
(inner1 OR inner2) OR (op2a code2 op2b)
@@ -9428,7 +9460,8 @@ or_var_with_comparison_1 (tree type, gimple *stmt,
static tree
or_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
tree truth_type = truth_type_for (TREE_TYPE (op1a));
@@ -9472,7 +9505,7 @@ or_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b,
case GIMPLE_ASSIGN:
/* Try to simplify by copy-propagating the definition. */
return or_var_with_comparison (type, op1a, invert, code2, op2a,
- op2b, outer_cond_bb);
+ op2b, outer_cond_bb, simplifier);
case GIMPLE_PHI:
/* If every argument to the PHI produces the same result when
@@ -9523,7 +9556,8 @@ or_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b,
gimple_bb (stmt)))
return NULL_TREE;
temp = or_var_with_comparison (type, arg, invert, code2,
- op2a, op2b, outer_cond_bb);
+ op2a, op2b, outer_cond_bb,
+ simplifier);
if (!temp)
return NULL_TREE;
else if (!result)
@@ -9555,19 +9589,21 @@ tree
maybe_fold_or_comparisons (tree type,
enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b,
- basic_block outer_cond_bb)
+ basic_block outer_cond_bb,
+ gimple_match_simplify_fn simplifier)
{
if (tree t = or_comparisons_1 (type, code1, op1a, op1b, code2, op2a, op2b,
- outer_cond_bb))
+ outer_cond_bb, simplifier))
return t;
if (tree t = or_comparisons_1 (type, code2, op2a, op2b, code1, op1a, op1b,
- outer_cond_bb))
+ outer_cond_bb, simplifier))
return t;
if (tree t = maybe_fold_comparisons_from_match_pd (type, BIT_IOR_EXPR, code1,
op1a, op1b, code2, op2a,
- op2b, outer_cond_bb))
+ op2b, outer_cond_bb,
+ simplifier))
return t;
return NULL_TREE;
@@ -9584,10 +9620,11 @@ maybe_fold_or_comparisons (tree type,
tree
gimple_fold_stmt_to_constant_1 (gimple *stmt, tree (*valueize) (tree),
- tree (*gvalueize) (tree))
+ tree (*gvalueize) (tree),
+ gimple_match_simplify_fn simplifier)
{
gimple_match_op res_op;
- res_op.set_simplifier (gimple_simplify);
+ res_op.set_simplifier (simplifier);
/* ??? 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
diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h
index ca7519c4c8904127ad5a80e1d39101550b397d91..211f8901461fe6dc20864cd9ba8c9277ff19dc99 100644
--- a/gcc/gimple-fold.h
+++ b/gcc/gimple-fold.h
@@ -36,17 +36,27 @@ extern tree follow_single_use_edges (tree);
extern tree follow_all_ssa_edges (tree);
extern bool fold_stmt (gimple_stmt_iterator *, bitmap = nullptr);
extern bool fold_stmt (gimple_stmt_iterator *, tree (*) (tree), bitmap = nullptr);
-extern bool fold_stmt_inplace (gimple_stmt_iterator *, tree (*) (tree) = no_follow_ssa_edges);
+extern bool fold_stmt (gimple_stmt_iterator *,
+ gimple_match_simplify_fn, bitmap = nullptr);
+extern bool fold_stmt (gimple_stmt_iterator *, tree (*) (tree),
+ gimple_match_simplify_fn, bitmap = nullptr);
+extern bool fold_stmt_inplace (gimple_stmt_iterator *,
+ tree (*) (tree) = no_follow_ssa_edges,
+ gimple_match_simplify_fn = gimple_simplify);
extern tree maybe_fold_and_comparisons (tree, enum tree_code, tree, tree,
enum tree_code, tree, tree,
- basic_block = nullptr);
+ basic_block = nullptr,
+ gimple_match_simplify_fn = gimple_simplify);
extern tree maybe_fold_or_comparisons (tree, enum tree_code, tree, tree,
enum tree_code, tree, tree,
- basic_block = nullptr);
+ basic_block = nullptr,
+ gimple_match_simplify_fn = gimple_simplify);
extern bool optimize_atomic_compare_exchange_p (gimple *);
extern void fold_builtin_atomic_compare_exchange (gimple_stmt_iterator *);
extern tree gimple_fold_stmt_to_constant_1 (gimple *, tree (*) (tree),
- tree (*) (tree) = no_follow_ssa_edges);
+ tree (*) (tree) = no_follow_ssa_edges,
+ gimple_match_simplify_fn
+ = gimple_simplify);
extern tree gimple_fold_stmt_to_constant (gimple *, tree (*) (tree));
extern tree fold_ctor_reference (tree, tree, const poly_uint64&,
const poly_uint64&, tree,