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





Reply via email to