diff options
author | Aldy Hernandez <aldyh@redhat.com> | 2020-03-10 08:05:04 +0100 |
---|---|---|
committer | Aldy Hernandez <aldyh@redhat.com> | 2020-03-10 17:42:12 +0100 |
commit | 25acb185730931fb8fbe824c145bbb1cce42d61c (patch) | |
tree | f2547c1e06c36054e95a14ca9013cd05dfe466ec /gcc | |
parent | 02807fb45dd247554211e57fe22b3a89db970e53 (diff) | |
download | gcc-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.cc | 51 | ||||
-rw-r--r-- | gcc/gimple-range-gori.h | 6 |
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 |