On 09/04/2018 07:58 AM, Richard Biener wrote:
On Mon, Sep 3, 2018 at 1:32 PM Aldy Hernandez <al...@redhat.com> wrote:
On 08/28/2018 05:27 AM, Richard Biener wrote:
On Mon, Aug 27, 2018 at 2:24 PM Aldy Hernandez <al...@redhat.com> wrote:
Howdy!
Phew, I think this is the last abstraction. This handles the unary
CONVERT_EXPR_P code.
It's the usual story-- normalize the symbolics to [-MIN,+MAX] and handle
everything generically.
Normalizing the symbolics brought about some nice surprises. We now
handle a few things we were punting on before, which I've documented in
the patch, but can remove if so desired. I wrote them mainly for myself:
/* NOTES: Previously we were returning VARYING for all symbolics, but
we can do better by treating them as [-MIN, +MAX]. For
example, converting [SYM, SYM] from INT to LONG UNSIGNED,
we can return: ~[0x8000000, 0xffffffff7fffffff].
We were also failing to convert ~[0,0] from char* to unsigned,
instead choosing to return VR_VARYING. Now we return ~[0,0]. */
Tested on x86-64 by the usual bootstrap and regtest gymnastics,
including --enable-languages=all, because my past sins are still
haunting me.
OK?
The new wide_int_range_convert_tree looks odd given it returns
tree's. I'd have expected an API that does the conversion resulting
in a wide_int range and the VRP code adapting to that by converting
the result to trees.
Rewritten as suggested.
A few notes.
First. I am not using widest_int as was done previously. We were
passing 0/false to the overflow args in force_fit_type so the call was
just degrading into wide_int_to_tree() anyhow. Am I missing some
subtlety here, and must we use widest_int and then force_fit_type on the
caller?
The issue is that the wide-ints get "converted", so it's indeed subtle.
This seems like it should be documented-- at the very least in
wide_int_range_convert.
What do you mean "converted"? I'd like to understand this better before
I write out the comment :). Do we lose precision by keeping it in a
wide_int as opposed to a widest_int?
Also, can we have the caller to wide_int_range_convert() use
wide_int_to_tree directly instead of passing through force_fit_type? It
seems force_fit_type with overflowable=0 and overflowed=false is just a
call to wide_int_to_tree anyhow.
+ || wi::rshift (wi::sub (vr0_max, vr0_min),
+ wi::uhwi (outer_prec, inner_prec),
+ inner_sign) == 0)
this was previously allowed only for VR_RANGEs - now it's also for
VR_ANTI_RANGE.
That looks incorrect. Testcase welcome ;)
See change to extract_range_into_wide_ints. VR_ANTI_RANGEs of constants
will remain as is, whereas VR_ANTI_RANGEs of symbols will degrade into
[-MIN,+MAX] and be handled generically.
Also, see comment:
+ /* We normalize everything to a VR_RANGE, but for constant
+ anti-ranges we must handle them by leaving the final result
+ as an anti range. This allows us to convert things like
+ ~[0,5] seamlessly. */
+ return (!wi::eq_p (min, wi::min_value (outer_prec, outer_sign))
+ || !wi::eq_p (max, wi::max_value (outer_prec, outer_sign)));
so you return false for VARYING? Why? I'd simply return true and
return VARYING in the new type in the path you return false.
Since symbols and VR_VARYING and other things get turned into a
[-MIN,+MAX] by extract_range_into_wide_ints, it's a lot easier to handle
things generically and return varying when the range spans the entire
domain. It also keeps with the rest of the wide_int_range_* functions
that return false when we know it's going to be VR_VARYING.
Aldy
Richard.
Second. I need extract_range_into_wide_ints to work with anti ranges of
constants. It seems like only the unary handling of CONVERT_EXPR here
uses it that way, so I believe it should go into one patch. If you
believe strongly otherwise, I could split out the 4 lines into a
separate patch, but I'd prefer not to.
Finally, I could use vr0_min.get_precision() instead of inner_precision,
but I think it's more regular and readable the way I have it.
Tested on all languages on x86-64 Linux.
OK for trunk?