patch to fix constant math - 4th patch - the wide-int class.
Kenneth Zadeck
zadeck@naturalbridge.com
Tue Oct 23 21:34:00 GMT 2012
On 10/23/2012 04:25 PM, Lawrence Crowl wrote:
> 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.
I am not a c++ hacker. if someone wants to go there later, we can
investigate this.
but it seems like a can of worms right now.
>
>>>> 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.
>
There is certainly a desire here not to let the ugliness of the back end
not drag down the tree level. But the truth is that with respect to
the signedness, the tree level is very dirty. If the double int code
had taken a type from the start, things may have been different. But
the truth is that sign is different than size, some of the operations do
not care about sign and some of the transformations that we want to do
we do need them to be done in a particular but that is not dependent on
the sign of the type. Richi has beat me up about this but i actually
believe that most of the time when the sign of the type does not match
the sign of the operation, the code is actually correct.
There were heroic things done at the rtl level to find the mode (and
therefor the bitsize and precision) since this is not stored in constant
integers. But doing that allows the precision and bitsize to be
reliably stored in the wide-ints. But both the tree and rtl levels
would need to significantly change to put the sign in.
More information about the Gcc-patches
mailing list