aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2020-03-10 08:05:04 +0100
committerAldy Hernandez <aldyh@redhat.com>2020-03-10 17:42:12 +0100
commit25acb185730931fb8fbe824c145bbb1cce42d61c (patch)
treef2547c1e06c36054e95a14ca9013cd05dfe466ec /gcc
parent02807fb45dd247554211e57fe22b3a89db970e53 (diff)
downloadgcc-25acb185730931fb8fbe824c145bbb1cce42d61c.zip
gcc-25acb185730931fb8fbe824c145bbb1cce42d61c.tar.gz
gcc-25acb185730931fb8fbe824c145bbb1cce42d61c.tar.bz2
Move recursion limits to gori_compute::compute_operand_range_op.
Allow special cases of: 1 = x & y 0 = x | y ...to recurse infinitely, because we know they won't blow up compile time.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gimple-range-gori.cc51
-rw-r--r--gcc/gimple-range-gori.h6
2 files changed, 51 insertions, 6 deletions
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index ee501f2..9c195bc 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -617,6 +617,8 @@ gori_compute::compute_name_range_op (irange &r, gimple *stmt,
gori_compute::gori_compute ()
{
+ m_depth = 0;
+ m_depth_limit = m_default_depth_limit;
// Create a boolean_type true and false range.
m_bool_zero = int_range<1> (boolean_false_node, boolean_false_node);
m_bool_one = int_range<1> (boolean_true_node, boolean_true_node);
@@ -708,6 +710,21 @@ is_gimple_logical_p (const gimple *gs)
return false;
}
+bool
+gori_compute::logical_operation_is_linear (const gimple *stmt,
+ const irange &lhs)
+{
+ tree_code code = gimple_expr_code (stmt);
+
+ if (code == BIT_IOR_EXPR && lhs.zero_p ())
+ return true;
+
+ if (code == BIT_AND_EXPR && lhs == m_bool_one)
+ return true;
+
+ return false;
+}
+
// Return an evaluation for NAME as it would appear in STMT when the
// statement's lhs evaluates to LHS. If successful, return TRUE and
// store the evaluation in R, otherwise return FALSE.
@@ -730,6 +747,23 @@ gori_compute::compute_operand_range_op (irange &r, gimple *stmt,
return true;
}
+ // Set the depth limit to the default for the duration of this
+ // iteration.
+ class save_depth_limit
+ {
+ public:
+ save_depth_limit (gori_compute *g)
+ {
+ gori = g;
+ save = g->m_depth_limit;
+ }
+ ~save_depth_limit () { gori->m_depth_limit = save; }
+ private:
+ gori_compute *gori;
+ unsigned save;
+ } limit (this);
+ m_depth_limit = m_default_depth_limit;
+
op1 = gimple_range_ssa_p (gimple_range_operand1 (stmt));
op2 = gimple_range_ssa_p (gimple_range_operand2 (stmt));
@@ -740,7 +774,14 @@ gori_compute::compute_operand_range_op (irange &r, gimple *stmt,
// Check for logical combination cases which require developing
// ranges and combining the results based on the operation.
if (is_gimple_logical_p (stmt))
- return compute_logical_operands (r, stmt, lhs, name, name_range);
+ {
+ // Allow infinite recursion for operations that are known to be
+ // linear.
+ if (logical_operation_is_linear (stmt, lhs))
+ m_depth_limit = ~0;
+ bool ret = compute_logical_operands (r, stmt, lhs, name, name_range);
+ return ret;
+ }
// Reaching this point means NAME is not in this stmt, but one of
// the names in it ought to be derived from it.
@@ -916,8 +957,6 @@ gori_compute::compute_logical_operands (irange &r, gimple *stmt,
{
tree op1, op2;
bool op1_in_chain, op2_in_chain;
- const unsigned depth_limit = 6; // Max depth of logical recursion.
- static unsigned depth = 0; // Current depth of recursion.
widest_irange op1_true, op1_false, op2_true, op2_false;
// Reaching this point means NAME is not in this stmt, but one of
@@ -940,12 +979,12 @@ gori_compute::compute_logical_operands (irange &r, gimple *stmt,
// recursively evaluating them for the true and false result. If
// the depth is too great simply terminate the calculation. See gcc
// testcase rvrp-logic-1.c.
- if (depth > depth_limit)
+ if (m_depth > m_depth_limit)
{
r.set_varying (TREE_TYPE (name));
return true;
}
- depth++;
+ m_depth++;
// The false path is not always a simple inversion of the true side.
// Calulate ranges for true and false on both sides.
@@ -983,7 +1022,7 @@ gori_compute::compute_logical_operands (irange &r, gimple *stmt,
op1_true, op1_false, op2_true, op2_false))
r.set_varying (TREE_TYPE (name));
- depth--;
+ m_depth--;
return true;
}
diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h
index 7f4b1a5..628257c 100644
--- a/gcc/gimple-range-gori.h
+++ b/gcc/gimple-range-gori.h
@@ -189,8 +189,14 @@ private:
const irange &op1_false,
const irange &op2_true,
const irange &op2_false);
+ bool logical_operation_is_linear (const gimple *, const irange &);
int_range<1> m_bool_zero; /* Boolean zero cached. */
int_range<1> m_bool_one; /* Boolean true cached. */
+ const unsigned m_default_depth_limit = 6;
+ // Max depth of logical recursion.
+ unsigned m_depth_limit;
+ // Current depth of logical recursion.
+ unsigned m_depth;
};
class trace_gori_compute : public gori_compute