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 >