patch to fix constant math - 4th patch - the wide-int class.

Lawrence Crowl crowl@google.com
Tue Oct 23 20:51:00 GMT 2012


On 10/23/12, Kenneth Zadeck <zadeck@naturalbridge.com> wrote:
> On 10/23/2012 02:38 PM, Lawrence Crowl wrote:
>> On 10/23/12, Kenneth Zadeck <zadeck@naturalbridge.com> wrote:
>>> On 10/23/2012 10:12 AM, Richard Biener wrote:
>>>> +  inline bool minus_one_p () const;
>>>> +  inline bool zero_p () const;
>>>> +  inline bool one_p () const;
>>>> +  inline bool neg_p () const;
>>>>
>>>> what's wrong with w == -1, w == 0, w == 1, etc.?
>>> I would love to do this and you seem to be somewhat knowledgeable
>>> of c++.  But i cannot for the life of me figure out how to do it.
>> Starting from the simple case, you write an operator ==.
>>
>> as global operator:  bool operator == (wide_int w, int i);
>> as member operator:  bool wide_int::operator == (int i);
>>
>> In the simple case,
>>
>> bool operator == (wide_int w, int i)
>> {
>>    switch (i)
>>      {
>>        case -1: return w.minus_one_p ();
>>        case  0: return w.zero_p ();
>>        case  1: return w.one_p ();
>>        default: unexpected....
>>      }
>> }
>
> no, this seems wrong.    you do not want to write code that can only
> fail at runtime unless there is a damn good reason to do that.

Well, that's because it's the oversimplified case.  :-)

>>> say i have a TImode number, which must be represented in 4 ints
>>> on a 32 bit host (the same issue happens on 64 bit hosts, but
>>> the examples are simpler on 32 bit hosts) and i compare it to -1.
>>> The value that i am going to see as the argument of the function
>>> is going have the value 0xffffffff.  but the value that i have
>>> internally is 128 bits.  do i take this and 0 or sign extend it?
>>
>> What would you have done with w.minus_one_p ()?
>
> the code "knows" that -1 is a negative number and it knows the
> precision of w.  That is enough information.  So it logically
> builds a -1 that has enough bits to do the conversion.

And the code could also know that '-n' is a negative number and do
the identical conversion.  It would certainly be more difficult to
write and get all the edge cases.

>>> in particular if someone wants to compare a number to 0xdeadbeef i
>>> have no idea what to do.  I tried defining two different functions,
>>> one that took a signed and one that took and unsigned number but
>>> then i wanted a cast in front of all the positive numbers.
>> This is where it does get tricky.  For signed arguments, you should sign
>> extend.  For unsigned arguments, you should not.  At present, we need
>> multiple overloads to avoid type ambiguities.
>>
>> bool operator == (wide_int w, long long int i);
>> bool operator == (wide_int w, unsigned long long int i);
>> inline bool operator == (wide_int w, long int i)
>>    { return w == (long long int) i; }
>> inline bool operator (wide_int w, unsigned long int i)
>>    { return w == (unsigned long long int) i; }
>> inline bool operator == (wide_int w, int i)
>>    { return w == (long long int) i; }
>> inline bool operator (wide_int w, unsigned int i)
>>    { return w == (unsigned long long int) i; }
>>
>> (There is a proposal before the C++ committee to fix this problem.)
>>
>> Even so, there is room for potential bugs when wide_int does not
>> carry around whether or not it is signed.  The problem is that
>> regardless of what the programmer thinks of the sign of the wide int,
>> the comparison will use the sign of the int.
>
> when they do we can revisit this.   but i looked at this and i said the
> potential bugs were not worth the effort.

I won't disagree.  I was answering what I thought were questions on
what was possible.

>>> If there is a way to do this, then i will do it, but it is going
>>> to have to work properly for things larger than a HOST_WIDE_INT.
>> The long-term solution, IMHO, is to either carry the sign information
>> around in either the type or the class data.  (I prefer type, but
>> with a mechanism to carry it as data when needed.)  Such comparisons
>> would then require consistency in signedness between the wide int
>> and the plain int.
>
> carrying the sign information is a non starter.    The rtl level does
> not have it and the middle end violates it more often than not.    My
> view was to design this having looked at all of the usage.   I have
> basically converted the whole compiler before i released the abi.   I am
> still getting out the errors and breaking it up in reviewable sized
> patches, but i knew very very well who my clients were before i wrote
> the abi.

Okay.

>>> I know that double-int does some of this and it does not carry
>>> around a notion of signedness either.  is this just code that has
>>> not been fully tested or is there a trick in c++ that i am missing?
>> The double int class only provides == and !=, and only with other
>> double ints.  Otherwise, it has the same value query functions that
>> you do above.  In the case of double int, the goal was to simplify
>> use of the existing semantics.  If you are changing the semantics,
>> consider incorporating sign explicitly.
>
> i have, and it does not work.

Unfortunate.

-- 
Lawrence Crowl



More information about the Gcc-patches mailing list