else if (tree cached_name = m_cache->same_cached_name (op1, op2))
{
tf_range op1_range, op2_range;
- gcc_assert (m_cache->get_range (op1_range, op1, cached_name));
- gcc_assert (m_cache->get_range (op2_range, op2, cached_name));
- gcc_assert (logical_combine (r_true_side, code, m_bool_one,
- op1_range, op2_range));
- gcc_assert (logical_combine (r_false_side, code, m_bool_zero,
- op1_range, op2_range));
- m_cache->set_range (lhs, cached_name,
- tf_range (r_true_side, r_false_side));
+ bool ok = m_cache->get_range (op1_range, op1, cached_name);
+ ok = ok && m_cache->get_range (op2_range, op2, cached_name);
+ ok = ok && logical_combine (r_true_side, code, m_bool_one,
+ op1_range, op2_range);
+ ok = ok && logical_combine (r_false_side, code, m_bool_zero,
+ op1_range, op2_range);
+ gcc_checking_assert (ok);
+ if (ok)
+ m_cache->set_range (lhs, cached_name,
+ tf_range (r_true_side, r_false_side));
}
}
}
// Return a range in R for the tree EXPR. Return true if a range is
-// representable.
+// representable, and UNDEFINED/false if not.
bool
get_tree_range (irange &r, tree expr)
// Return false if the type isn't suported.
if (!irange::supports_type_p (type))
- return false;
+ {
+ r.set_undefined ();
+ return false;
+ }
switch (TREE_CODE (expr))
{
res = range_of_call (r, as_a<gcall *> (s));
else if (is_a<gassign *> (s) && gimple_assign_rhs_code (s) == COND_EXPR)
res = range_of_cond_expr (r, as_a<gassign *> (s));
- else
+
+ if (!res)
{
// If no name is specified, try the expression kind.
if (!name)
r.set_varying (t);
return true;
}
+ if (!gimple_range_ssa_p (name))
+ return false;
// We don't understand the stmt, so return the global range.
r = gimple_range_global (name);
return true;
}
- if (res)
+
+ if (r.undefined_p ())
+ return true;
+
+ // We sometimes get compatible types copied from operands, make sure
+ // the correct type is being returned.
+ if (name && TREE_TYPE (name) != r.type ())
{
- if (r.undefined_p ())
- return true;
- // We sometimes get compatible types copied from operands, make sure
- // the correct type is being returned.
- if (name && TREE_TYPE (name) != r.type ())
- {
- gcc_checking_assert (range_compatible_p (r.type (),
- TREE_TYPE (name)));
- range_cast (r, TREE_TYPE (name));
- }
- return true;
+ gcc_checking_assert (range_compatible_p (r.type (), TREE_TYPE (name)));
+ range_cast (r, TREE_TYPE (name));
}
- return false;
+ return true;
}
// Calculate a range for range_op statement S and return it in R. If any
int_range_max ir0, ir1;
tree arg0 = gimple_call_arg (call, 0);
tree arg1 = gimple_call_arg (call, 1);
- gcc_assert (query.range_of_expr (ir0, arg0, call));
- gcc_assert (query.range_of_expr (ir1, arg1, call));
+ query.range_of_expr (ir0, arg0, call);
+ query.range_of_expr (ir1, arg1, call);
bool saved_flag_wrapv = flag_wrapv;
// Pretend the arithmetic is wrapping. If there is any overflow,
prec = TYPE_PRECISION (TREE_TYPE (arg));
mini = 0;
maxi = prec;
- gcc_assert (query.range_of_expr (r, arg, call));
+ query.range_of_expr (r, arg, call);
// If arg is non-zero, then ffs or popcount are non-zero.
if (!range_includes_zero_p (&r))
mini = 1;
}
}
- gcc_assert (query.range_of_expr (r, arg, call));
+ query.range_of_expr (r, arg, call);
// From clz of minimum we can compute result maximum.
if (r.constant_p ())
{
mini = -2;
}
}
- gcc_assert (query.range_of_expr (r, arg, call));
+ query.range_of_expr (r, arg, call);
if (!r.undefined_p ())
{
if (r.lower_bound () != 0)
if (!irange::supports_type_p (TREE_TYPE (op1)))
return false;
- gcc_assert (range_of_expr (cond_range, cond, s));
- gcc_assert (range_of_expr (range1, op1, s));
- gcc_assert (range_of_expr (range2, op2, s));
+ range_of_expr (cond_range, cond, s);
+ range_of_expr (range1, op1, s);
+ range_of_expr (range2, op2, s);
// If the condition is known, choose the appropriate expression.
if (cond_range.singleton_p ())
// If name is defined in this block, try to get an range from S.
if (def_stmt && gimple_bb (def_stmt) == bb)
- gcc_assert (range_of_stmt (r, def_stmt, expr));
+ range_of_stmt (r, def_stmt, expr);
else
// Otherwise OP comes from outside this block, use range on entry.
range_on_entry (r, bb, expr);
gcc_checking_assert (gimple_range_ssa_p (name));
// Start with any known range
- gcc_assert (range_of_stmt (r, SSA_NAME_DEF_STMT (name), name));
+ range_of_stmt (r, SSA_NAME_DEF_STMT (name), name);
// Now see if there is any on_entry value which may refine it.
if (m_cache.block_range (entry_range, bb, name))
{
// on-exit from the exit block?
gcc_checking_assert (bb != EXIT_BLOCK_PTR_FOR_FN (cfun));
+ gcc_checking_assert (gimple_range_ssa_p (name));
gimple *s = last_stmt (bb);
// If there is no statement in the block and this isn't the entry
if (!s && bb != ENTRY_BLOCK_PTR_FOR_FN (cfun))
range_on_entry (r, bb, name);
else
- gcc_assert (range_of_expr (r, name, s));
+ range_of_expr (r, name, s);
gcc_checking_assert (r.undefined_p ()
|| range_compatible_p (r.type (), TREE_TYPE (name)));
}
// PHI arguments can be constants, catch these here.
if (!gimple_range_ssa_p (name))
- {
- gcc_assert (range_of_expr (r, name));
- return true;
- }
+ return range_of_expr (r, name);
range_on_exit (r, e->src, name);
gcc_checking_assert (r.undefined_p ()
// provided it represents the SSA_NAME on the LHS of the statement.
// It is only required if there is more than one lhs/output. Check
// the global cache for NAME first to see if the evaluation can be
-// avoided. If a range cannot be calculated, return false.
+// avoided. If a range cannot be calculated, return false and UNDEFINED.
bool
gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name)
{
- // If no name, simply call the base routine.
+ r.set_undefined ();
+
if (!name)
name = gimple_get_lhs (s);
+ // If no name, simply call the base routine.
if (!name)
return calc_stmt (r, s, NULL_TREE);
- gcc_checking_assert (TREE_CODE (name) == SSA_NAME &&
- irange::supports_type_p (TREE_TYPE (name)));
+ if (!gimple_range_ssa_p (name))
+ return false;
// If this STMT has already been processed, return that value.
if (m_cache.m_globals.get_global_range (r, name))
return true;
+
// Avoid infinite recursion by initializing global cache
int_range_max tmp = gimple_range_global (name);
m_cache.m_globals.set_global_range (name, tmp);
- gcc_assert (calc_stmt (r, s, name));
+ calc_stmt (r, s, name);
if (is_a<gphi *> (s))
r.intersect (tmp);