static tree
and_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b,
- enum tree_code code2, tree op2a, tree op2b);
+ enum tree_code code2, tree op2a, tree op2b, basic_block);
static tree
and_var_with_comparison (tree type, tree var, bool invert,
- enum tree_code code2, tree op2a, tree op2b);
+ enum tree_code code2, tree op2a, tree op2b,
+ basic_block);
static tree
and_var_with_comparison_1 (tree type, gimple *stmt,
- enum tree_code code2, tree op2a, tree op2b);
+ enum tree_code code2, tree op2a, tree op2b,
+ basic_block);
static tree
or_comparisons_1 (tree, enum tree_code code1, tree op1a, tree op1b,
- enum tree_code code2, tree op2a, tree op2b);
+ enum tree_code code2, tree op2a, tree op2b,
+ basic_block);
static tree
or_var_with_comparison (tree, tree var, bool invert,
- enum tree_code code2, tree op2a, tree op2b);
+ enum tree_code code2, tree op2a, tree op2b,
+ basic_block);
static tree
or_var_with_comparison_1 (tree, gimple *stmt,
- enum tree_code code2, tree op2a, tree op2b);
+ enum tree_code code2, tree op2a, tree op2b,
+ basic_block);
/* Helper function for and_comparisons_1: try to simplify the AND of the
ssa variable VAR with the comparison specified by (OP2A CODE2 OP2B).
static tree
and_var_with_comparison (tree type, tree var, bool invert,
- enum tree_code code2, tree op2a, tree op2b)
+ enum tree_code code2, tree op2a, tree op2b,
+ basic_block outer_cond_bb)
{
tree t;
gimple *stmt = SSA_NAME_DEF_STMT (var);
if (invert)
t = or_var_with_comparison_1 (type, stmt,
invert_tree_comparison (code2, false),
- op2a, op2b);
+ op2a, op2b, outer_cond_bb);
else
- t = and_var_with_comparison_1 (type, stmt, code2, op2a, op2b);
+ t = and_var_with_comparison_1 (type, stmt, code2, op2a, op2b,
+ outer_cond_bb);
return canonicalize_bool (t, invert);
}
static tree
and_var_with_comparison_1 (tree type, gimple *stmt,
- enum tree_code code2, tree op2a, tree op2b)
+ enum tree_code code2, tree op2a, tree op2b,
+ basic_block outer_cond_bb)
{
tree var = gimple_assign_lhs (stmt);
tree true_test_var = NULL_TREE;
gimple_assign_rhs2 (stmt),
code2,
op2a,
- op2b);
+ op2b, outer_cond_bb);
if (t)
return t;
}
return (is_and
? boolean_false_node
: and_var_with_comparison (type, inner2, false, code2, op2a,
- op2b));
+ op2b, outer_cond_bb));
else if (inner2 == false_test_var)
return (is_and
? boolean_false_node
: and_var_with_comparison (type, inner1, false, code2, op2a,
- op2b));
+ op2b, outer_cond_bb));
/* Next, redistribute/reassociate the AND across the inner tests.
Compute the first partial result, (inner1 AND (op2a code op2b)) */
&& (t = maybe_fold_and_comparisons (type, gimple_assign_rhs_code (s),
gimple_assign_rhs1 (s),
gimple_assign_rhs2 (s),
- code2, op2a, op2b)))
+ code2, op2a, op2b,
+ outer_cond_bb)))
{
/* Handle the AND case, where we are reassociating:
(inner1 AND inner2) AND (op2a code2 op2b)
&& (t = maybe_fold_and_comparisons (type, gimple_assign_rhs_code (s),
gimple_assign_rhs1 (s),
gimple_assign_rhs2 (s),
- code2, op2a, op2b)))
+ code2, op2a, op2b,
+ outer_cond_bb)))
{
/* Handle the AND case, where we are reassociating:
(inner1 AND inner2) AND (op2a code2 op2b)
static tree
and_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b,
- enum tree_code code2, tree op2a, tree op2b)
+ enum tree_code code2, tree op2a, tree op2b,
+ basic_block outer_cond_bb)
{
tree truth_type = truth_type_for (TREE_TYPE (op1a));
case GIMPLE_ASSIGN:
/* Try to simplify by copy-propagating the definition. */
return and_var_with_comparison (type, op1a, invert, code2, op2a,
- op2b);
+ op2b, outer_cond_bb);
case GIMPLE_PHI:
/* If every argument to the PHI produces the same result when
gimple_bb (stmt)))
return NULL_TREE;
temp = and_var_with_comparison (type, arg, invert, code2,
- op2a, op2b);
+ op2a, op2b,
+ outer_cond_bb);
if (!temp)
return NULL_TREE;
else if (!result)
return NULL_TREE;
}
+static basic_block fosa_bb;
+static tree
+follow_outer_ssa_edges (tree val)
+{
+ if (TREE_CODE (val) == SSA_NAME
+ && !SSA_NAME_IS_DEFAULT_DEF (val))
+ {
+ basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (val));
+ if (!def_bb
+ || def_bb == fosa_bb
+ || (dom_info_available_p (CDI_DOMINATORS)
+ && (def_bb == fosa_bb
+ || dominated_by_p (CDI_DOMINATORS, fosa_bb, def_bb))))
+ return val;
+ return NULL_TREE;
+ }
+ return val;
+}
+
/* 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
enum tree_code code1,
tree op1a, tree op1b,
enum tree_code code2, tree op2a,
- tree op2b)
+ tree op2b,
+ basic_block outer_cond_bb)
{
/* Allocate gimple stmt1 on the stack. */
gassign *stmt1
gimple_assign_set_rhs_code (stmt1, code1);
gimple_assign_set_rhs1 (stmt1, op1a);
gimple_assign_set_rhs2 (stmt1, op1b);
+ gimple_set_bb (stmt1, NULL);
/* Allocate gimple stmt2 on the stack. */
gassign *stmt2
gimple_assign_set_rhs_code (stmt2, code2);
gimple_assign_set_rhs1 (stmt2, op2a);
gimple_assign_set_rhs2 (stmt2, op2b);
+ gimple_set_bb (stmt2, NULL);
/* Allocate SSA names(lhs1) on the stack. */
tree lhs1 = (tree)XALLOCA (tree_ssa_name);
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))
+ fosa_bb = outer_cond_bb;
+ if (op.resimplify (NULL, (!outer_cond_bb
+ ? follow_all_ssa_edges : follow_outer_ssa_edges)))
{
if (gimple_simplified_result_is_gimple_val (&op))
{
tree
maybe_fold_and_comparisons (tree type,
enum tree_code code1, tree op1a, tree op1b,
- enum tree_code code2, tree op2a, tree op2b)
+ enum tree_code code2, tree op2a, tree op2b,
+ basic_block outer_cond_bb)
{
- if (tree t = and_comparisons_1 (type, code1, op1a, op1b, code2, op2a, op2b))
+ if (tree t = and_comparisons_1 (type, code1, op1a, op1b, code2, op2a, op2b,
+ outer_cond_bb))
return t;
- if (tree t = and_comparisons_1 (type, code2, op2a, op2b, code1, op1a, op1b))
+ if (tree t = and_comparisons_1 (type, code2, op2a, op2b, code1, op1a, op1b,
+ outer_cond_bb))
return t;
if (tree t = maybe_fold_comparisons_from_match_pd (type, BIT_AND_EXPR, code1,
op1a, op1b, code2, op2a,
- op2b))
+ op2b, outer_cond_bb))
return t;
return NULL_TREE;
static tree
or_var_with_comparison (tree type, tree var, bool invert,
- enum tree_code code2, tree op2a, tree op2b)
+ enum tree_code code2, tree op2a, tree op2b,
+ basic_block outer_cond_bb)
{
tree t;
gimple *stmt = SSA_NAME_DEF_STMT (var);
if (invert)
t = and_var_with_comparison_1 (type, stmt,
invert_tree_comparison (code2, false),
- op2a, op2b);
+ op2a, op2b, outer_cond_bb);
else
- t = or_var_with_comparison_1 (type, stmt, code2, op2a, op2b);
+ t = or_var_with_comparison_1 (type, stmt, code2, op2a, op2b,
+ outer_cond_bb);
return canonicalize_bool (t, invert);
}
static tree
or_var_with_comparison_1 (tree type, gimple *stmt,
- enum tree_code code2, tree op2a, tree op2b)
+ enum tree_code code2, tree op2a, tree op2b,
+ basic_block outer_cond_bb)
{
tree var = gimple_assign_lhs (stmt);
tree true_test_var = NULL_TREE;
tree t = or_comparisons_1 (type, innercode,
gimple_assign_rhs1 (stmt),
gimple_assign_rhs2 (stmt),
- code2,
- op2a,
- op2b);
+ code2, op2a, op2b, outer_cond_bb);
if (t)
return t;
}
return (is_or
? boolean_true_node
: or_var_with_comparison (type, inner2, false, code2, op2a,
- op2b));
+ op2b, outer_cond_bb));
else if (inner2 == false_test_var)
return (is_or
? boolean_true_node
: or_var_with_comparison (type, inner1, false, code2, op2a,
- op2b));
+ op2b, outer_cond_bb));
/* Next, redistribute/reassociate the OR across the inner tests.
Compute the first partial result, (inner1 OR (op2a code op2b)) */
&& (t = maybe_fold_or_comparisons (type, gimple_assign_rhs_code (s),
gimple_assign_rhs1 (s),
gimple_assign_rhs2 (s),
- code2, op2a, op2b)))
+ code2, op2a, op2b,
+ outer_cond_bb)))
{
/* Handle the OR case, where we are reassociating:
(inner1 OR inner2) OR (op2a code2 op2b)
&& (t = maybe_fold_or_comparisons (type, gimple_assign_rhs_code (s),
gimple_assign_rhs1 (s),
gimple_assign_rhs2 (s),
- code2, op2a, op2b)))
+ code2, op2a, op2b,
+ outer_cond_bb)))
{
/* Handle the OR case, where we are reassociating:
(inner1 OR inner2) OR (op2a code2 op2b)
static tree
or_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b,
- enum tree_code code2, tree op2a, tree op2b)
+ enum tree_code code2, tree op2a, tree op2b,
+ basic_block outer_cond_bb)
{
tree truth_type = truth_type_for (TREE_TYPE (op1a));
case GIMPLE_ASSIGN:
/* Try to simplify by copy-propagating the definition. */
return or_var_with_comparison (type, op1a, invert, code2, op2a,
- op2b);
+ op2b, outer_cond_bb);
case GIMPLE_PHI:
/* If every argument to the PHI produces the same result when
gimple_bb (stmt)))
return NULL_TREE;
temp = or_var_with_comparison (type, arg, invert, code2,
- op2a, op2b);
+ op2a, op2b, outer_cond_bb);
if (!temp)
return NULL_TREE;
else if (!result)
tree
maybe_fold_or_comparisons (tree type,
enum tree_code code1, tree op1a, tree op1b,
- enum tree_code code2, tree op2a, tree op2b)
+ enum tree_code code2, tree op2a, tree op2b,
+ basic_block outer_cond_bb)
{
- if (tree t = or_comparisons_1 (type, code1, op1a, op1b, code2, op2a, op2b))
+ if (tree t = or_comparisons_1 (type, code1, op1a, op1b, code2, op2a, op2b,
+ outer_cond_bb))
return t;
- if (tree t = or_comparisons_1 (type, code2, op2a, op2b, code1, op1a, op1b))
+ if (tree t = or_comparisons_1 (type, code2, op2a, op2b, code1, op1a, op1b,
+ outer_cond_bb))
return t;
if (tree t = maybe_fold_comparisons_from_match_pd (type, BIT_IOR_EXPR, code1,
op1a, op1b, code2, op2a,
- op2b))
+ op2b, outer_cond_bb))
return t;
return NULL_TREE;