I'm assuming the silence on the RFC means nobody is viscerally opposed to it, so here goes the actual implementation ;-). FWI: https://gcc.gnu.org/ml/gcc-patches/2018-10/msg00157.html My aim is no change to the current functionality, but there are some things that changed slightly (with no appreciable change in bootstrapability or tests). 1. Primarily, we were building value_ranges by modifying them in-flight with no regards to the validity of the resulting range. By enforcing the API, I noticed we periodically built VR_VARYING / VR_UNDEFINED, but left the equivalence bits uncleared. This comment in the original header file indicates that this is invalid behavior: /* Set of SSA names whose value ranges are equivalent to this one. This set is only valid when TYPE is VR_RANGE or VR_ANTI_RANGE. */ The API now enforces this upon construction. 2. I also saw us setting min/max when VARYING or UNDEFINED was set. This is invalid. Although these values were being ignored, the API now enforces this. 3. I saw one case in set_value_range_with_overflow() were we were building an invalid range with swapped ranges, where we were silently depending on somebody further up the call chain to swap them for us. I've fixed this at creation. 4. There is one assert in ipcp_vr_lattice which I hope to remove, but left as proof that the original VR_UNDEFINED set was not necessary, as it is now done by default on an empty constructor: - void init () { m_vr.type = VR_UNDEFINED; } + void init () { gcc_assert (m_vr.undefined_p ()); } One last note. The file tree-vrp.c already has a cripple API of sorts in the form of functions (set_value_range_to_varying, etc). I have tried to keep those functions available, by calling the API under the covers, but would be okay in removing them altogether as a follow-up. Please refer to the RFC wrt the min/max/vrtype accessors, as well as the new tree type field. I am quoting the class declaration below to make it easy to review at a high level. Tested on x86-64 Linux. All languages, including Ada and Go. OK for trunk? Aldy class GTY((for_user)) value_range { public: value_range (); value_range (tree type); value_range (value_range_type, tree type, tree, tree, bitmap = NULL); bool operator== (const value_range &) const; bool operator!= (const value_range &) const; void intersect (const value_range *); void union_ (const value_range *); /* Like operator== but ignore equivalence bitmap. */ bool ignore_equivs_equal_p (const value_range &) const; /* Like a operator= but update equivalence bitmap efficiently. */ void copy_with_equiv_update (const value_range *); /* Types of value ranges. */ bool undefined_p () const; bool varying_p () const; bool symbolic_p () const; bool numeric_p () const; void set_undefined (tree = NULL); void set_varying (tree = NULL); /* Equivalence bitmap methods. */ bitmap equiv () const; void set_equiv (bitmap); void equiv_free (); void equiv_copy (const value_range *); void equiv_clear (); void equiv_and (const value_range *); void equiv_ior (const value_range *); /* Misc methods. */ tree type () const; bool null_p () const; bool may_contain_p (tree) const; tree singleton () const; void set_and_canonicalize (enum value_range_type, tree, tree, tree, bitmap); void dump () const; /* Temporary accessors that should eventually be removed. */ enum value_range_type vrtype () const; tree min () const; tree max () const; private: void set (value_range_type, tree type, tree, tree, bitmap); void check (); bool equal_p (const value_range &, bool ignore_equivs) const; enum value_range_type m_vrtype; public: /* These should be private, but GTY is a piece of crap. */ tree m_min; tree m_max; tree m_type; /* Set of SSA names whose value ranges are equivalent to this one. This set is only valid when TYPE is VR_RANGE or VR_ANTI_RANGE. */ bitmap m_equiv; };