Kenneth Zadeck <zad...@naturalbridge.com> wrote: >On 12/16/2013 06:19 AM, Richard Biener wrote: >> On 12/15/13 7:48 PM, Kenneth Zadeck wrote: >>> On 12/15/2013 11:40 AM, Richard Sandiford wrote: >>>> Kenneth Zadeck <zad...@naturalbridge.com> writes: >>>>> it is certainly true that in order to do an unbounded set of >operations, >>>>> you would have to check on every operation. so my suggestion >that we >>>>> should remove the checking from the infinite precision would not >support >>>>> this. but the reality is that there are currently no places in >the >>>>> compiler that do this. >>>>> >>>>> Currently all of the uses of widest-int are one or two operations, >and >>>>> the style of code writing is that you do these and then you deal >with >>>>> the overflow at the time that you convert the widest-int to a >tree. I >>>>> think that it is important to maintain the style of programming >where >>>>> for a small finite number of computations do not need to check >until >>>>> they convert back. >>>>> >>>>> The problem with making the buffer size so tight is that we do not >have >>>>> an adequate reserves to allow this style for any supportable type. >>>>> I personally think that 2x + some small n is what we need to have. >>>>> >>>>> >>>>> i am not as familiar with how this is used (or to be used when all >of >>>>> the offset math is converted to use wide-int), but there appear to >be >>>>> two uses of multiply. one is the "harmless" mult by 3" and the >other >>>>> is where people are trying to compute the size of arrays. These >last >>>>> operations do need to be checked for overflow. The question >here is >>>>> do you want to force those operations to overflow individually or >do you >>>>> want to check when you convert out. Again, i think 2x + some >small >>>>> number is what we might want to consider. >>>> It's a fair question, but personally I think checking for overflow >>>> on the operation is much more robust. Checking on conversion >doesn't >>>> allow you to stop thinking about overflow, it just changes the way >you >>>> think about it: rather than handling explicit overflow flags, you >have >>>> to remember to ask "is the range of the unconverted result within >the >>>> range of widest_int", which I bet it is something that would be >easily >>>> forgotten once widest_int & co. are part of the furniture. >>>> >>>> E.g. the SPARC operation (picked only because I remember it): >>>> >>>> for (i = 0; i < VECTOR_CST_NELTS (arg0); ++i) >>>> { >>>> tree e0 = VECTOR_CST_ELT (arg0, i); >>>> tree e1 = VECTOR_CST_ELT (arg1, i); >>>> >>>> bool neg1_ovf, neg2_ovf, add1_ovf, add2_ovf; >>>> >>>> tmp = wi::neg (e1, &neg1_ovf); >>>> tmp = wi::add (e0, tmp, SIGNED, &add1_ovf); >>>> if (wi::neg_p (tmp)) >>>> tmp = wi::neg (tmp, &neg2_ovf); >>>> else >>>> neg2_ovf = false; >>>> result = wi::add (result, tmp, SIGNED, &add2_ovf); >>>> overflow |= neg1_ovf | neg2_ovf | add1_ovf | add2_ovf; >>>> } >>>> >>>> gcc_assert (!overflow); >>>> >>>> return wide_int_to_tree (rtype, result); >>>> >>>> seems pretty natural. If instead it was modelled as a widest_int >>>> chain without overflow then it would be less obviously correct. >>>> >>>> Thanks, >>>> Richard >>> Let us for the sake of argument assume that this was common code >rather >>> than code in a particular port, because code in a particular port >can >>> know more about the environment than common code is allowed to. >>> >>> My main point is that this code is in wide-int not widest-int >because at >>> this level the writer of this code actually wants to model what the >>> target wants to do. So doing the adds in precision and testing >>> overflow is perfectly fine at every step. But this loop CANNOT be >>> written in a style where you tested the overflow at the end because >if >>> this is common code you cannot make any assumptions about the >largest >>> mode on the machine. If the buffer was 2x + n in size, then it >would >>> be reasonably safe to assume that the number of elements in the >vector >>> could be represented in an integer and so you could wait till the >end. >>> >>> I think that my point was that (and i feel a little uncomfortable >>> putting words in richi's mouth but i believe that this was his point >>> early on) was that he thinks of the widest int as an infinite >precision >>> representation. he was the one who was pushing for the entire rep >to >>> be done with a large internal (or perhaps unbounded) rep because he >felt >>> that this was more natural to not have to think about overflow. >He >>> wanted you to be able to chain a mult and a divide and not see the >>> product get truncated before the divide was done. The rep that we >>> have now really sucks with respect to this because widest int >truncates >>> if you are close to the largest precision on the machine and does >not if >>> you are small with respect to that. >>> >>> My other point is that while you think that the example above is >nice, >>> the experience with double-int is contrary to this. people will >say >>> (and test) the normal modes and anyone trying to use large modes >will >>> die a terrible death of a thousand cuts. >> Well - the cases that matter in practice are >> >> 1) the things we have offset_int for - code that does bit vs. byte >> quantity calculations on addresses or address offsets. It used >> either HWI before (and probably still does, and thus is buggy) or >> double-int. The usual patter was/is to do host_integerp (t, 0) >> and then TREE_LOW_CST (t) * BITS_PER_UNIT (oops) or blindly assume >> that doing things in double-int works (which it does in practice). >> >> 2) passes that want to know whether a single operation overflows >> >> the multiple-operation and then check overflow after-the-fact is >> seldomly used - it is, mainly from the frontends which use trees >> and thus get a sticky TREE_OVERFLOW. Yes, infinite precision >> would make this work as well, and yes, originally I thought of >> basing all of wide-int on an internally infinite precision >> implementation (and luckily we are close enough that I may end >> up fixing the implementation detail to work that way ...). >> With the infinite precision internal rep you'd have explicit >> truncations and sign-/zero-extensions at the right point and >> failing to do that before conversion to tree/RTX could have been >> easily turned into ICEs saying we overflowed and nobody cared. >> >> Well. Let's see how the thing we have now works out. >richi, > >i think that you miss the point. right now on the x86-64, the max >size >is 128 +64 bits. On my private platform it is 256 + 64 bits. > >if, at the tree level, i do a widest-int multiply of two timode values >that are large with respect to their precision, i get different answers
>on the two targets. 95% of the existing trunk bugs that we fixed we >because people thought that double-int was big enough so that they did >not have to care. But what you and richard are saying is that you do >need to care (even though none of the code currently does care), but >only for rarely executed cases. With widest-int and a larger buffer we > >could can make that expectation true in all of the places where you get > >in, do some finite work and get out. In my opinion, being able to do >this is the only reason for widest-int and if this does not work >reliably, then i would be inclined to convert everything to the >explicit >precision where the definition of what is done is rock solid. >Because >to me, if the rep is not completely predictable, then it is not worth >using. At the moment we do not have the infinite precision code. We have offset._int which effectively has a precision and widest int which is indeed somewhat useless. We have fixed int where you specify your desired infinite precision which is better. Note that we have shifted the double-int host dependence to a widest-int target dependence. Which is equally bad. Richard. >Kenny > > > >> Richard. >> >>>