+2019-08-16 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-ssa-evrp-analyze.c (record_ranges_from_phis): Skip PHIs
+ for which we can't represent a range.
+ * ipa-cp.c (ipcp_vr_lattice::set_to_bottom): Pass type to
+ set_varying.
+ * tree-ssa-threadedge.c (record_temporary_equivalences_from_phis):
+ Set VR_UNDEFINED if type is not supported.
+ * tree-ssanames.c (get_range_info): Pass type to set_varying.
+ * tree-vrp.c (value_range_base::check): Assert that a varying has
+ min/max set.
+ (value_range_base::equal_p): Early bail for undefines.
+ (value_range_base::set_varying): Accept a type.
+ (value_range::set_varying): Same.
+ (value_range_base::type): VARYING can have a type, while UNDEFINE
+ is typeless.
+ (value_range_base::dump): Print type for VARYING nodes.
+ (value_range_base::set): Add type to VARYING.
+ (extract_range_from_multiplicative_op): Pass type to set_varying.
+ (extract_range_from_binary_expr): Same.
+ (value_range_base::intersect_helper): Same.
+ (value_range_base::union_helper): Same.
+ (value_range_base::normalize_symbolics): Same.
+ (determine_value_range_1): Same.
+ * tree-vrp.h (class value_range_base): Add type to set_varying.
+ Add prototype for dump(void).
+ Add prototype for supports_type_p.
+ (class value_range): Add type to set_varying.
+ Add prototype for dump(void).
+ * vr-values.c (set_value_range_to_truthvalue): Pass type to
+ set_varying.
+ (vr_values::get_lattice_entry): Set varying even if propagation
+ finished.
+ Pass type to set_varying.
+ (vr_values::get_value_range): Remove vr_const_varying.
+ Reallocate the lattice if needed.
+ (vr_values::update_value_range): Pass type to set_varying.
+ (vr_values::extract_range_for_var_from_comparison_expr): Same.
+ (vr_values::extract_range_from_binary_expr): Same.
+ (vr_values::extract_range_from_unary_expr): Same.
+ (vr_values::extract_range_from_cond_expr): Same.
+ (vr_values::check_for_binary_op_overflow): Same.
+ (vr_values::extract_range_basic): Same.
+ (vr_values::extract_range_from_assignment): Same.
+ (vr_values::vr_values): Increase size of num_vr_values.
+ (vr_values::extract_range_from_phi_node): Pass type to
+ set_varying.
+
2019-08-15 H.J. Lu <hongjiu.lu@intel.com>
PR target/90878
if (virtual_operand_p (lhs))
continue;
+ /* Skips floats and other things we can't represent in a
+ range. */
+ if (!value_range_base::supports_type_p (TREE_TYPE (lhs)))
+ continue;
+
value_range vr_result;
bool interesting = stmt_interesting_for_vrp (phi);
if (!has_unvisited_preds && interesting)
vr_values->extract_range_from_phi_node (phi, &vr_result);
else
{
- vr_result.set_varying ();
+ vr_result.set_varying (TREE_TYPE (lhs));
/* When we have an unvisited executable predecessor we can't
use PHI arg ranges which may be still UNDEFINED but have
to use VARYING for them. But we can still resort to
{
if (m_vr.varying_p ())
return false;
- m_vr.set_varying ();
+ /* ?? We create all sorts of VARYING ranges for floats, structures,
+ and other types which we cannot handle as ranges. We should
+ probably avoid handling them throughout the pass, but it's easier
+ to create a sensible VARYING here and let the lattice
+ propagate. */
+ m_vr.set_varying (integer_type_node);
return true;
}
else if (TREE_CODE (src) == INTEGER_CST)
new_vr->set (src);
else
- new_vr->set_varying ();
+ new_vr->set_varying (TREE_TYPE (src));
/* This is a temporary range for DST, so push it. */
evrp_range_analyzer->push_value_range (dst, new_vr);
wide_int wmin, wmax;
enum value_range_kind kind = get_range_info (name, &wmin, &wmax);
- if (kind == VR_VARYING || kind == VR_UNDEFINED)
- min = max = NULL;
+ if (kind == VR_VARYING)
+ vr.set_varying (TREE_TYPE (name));
+ else if (kind == VR_UNDEFINED)
+ vr.set_undefined ();
else
{
min = wide_int_to_tree (TREE_TYPE (name), wmin);
max = wide_int_to_tree (TREE_TYPE (name), wmax);
+ vr.set (kind, min, max);
}
- vr.set (kind, min, max);
return kind;
}
break;
}
case VR_UNDEFINED:
- case VR_VARYING:
gcc_assert (!min () && !max ());
break;
+ case VR_VARYING:
+ gcc_assert (m_min && m_max);
+ break;
default:
gcc_unreachable ();
}
bool
value_range_base::equal_p (const value_range_base &other) const
{
+ /* Ignore types for undefined. All undefines are equal. */
+ if (undefined_p ())
+ return m_kind == other.m_kind;
+
return (m_kind == other.m_kind
&& vrp_operand_equal_p (m_min, other.m_min)
&& vrp_operand_equal_p (m_max, other.m_max));
}
void
-value_range_base::set_varying ()
+value_range_base::set_varying (tree type)
{
m_kind = VR_VARYING;
- m_min = m_max = NULL;
+ if (supports_type_p (type))
+ {
+ m_min = vrp_val_min (type, true);
+ m_max = vrp_val_max (type, true);
+ }
+ else
+ /* We can't do anything range-wise with these types. */
+ m_min = m_max = error_mark_node;
}
void
-value_range::set_varying ()
+value_range::set_varying (tree type)
{
- set (VR_VARYING, NULL, NULL, NULL);
+ value_range_base::set_varying (type);
+ equiv_clear ();
}
/* Return TRUE if it is possible that range contains VAL. */
tree
value_range_base::type () const
{
- /* Types are only valid for VR_RANGE and VR_ANTI_RANGE, which are
- known to have non-zero min/max. */
- gcc_assert (min ());
+ gcc_assert (m_min || undefined_p ());
return TREE_TYPE (min ());
}
fprintf (file, "]");
}
else if (varying_p ())
- fprintf (file, "VARYING");
+ {
+ print_generic_expr (file, type ());
+ fprintf (file, " VARYING");
+ }
else
gcc_unreachable ();
}
+void
+value_range_base::dump () const
+{
+ dump (stderr);
+}
+
void
value_range::dump (FILE *file) const
{
}
}
+void
+value_range::dump () const
+{
+ dump (stderr);
+}
+
void
dump_value_range (FILE *file, const value_range *vr)
{
}
else if (kind == VR_VARYING)
{
- set_varying ();
+ gcc_assert (TREE_TYPE (min) == TREE_TYPE (max));
+ tree typ = TREE_TYPE (min);
+ if (supports_type_p (typ))
+ {
+ gcc_assert (vrp_val_min (typ, true));
+ gcc_assert (vrp_val_max (typ, true));
+ }
+ set_varying (typ);
return;
}
for VR_ANTI_RANGE empty range, so drop to varying as well. */
if (TYPE_PRECISION (TREE_TYPE (min)) == 1)
{
- set_varying ();
+ set_varying (TREE_TYPE (min));
return;
}
to varying in this case. */
if (tree_int_cst_lt (max, min))
{
- set_varying ();
+ set_varying (TREE_TYPE (min));
return;
}
{
/* We cannot deal with empty ranges, drop to varying.
??? This could be VR_UNDEFINED instead. */
- set_varying ();
+ set_varying (type);
return;
}
else if (TYPE_PRECISION (TREE_TYPE (min)) == 1
&& wi::eq_p (wi::to_wide (max), wi::max_value (prec, sign)))
{
if (kind == VR_RANGE)
- set_varying ();
+ set_varying (type);
else if (kind == VR_ANTI_RANGE)
set_undefined ();
else
|| code == LSHIFT_EXPR);
if (!range_int_cst_p (vr1))
{
- vr->set_varying ();
+ vr->set_varying (type);
return;
}
vr->set (VR_RANGE, wide_int_to_tree (type, res_lb),
wide_int_to_tree (type, res_ub));
else
- vr->set_varying ();
+ vr->set_varying (type);
}
/* If BOUND will include a symbolic bound, adjust it accordingly,
if (!INTEGRAL_TYPE_P (expr_type)
&& !POINTER_TYPE_P (expr_type))
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
&& code != BIT_IOR_EXPR
&& code != BIT_XOR_EXPR)
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
have UNDEFINED result for all or some value-ranges of the not UNDEFINED
operand. */
else if (vr0.undefined_p ())
- vr0.set_varying ();
+ vr0.set_varying (expr_type);
else if (vr1.undefined_p ())
- vr1.set_varying ();
+ vr1.set_varying (expr_type);
/* We get imprecise results from ranges_from_anti_range when
code is EXACT_DIV_EXPR. We could mask out bits in the resulting
|| vr0.symbolic_p ()
|| vr1.symbolic_p ()))
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
else if (vr0.zero_p () && vr1.zero_p ())
vr->set_zero (expr_type);
else
- vr->set_varying ();
+ vr->set_varying (expr_type);
}
else if (code == POINTER_PLUS_EXPR)
{
else if (vr0.zero_p () && vr1.zero_p ())
vr->set_zero (expr_type);
else
- vr->set_varying ();
+ vr->set_varying (expr_type);
}
else if (code == BIT_AND_EXPR)
{
else if (vr0.zero_p () || vr1.zero_p ())
vr->set_zero (expr_type);
else
- vr->set_varying ();
+ vr->set_varying (expr_type);
}
else
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
if (((bool)min_ovf && sym_min_op0 != sym_min_op1)
|| ((bool)max_ovf && sym_max_op0 != sym_max_op1))
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
wmin, wmax, min_ovf, max_ovf);
if (type == VR_VARYING)
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
a single range or anti-range as the above is
[-INF+1, +INF(OVF)] intersected with ~[5, 5]
but one could use a scheme similar to equivalences for this. */
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
}
vr->set (VR_RANGE, wide_int_to_tree (expr_type, wmin),
wide_int_to_tree (expr_type, wmax));
else
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
else if (code == MULT_EXPR)
if (!range_int_cst_p (&vr0)
|| !range_int_cst_p (&vr1))
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
extract_range_from_multiplicative_op (vr, code, expr_type, &vr0, &vr1);
}
}
}
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
else if (code == TRUNC_DIV_EXPR
TYPE_OVERFLOW_UNDEFINED (expr_type),
extra_range_p, extra_min, extra_max))
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
vr->set (VR_RANGE, wide_int_to_tree (expr_type, wmin),
vr->set (VR_RANGE, min, max);
}
else
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
else if (code == BIT_IOR_EXPR)
vr->set (VR_RANGE, min, max);
}
else
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
else if (code == BIT_XOR_EXPR)
vr->set (VR_RANGE, min, max);
}
else
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
}
|| max == NULL_TREE
|| TREE_OVERFLOW_P (max))
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
Note that we do accept [-INF, -INF] and [+INF, +INF]. */
if (vrp_val_is_min (min) && vrp_val_is_max (max))
{
- vr->set_varying ();
+ vr->set_varying (expr_type);
return;
}
/* If the new range has its limits swapped around (MIN > MAX),
then the operation caused one of them to wrap around, mark
the new range VARYING. */
- vr->set_varying ();
+ vr->set_varying (expr_type);
}
else
vr->set (type, min, max);
|| !(INTEGRAL_TYPE_P (type)
|| POINTER_TYPE_P (type)))
{
- vr->set_varying ();
+ vr->set_varying (type);
return;
}
else if (vr0.zero_p ())
vr->set_zero (type);
else
- vr->set_varying ();
+ vr->set_varying (type);
return;
}
vr->set (VR_RANGE, min, max);
}
else
- vr->set_varying ();
+ vr->set_varying (outer_type);
return;
}
else if (code == ABS_EXPR)
vr->set (VR_RANGE, wide_int_to_tree (type, wmin),
wide_int_to_tree (type, wmax));
else
- vr->set_varying ();
+ vr->set_varying (type);
return;
}
else if (code == ABSU_EXPR)
}
/* For unhandled operations fall back to varying. */
- vr->set_varying ();
+ vr->set_varying (type);
return;
}
VR_RANGE can still be a VR_RANGE. Work on a temporary so we can
fall back to vr0 when this turns things to varying. */
value_range_base tem;
- tem.set (vr0type, vr0min, vr0max);
+ if (vr0type == VR_UNDEFINED)
+ tem.set_undefined ();
+ else if (vr0type == VR_VARYING)
+ tem.set_varying (vr0->type ());
+ else
+ tem.set (vr0type, vr0min, vr0max);
/* If that failed, use the saved original VR0. */
if (tem.varying_p ())
return *vr0;
/* Work on a temporary so we can still use vr0 when union returns varying. */
value_range_base tem;
- tem.set (vr0type, vr0min, vr0max);
+ if (vr0type == VR_UNDEFINED)
+ tem.set_undefined ();
+ else if (vr0type == VR_VARYING)
+ tem.set_varying (vr0->type ());
+ else
+ tem.set (vr0type, vr0min, vr0max);
/* Failed to find an efficient meet. Before giving up and setting
the result to VARYING, see if we can at least derive a useful
if (min_symbolic && max_symbolic)
{
value_range_base var;
- var.set_varying ();
+ var.set_varying (ttype);
return var;
}
if (kind () == VR_RANGE)
return value_range_base (VR_RANGE, n, vrp_val_max (ttype));
}
value_range_base var;
- var.set_varying ();
+ var.set_varying (ttype);
return var;
}
// ~[NUM, SYM] -> [-MIN, NUM - 1]
return value_range_base (VR_RANGE, vrp_val_min (ttype), n);
}
value_range_base var;
- var.set_varying ();
+ var.set_varying (ttype);
return var;
}
vr->set (kind, wide_int_to_tree (TREE_TYPE (expr), min),
wide_int_to_tree (TREE_TYPE (expr), max));
else
- vr->set_varying ();
+ vr->set_varying (TREE_TYPE (expr));
}
}
bool constant_p () const;
bool undefined_p () const;
bool varying_p () const;
- void set_varying ();
+ void set_varying (tree type);
void set_undefined ();
void union_ (const value_range_base *);
bool nonzero_p () const;
bool singleton_p (tree *result = NULL) const;
void dump (FILE *) const;
+ void dump () const;
+ static bool supports_type_p (tree);
value_range_base normalize_symbolics () const;
protected:
/* Types of value ranges. */
void set_undefined ();
- void set_varying ();
+ void set_varying (tree);
/* Equivalence bitmap methods. */
bitmap equiv () const;
/* Misc methods. */
void deep_copy (const value_range *);
void dump (FILE *) const;
+ void dump () const;
private:
/* Deep-copies bitmap argument. */
tree expr;
};
+// Return true if TYPE is a valid type for value_range to operate on.
+// Otherwise return FALSE.
+
+inline bool
+value_range_base::supports_type_p (tree type)
+{
+ if (type && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)))
+ return type;
+ return NULL;
+}
+
extern void register_edge_assert_for (tree, edge, enum tree_code,
tree, tree, vec<assert_info> &);
extern bool stmt_interesting_for_vrp (gimple *);
set_value_range_to_truthvalue (value_range *vr, tree type)
{
if (TYPE_PRECISION (type) == 1)
- vr->set_varying ();
+ vr->set_varying (type);
else
vr->update (VR_RANGE, build_int_cst (type, 0), build_int_cst (type, 1));
}
if (vr)
return vr;
- /* After propagation finished do not allocate new value-ranges. */
- if (values_propagated)
- return NULL;
-
/* Create a default value range. */
vr_value[ver] = vr = vrp_value_range_pool.allocate ();
+
+ /* After propagation finished return varying. */
+ if (values_propagated)
+ {
+ vr->set_varying (TREE_TYPE (var));
+ return vr;
+ }
+
vr->set_undefined ();
/* If VAR is a default definition of a parameter, the variable can
{
get_range_info (var, *vr);
if (vr->undefined_p ())
- vr->set_varying ();
+ vr->set_varying (TREE_TYPE (sym));
}
else
- vr->set_varying ();
+ vr->set_varying (TREE_TYPE (sym));
}
else if (TREE_CODE (sym) == RESULT_DECL
&& DECL_BY_REFERENCE (sym))
const value_range *
vr_values::get_value_range (const_tree var)
{
- static const value_range vr_const_varying (VR_VARYING, NULL, NULL);
-
/* If we have no recorded ranges, then return NULL. */
if (!vr_value)
return NULL;
value_range *vr = get_lattice_entry (var);
+
+ /* Reallocate the lattice if needed. */
if (!vr)
- return &vr_const_varying;
+ {
+ unsigned int old_sz = num_vr_values;
+ num_vr_values = num_ssa_names + num_ssa_names / 10;
+ vr_value = XRESIZEVEC (value_range *, vr_value, num_vr_values);
+ for ( ; old_sz < num_vr_values; old_sz++)
+ vr_value [old_sz] = NULL;
+
+ /* Now that the lattice has been resized, we should never fail. */
+ vr = get_lattice_entry (var);
+ gcc_assert (vr);
+ }
return vr;
}
{
value_range *vr = get_lattice_entry (def);
if (vr)
- vr->set_varying ();
+ vr->set_varying (TREE_TYPE (def));
}
/* Set value-ranges of all SSA names defined by STMT to varying. */
called, if we are anyway, keep it VARYING. */
if (old_vr->varying_p ())
{
- new_vr->set_varying ();
+ new_vr->set_varying (new_vr->type ());
is_new = false;
}
else if (new_vr->undefined_p ())
{
- old_vr->set_varying ();
- new_vr->set_varying ();
+ old_vr->set_varying (TREE_TYPE (var));
+ new_vr->set_varying (TREE_TYPE (var));
return true;
}
else
if ((POINTER_TYPE_P (type) && cond_code != NE_EXPR && cond_code != EQ_EXPR)
|| limit == var)
{
- vr_p->set_varying ();
+ vr_p->set_varying (type);
return;
}
all should be optimized away above us. */
if (cond_code == LT_EXPR
&& compare_values (max, min) == 0)
- vr_p->set_varying ();
+ vr_p->set_varying (TREE_TYPE (min));
else
{
/* For LT_EXPR, we create the range [MIN, MAX - 1]. */
all should be optimized away above us. */
if (cond_code == GT_EXPR
&& compare_values (min, max) == 0)
- vr_p->set_varying ();
+ vr_p->set_varying (TREE_TYPE (min));
else
{
/* For GT_EXPR, we create the range [MIN + 1, MAX]. */
else if (is_gimple_min_invariant (op0))
vr0.set (op0);
else
- vr0.set_varying ();
+ vr0.set_varying (TREE_TYPE (op0));
if (TREE_CODE (op1) == SSA_NAME)
vr1 = *(get_value_range (op1));
else if (is_gimple_min_invariant (op1))
vr1.set (op1);
else
- vr1.set_varying ();
+ vr1.set_varying (TREE_TYPE (op1));
/* If one argument is varying, we can sometimes still deduce a
range for the output: any + [3, +INF] is in [MIN+3, +INF]. */
else if (is_gimple_min_invariant (op0))
vr0.set (op0);
else
- vr0.set_varying ();
+ vr0.set_varying (type);
::extract_range_from_unary_expr (vr, code, type, &vr0, TREE_TYPE (op0));
}
else if (is_gimple_min_invariant (op0))
tem0.set (op0);
else
- tem0.set_varying ();
+ tem0.set_varying (TREE_TYPE (op0));
tree op1 = gimple_assign_rhs3 (stmt);
value_range tem1;
else if (is_gimple_min_invariant (op1))
tem1.set (op1);
else
- tem1.set_varying ();
+ tem1.set_varying (TREE_TYPE (op1));
/* The resulting value range is the union of the operand ranges */
vr->deep_copy (vr0);
else if (TREE_CODE (op0) == INTEGER_CST)
vr0.set (op0);
else
- vr0.set_varying ();
+ vr0.set_varying (TREE_TYPE (op0));
if (TREE_CODE (op1) == SSA_NAME)
vr1 = *get_value_range (op1);
else if (TREE_CODE (op1) == INTEGER_CST)
vr1.set (op1);
else
- vr1.set_varying ();
+ vr1.set_varying (TREE_TYPE (op1));
tree vr0min = vr0.min (), vr0max = vr0.max ();
tree vr1min = vr1.min (), vr1max = vr1.max ();
if (vr->kind () == VR_RANGE
&& (vr->min () == vr->max ()
|| operand_equal_p (vr->min (), vr->max (), 0)))
- vr->set_varying ();
+ vr->set_varying (vr->type ());
return;
}
}
vr->set (build_int_cst (type, ovf));
else if (TYPE_PRECISION (type) == 1
&& !TYPE_UNSIGNED (type))
- vr->set_varying ();
+ vr->set_varying (type);
else
vr->set (VR_RANGE, build_int_cst (type, 0),
build_int_cst (type, 1));
vr->equiv_clear ();
}
else
- vr->set_varying ();
+ vr->set_varying (type);
}
&& is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))
vr->set (gimple_assign_rhs1 (stmt));
else
- vr->set_varying ();
+ vr->set_varying (TREE_TYPE (gimple_assign_lhs (stmt)));
if (vr->varying_p ())
extract_range_basic (vr, stmt);
vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges")
{
values_propagated = false;
- num_vr_values = num_ssa_names;
+ num_vr_values = num_ssa_names * 2;
vr_value = XCNEWVEC (value_range *, num_vr_values);
vr_phi_edge_counts = XCNEWVEC (int, num_ssa_names);
bitmap_obstack_initialize (&vrp_equiv_obstack);
vr_arg_tem.set (vr_arg_->kind (), vr_arg_->min (),
vr_arg_->max (), NULL);
if (vr_arg_tem.symbolic_p ())
- vr_arg_tem.set_varying ();
+ vr_arg_tem.set_varying (TREE_TYPE (arg));
}
else
vr_arg = vr_arg_;
goto update_range;
varying:
- vr_result->set_varying ();
+ vr_result->set_varying (TREE_TYPE (lhs));
scev_check:
/* If this is a loop PHI node SCEV may known more about its value-range.
|| compare_values (vr_result->min (), vr_result->max ()) > 0))
;
else
- vr_result->set_varying ();
+ vr_result->set_varying (TREE_TYPE (lhs));
/* If the new range is different than the previous value, keep
iterating. */