This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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



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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]