On Sat, Aug 19, 2017 at 1:04 PM, Ivan A. Kosarev via llvm-dev < llvm-dev at lists.llvm.org> wrote:> Daniel, > > >> the type of (*x) is not compatible with the type of (*b) or, > >> recursively, type of b->i. Similarly, the type of (*b) is not > >> compatible with (*x) or, recursively, x->i. > ... > > I think these are interesting interpretations. I'm not sure > > i'd personally agree with them (and there are definitely > > compilers out there that do not). > > I wonder how you know that those compilers interpret it differently.I know how to produce internal pass dump files and debug output from a lot of compilers (XLC, ICC, GCC, etc) So i'm staring at the debug output to see what it says.> Would you mind if we proceed with concrete examples from this point? > > I don't believe we are ever going to agree, so i'm not sure there is apoint.> These two accesses are allowed overlap as the type of b->a is compatible > with the type of (*x).Errr, previously you split the access into one, and said it's about whether each part is compatible. So i assume then you also believe *b is compatible with *x here?> I should admit I don't see what makes this case special. Can you elaborate > please? >Honestly? I don't find your answers that consistent with the rules. I do not feel you have explained *why* you find these types "incompatible" (the rules only talk about direct compatibility as one option). You have just asserted they are so. But i also don't really have a strong desire to argue about TBAA, as people often do not agree on the answers. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170819/cf1ab8d7/attachment.html>
On Sat, Aug 19, 2017 at 1:36 PM, Daniel Berlin <dberlin at dberlin.org> wrote:> > > On Sat, Aug 19, 2017 at 1:04 PM, Ivan A. Kosarev via llvm-dev < > llvm-dev at lists.llvm.org> wrote: > >> Daniel, >> >> >> the type of (*x) is not compatible with the type of (*b) or, >> >> recursively, type of b->i. Similarly, the type of (*b) is not >> >> compatible with (*x) or, recursively, x->i. >> ... >> > I think these are interesting interpretations. I'm not sure >> > i'd personally agree with them (and there are definitely >> > compilers out there that do not). >> >> I wonder how you know that those compilers interpret it differently. > > > I know how to produce internal pass dump files and debug output from a lot > of compilers (XLC, ICC, GCC, etc) > So i'm staring at the debug output to see what it says. > >Also, in the case of GCC specifically, i wrote a large amount of it's current aliasing infrastructure, so i have scripts to use the debugger to print out the tbaa tree nicely from the in-memory structure. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170819/d4376964/attachment.html>
Hello Daniel, >>>> the type of (*x) is not compatible with the type of (*b) or, >>>> recursively, type of b->i. Similarly, the type of (*b) is >>>> not compatible with (*x) or, recursively, x->i. >> ... >>> I think these are interesting interpretations. I'm not sure >>> i'd personally agree with them (and there are definitely >>> compilers out there that do not). >> >> I wonder how you know that those compilers interpret it >> differently. If the correct answer for a specific case is >> "no alias", then reloading of values does not say anything >> about how authors interpret the cited clause. >> >> It's only omission of reloading that does matter. > > I know how to produce internal pass dump files and debug output > from a lot of compilers (XLC, ICC, GCC, etc) > So i'm staring at the debug output to see what it says. Sorry, what I'm trying to determine here is whether observed facts contradict with either or both of the interpretations. I would appreciate if you can help me with this so once it is settled, we can proceed with resolving outstanding TBAA issues. So once again, if for a specific case the correct answer is "no alias", then how you know by looking at the generated code, dump files and debug output what way the authors interpret the clause? You said that there are compilers that definitely do not agree with that 'a->i' and 'b->i' may not overlap if the types of (*a) and (*b) are not compatible. Can we know how you came to this conclusion? Can you provide specific examples? > It's not clear GCC agrees with my interpretation. I can get it > to seem to answer both ways. Let's consider this as a specific example: https://bugs.llvm.org/show_bug.cgi?id=8572 and keeping in mind your experience: > Also, in the case of GCC specifically, i wrote a large amount > of it's current aliasing infrastructure, so i have scripts to > use the debugger to print out the tbaa tree nicely from the > in-memory structure. Do you treat that gcc behavior as intentional or a bug? Do you think we should file a defect report and ask gcc developers to fix it so that the code like this shall preserve its cycles? >> These two accesses are allowed overlap as the type of b->a is >> compatible with the type of (*x). > > Errr, previously you split the access into one, and said it's > about whether each part is compatible. > So i assume then you also believe *b is compatible with *x > here? Let me repeat the example: struct A { int i; } *x; struct B { struct A a; } *b; b->a x->i And the wording: An object shall have its stored value accessed only by an lvalue expression that has one of the following types: - a type compatible with the effective type of the object, - a qualified version of a type compatible with the effective type of the object, - a type that is the signed or unsigned type corresponding to the effective type of the object, - a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object, - an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or - a character type. The answer to your question is: (*b) need not to be compatible with (*x) for accesses b->a and x->i to be allowed to overlap, because the type of (*b) is an aggregate that includes the type of (*x) among its members, which is exactly what the Standard says. Here's the full analysis: B is not compatible with A or A::i. And A is not compatible with B, but it is compatible with B::a. Now back you your previous examples: struct A { int i; } *a; struct B { struct A a; } *b; struct X { int i; } *x; a->i x->i Here A is not compatible with X or X::i and X is not compatible with A or A::i. Therefore, no alias. b->a.i x->i B is not compatible with X or X::i and X is not compatible with B, B::a or B::a::i. No alias. Now, > I don't find your answers that consistent with the rules. can you tell me what exactly looks inconsistent in the analysis of these three cases? Also, I wonder what makes you thinking that by lvalue access in this quote we should mean only the final lvalue access? How any other lvalues accesses are different? > I do not feel you have explained *why* you find these types > "incompatible" (the rules only talk about direct compatibility > as one option). > You have just asserted they are so. Can you expand on this? Which of these three types A, B and X you think/suspect are compatible and why? Thanks, --
Hello Daniel, Like gcc, icc says "no alias", except when the members we access are part of the common initial sequence so it seems they treat it as if we were accessing the members through a union, which in turn looks like a way to handle the problem with taking pointers to union members. We know that gcc makes no guarantees about dereferencing of such pointers and so can afford the luxury of further optimizations regardless of how accessed members relate to common initial sequences. Either way, they clearly do not think that these accesses may alias because base types have members of the same type. https://godbolt.org/g/jqn7GC struct BUF1 { char x[8]; int b1; }; struct BUF2 { char x1[7]; char x2; int b2; }; int foo(int n, struct BUF1* p, struct BUF2* q) { for (int i = 0; i < n; i++) p->b1 += q->b2; return 0; } icc -Os results in: foo(int, BUF1*, BUF2*): test edi, edi #16.25 jle ..B1.3 # Prob 0% #16.25 inc edi #16.5 mov eax, DWORD PTR [8+rsi] #17.9 mov edx, DWORD PTR [8+rdx] #17.18 sub eax, edx #17.9 imul edx, edi #16.5 add eax, edx #17.9 mov DWORD PTR [8+rsi], eax #17.9 ..B1.3: # Preds ..B1.1 ..B1.2 xor eax, eax #18.12 ret #18.12 Thanks, --
On Sun, Aug 20, 2017 at 2:47 AM, Ivan A. Kosarev via llvm-dev < llvm-dev at lists.llvm.org> wrote:> Hello Daniel, > > >>>> the type of (*x) is not compatible with the type of (*b) or, > >>>> recursively, type of b->i. Similarly, the type of (*b) is > >>>> not compatible with (*x) or, recursively, x->i. > >> ... > >>> I think these are interesting interpretations. I'm not sure > >>> i'd personally agree with them (and there are definitely > >>> compilers out there that do not). > >> > >> I wonder how you know that those compilers interpret it > >> differently. If the correct answer for a specific case is > >> "no alias", then reloading of values does not say anything > >> about how authors interpret the cited clause. > >> > >> It's only omission of reloading that does matter. > > > > I know how to produce internal pass dump files and debug output > > from a lot of compilers (XLC, ICC, GCC, etc) > > So i'm staring at the debug output to see what it says. > > Sorry, what I'm trying to determine here is whether observed facts > contradict with either or both of the interpretations. I would appreciate > if you can help me with this so once it is settled, we can proceed with > resolving outstanding TBAA issues. >I really don't have the energy to keep going around on this.> > So once again, if for a specific case the correct answer is "no alias", > then how you know by looking at the generated code, dump files and debug > output what way the authors interpret the clause? >Because i can get the compilers to print, explicitly, what their interpretation of tbaa is.> > You said that there are compilers that definitely do not agree with that > 'a->i' and 'b->i' may not overlap if the types of (*a) and (*b) are not > compatible.This is actually not what i said at all. Because we disagree as to whether they are compatible. You are asserting "compatibility" as if the rules are easy and everyone must agree with your interpretation, but this is not the case. I'm not sure why you find that surprising, it's been the case forever that people disagree on interpretations of these rules.> Can we know how you came to this conclusion? Can you provide specific > examples? > >This conversation is becoming both frustrating, energy eating, and honestly, not worth arguing about as there is simply no objective truth to TBAA rules. So i'm going to bow out. Please feel free to do whatever you think is right, that users are happy with, and that you document and test very well. Thanks, Dan -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170820/c074d178/attachment.html>