On 7/2/19 4:17 PM, Jeff Law wrote:
On 7/1/19 2:52 AM, Aldy Hernandez wrote:
As discussed before, this enforces types on undefined and varying, which
makes everything more regular, and removes some special casing
throughout range handling.
The min/max fields will contain TYPE_MIN_VALUE and TYPE_MAX_VALUE, which
will make it easy to get at the bounds of a range later on. Since
pointers don't have TYPE_MIN/MAX_VALUE, we are using build_zero_cst()
and wide_int_to_tree(wi::max_value(precision)), for consistency.
UNDEFINED is set similarly, though nobody should ever ask for anything
except type() from it. That is, no one should be asking for the bounds.
There is one wrinkle, ipa-cp creates VR_VARYING ranges of floats,
presumably to pass around state?? This causes value_range_base::type()
and others to fail, even though I haven't actually seen a case of
someone actually trying to set a VR_RANGE of a float. For now, I've
built a NOP_EXPR wrapper so type() works correctly. The correct
approach would probably be to avoid creating these varying/undefined
ranges in ipa-cp, but I don't have enough ipa-cp-foo to do so.
Suggestions welcome, if you don't like special casing this for ipa-cp.
Or perhaps as a follow up.
No idea why we create ranges of floats from ipa-cp. I presume it's
coming from propagate_vr_across_jump_function? Or somewhere else?
I believe it was ipcp_vr_lattice::set_to_bottom, while changing an
UNDEFINED to VARYING. IMO, we shouldn't even have created UNDEFINED
ranges of floats. It's not like we can do anything with float ranges.
In this patch I start introducing a couple small API changes that will
be needed for range-ops. Since they're needed/useful for this patch, I
started adding them on a need-to-use basis. They are:
value_range_base (tree type)
This is our constructor for building a varying:
value_range_base foo (some_type);
value_range_base::supports_type_p(tree type)
We use this instead of having to test everywhere for
INTEGRAL_TYPE_P and POINTER_TYPE_P which VRP uses throughout.
I have not ported every use of the INTEGRAL || POINTER in the
compiler to this function. But that could be a follow up
cleanup if someone (else) is interested :).
Cleanups of this nature are pre-approved once this patch is ACK'd and
installed.
value_range_base_normalize_symbolics():
This normalizes symbolics into constants. In VRP we usually
normalize necessary symbolics into [MIN, MAX]. This patch does
slightly better. Now we transform:
// [SYM, SYM] -> VARYING
// [SYM, NUM] -> [-MIN, NUM]
// [NUM, SYM] -> [NUM, +MAX]
// ~[SYM, NUM] -> [NUM + 1, +MAX]
// ~[NUM, SYM] -> [-MIN, NUM - 1]
TBH, this bit and its use in *multiplicative_op probably fits
better with the canonicalization patch, but as I said. They're
a bit intertwined. Ughh.
I think it does fit better there, but we ought to be able to manage.
Finally, as you mentioned before, we need a way of caching varyings in
the allocation pool. The type_range_cache class in the attached patch
is Andrew's doing, but I'll be happy to take the blame and address
anything that needs doing.
Tested on x86-64 Linux with --enable-languages=all.
Aldy
range-ops-type.patch
commit 24c3a6a2cb7424a9c022930cada3a5f3c84a388a
Author: Aldy Hernandez <al...@redhat.com>
Date: Fri Jun 28 11:00:10 2019 +0200
VR_UNDEFINED and VR_VARYING now have a type.
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 01fb97cedb2..a5247735694 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,72 @@
+2019-07-01 Aldy Hernandez <al...@redhat.com>
+
+ * gimple-ssa-evrp-analyze.c (record_ranges_from_phis): Skip PHIs
+ who's result are not valid for a value_range.
+ Set type for varying value_range.
+ * ipa-cp.c (ipcp_vr_lattice::init): Set type for varying/undef
+ value_range.
+ (ipcp_vr_lattice::set_to_bottom): Same.
+ (initialize_node_lattices): Same.
+ * tree-ssa-threadedge.c (record_temporary_equivalences_from_phis):
+ Same.
+ * tree-ssanames.c (get_range_info): Same.
+ * tree-vrp.c (value_range::set_equiv): Do not set equiv on
+ undef/varying.
+ (value_range_base::value_range_base): New constructor.
+ (value_range_base::check): Remove assert for empty min/max.
+ (value_range_base::equal_p): Allow comparison of typeless undefs.
+ (value_range_base::set_undefined): Add type.
+ (value_range::set_undefined): Same.
+ (value_range_base::set_varying): Same.
+ (value_range::set_varying): Same.
+ (value_range_base::type): Remove assert.
+ (value_range_base::dump): Display type for varying/undef.
+ (value_range_base::dump): Add argument-less overload.
+ (value_range::dump): Same.
+ (vrp_val_max): Add handle_pointers argument.
+ (vrp_val_min): Same.
+ (vrp_val_is_max): Same.
+ (vrp_val_is_min): Same.
+ (value_range_base::set_and_canonicalize): Adjust so type is
+ allowed for varying/undef.
+ (ranges_from_anti_range): Same.
+ (extract_range_from_muliplicative_op): Same.
+ (extract_range_from_binary_expr): Same.
+ (extract_range_from_unary_expr): Same.
+ (vrp_prop::vrp_initialize): Same.
+ (vrp_prop::visit_stmt): Same.
+ (value_range_base::union_helper): Same.
+ (value_range_base::normalize_symbolics): Same.
+ (determine_value_range_1): Same.
+ * tree-vrp.h (value_range_base): Add value_range_base(tree type)
+ constructor.
+ Add dump (), supports_type_p,
+ value_range_base_normalize_symbolics, set_varying, and
+ set_undefined.
+ (value_range): Add set_varying, set_undefined, and dump().
+ (vrp_val_is_min): Add argument.
+ (vrp_val_is_max): Same.
+ (vrp_val_min): Same.
+ (vrp_val_max): Same.
+ (range_includes_zero_p): Adjust for varying/undef with types.
+ * vr-values.c (class type_range_cache): New.
+ (set_value_range_to_truthvalue): Adjust for varying/undef with
+ types.
+ (get_value_range): Same.
+ (vr_values::set_defs_to_varying): Same.
+ (vr_values::update_value_range): Same.
+ (extract_range_for_var_from_comparison_expr): Same.
+ (extract_range_from_binary_expr): Same.
+ (extract_range_from_cond_expr): Same.
+ (check_for_binary_op_overflow): Same.
+ (extract_range_basic): Same.
+ (extract_range_from_assignment): Same.
+ (vr_values::vr_values): Initialize type cache.
+ (vr_values::~vr_values): Free type cache.
+ (extract_range_from_phi_node): Adjust for varying/undef with
+ types.
+ * vr-values.h (class vr_values): Add type_cache.
+
2019-06-26 Jeff Law <l...@redhat.com>
+
+/* Allocate a new range from the obstack and set it to VARYING for TYPE. */
+inline value_range *
+type_range_cache::new_varying (tree type)
+{
+ /* Allocate memory. */
+ void *p = XOBNEW (&m_range_obj, value_range);
+ /* Invoke the constructors on the memory using placement new. */
+ value_range *new_p = new (p) value_range ();
+ /* Initialize it to varying. */
+ new_p->set_varying (type);
+ return new_p;
+}
So is placement new C++98/C++03 or C++11?
If the former then we can use it, if the latter we probably can't since
we haven't stepped forward to C++11.
Google isn't cooperating here to narrow the specific C++ version, but
I'm seeing some very old references to placement new, from the mid to
the late 1990s.
FWIW, the above snippet shows no warnings when compiled with -std=c++-98
-Wall.
Aldy