On Sun, Apr 21, 2013 at 10:54 PM, Kenneth Zadeck
<zad...@naturalbridge.com> wrote:
> Richard,
>
> i pulled these two frags out of your comments because i wanted to get some
> input from you on it while i addressed the other issues you raised.
>
>
>> +  enum SignOp {
>> +    /* Many of the math functions produce different results depending
>> +       on if they are SIGNED or UNSIGNED.  In general, there are two
>> +       different functions, whose names are prefixed with an 'S" and
>> +       or an 'U'.  However, for some math functions there is also a
>> +       routine that does not have the prefix and takes an SignOp
>> +       parameter of SIGNED or UNSIGNED.  */
>> +    SIGNED,
>> +    UNSIGNED
>> +  };
>>
>> You seem to insist on that.  It should propagate to the various parts
>> of the compiler that have settled for the 'uns' integer argument.
>> Having one piece behave different is just weird.  I suppose I will
>> find code like
>>
>>      wi.ext (prec, uns ? UNSIGNED : SIGNED)
>
>
> there is a lot more flexibility on my part than you perceive with respect to
> this point.   My primary issue is that i do not want to have is an interface
> that has 0 and 1 as a programmer visible part.   Beyond that i am open to
> suggestion.
>
> The poster child of my hate are the host_integer_p and the tree_low_cst
> interfaces. I did not want the wide int stuff to look like these.  I see
> several problems with these:
>
> 1) of the 314 places where tree_low_cst is called in the gcc directory (not
> the subdirectories where the front ends live), NONE of the calls have a
> variable second parameter.   There are a handful of places, as one expects,
> in the front ends that do, but NONE in the middle end.
> 2) there are a small number of the places where host_integer_p is called
> with one parameter and then it is followed by a call to tree_low_cst that
> has the value with the other sex.   I am sure these are mistakes, but having
> the 0s and 1s flying around does not make it easy to spot them.
> 3) tree_low_cst implies that the tree cst has only two hwis in it.
>
> While i do not want to propagate an interface with 0 and 1 into wide-int, i
> can understand your dislike of having a wide-int only solution for this.
>
> I will point out that for your particular example, uns is almost always set
> by a call to TYPE_UNSIGNED.  There could easily be a different type accessor
> that converts this part of the type to the right thing to pass in here.   I
> think that there is certainly some place for there to be a unified SYMBOLIC
> api that controls the signedness everywhere in the compiler.
>
> I would like to move toward this direction, but you have been so negative to
> the places where i have made it convenient to directly convert from tree or
> rtl into or out of wide-int that i have hesitated to do something that
> directly links trees and wide-int. So i would like to ask you what would
> like?

Ideally I'd like the wide-int introduction to _not_ be the introduction of
a unified symbolic way that controls signedness.  We do have two
kinds of interfaces currently - one that uses different API entries,
like build_int_cstu vs. build_int_cst or double_int::from_shwi vs. from_uhwi,
and one that uses the aforementioned integer flag 'uns' with 0 being
signed and 1 being unsigned.

I think the _uhwi vs. _shwi and _cstu variants are perfectly fine
(but only for compile-time constant uses as you say), and the wide-int
interface makes use of this kind, too.

Proposing a better API for the 'uns' flag separately from wide-int would
be a better way to get anybody else than me chime in (I have the feeling
that the wide-int series seems to scare off every other reviewer besides me...).
I can live with the SIGNED/UNSIGNED enum, but existing APIs should
be changed to use that.

For wide-int I suggest to go the route you don't want to go.  Stick to
existing practice and use the integer 'uns' flag.  It's as good as
SIGNED/UNSIGNED for _variable_ cases (and yes, a lot less descriptive
for constant cases).  For wide-int, always add a static interface
if there is a variable one and convert variable uses to the proper static
interface.

That said, a lot of my pushback is because I feel a little lonesome in this
wide-int review and don't want to lone-some decide about that (generic)
interface part as well.

>> +  template <typename T>
>> +    inline bool gt_p (T c, SignOp sgn) const;
>> +  template <typename T>
>> +    inline bool gts_p (T c) const;
>> +  template <typename T>
>> +    inline bool gtu_p (T c) const;
>>
>> it's bad that we can't use the sign information we have available in
>> almost
>> all cases ... (where precision is not an exact multiple of
>> HOST_BITS_PER_WIDE_INT
>> and len == precision / HOST_BITS_PER_WIDE_INT).  It isn't hard to encode
>> a sign - you just have to possibly waste a word of zeroes for positive
>> values where at the moment precision is an exact multiple of
>> HOST_BIST_PER_WIDE_INT and len == precision / HOST_BITS_PER_WIDE_INT.
>> Which of course means that the encoding can be one word larger than
>> maximally required by 'precision'.
>>
> Going back to point 1 above,   the front ends structure the middle end code
> where (generally) the sign that is used is encoded in the operator that one
> is looking at.    So the majority of uses in the middle end this fall into
> the second or third templates and the first template is there as a
> convenience routine for the middle ends.
> The front ends certainly use the first template.
>
> This is how the rtl level has survived so long without a sign bit in the
> modes, the operators tell the whole story.   The truth is that in the middle
> end, the story is the same - it is the operators (most of the time) that
> drive the calls being made.

With the difference RTL vs. tree that tree knows about undefined overflow
for signed plus while RTL does not (there isn't a signed plus).  And that
tree gets the operator signedness from the sign of the operands.

> There is an assumption that you are making that i certainly do not believe
> is true in the backends and i kind of doubt is true in the middle ends.
> That is that the sign of the compare ALWAYS matches the sign of the
> operands.   Given that i have never seen any code that verifies this in the
> middle end, i am going to assume that it is not true, because it is always
> true in gcc that anything that we do not explicitly verify generally turns
> out to only be generally true and you can spend your life tracking down the
> end cases.  This is a needless complication.
> At the rtl level, this is completely doomed by the GEN_INT which neither
> takes a mode or an indication of sign.   To assume that there is any
> meaningful sign information there is a horror story waiting to be written
> ("sure what could go wrong if we go into the old house?  whats that i hear,
> it sounds like a chain saw ....").

Well .. ;)  If you constructed a wide-int constant A from the signed number
-10465 and a wide-int constant B from the unsigned number 921, then
if you ask whether A is less than B then I expect the answer 'yes'.  If
you ask whether A is unsigned less than B (ltu_p) then I'd be confused
and be tempted to error out.  You should have first converted A to unsigned,
that is, zero-extend it from its precision (which in my wide-int speak
simply results in another signed but positive number).  That is,
having ltu_p interpreting a value as different value sounds wrong.

> The api that i have is independent of the rep that i happen to use inside of
> wide-ints.   The fact that it might be work is really just an accident.
> Gimple was designed (and rtl just happened) so that the operators carry the
> information that is needed.   The fact that those operators are generally
> redundant with the types is a byproduct of the strong typing of the middle
> ends.   With this respect, i think i have the right interface.

The api may be independent of the rep - but it doesn't make actual API
use independent of the information present in the rep.  If the API allows
for "mismatches", like feeding a negative value to a ltu_p call, then
I view it as inherently fragile and unclean.

That said, all numbers are part of the infinite precision signed set of numbers
and we can compare them.  And the current wide-int representation seems
to be powerful enough to place each wide-int into that number space
unambiguously.  So why not use that property to clean up the API and
make it less error-prone to use?

Richard.

> Kenny
>

Reply via email to