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?
> > 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. jeff