<div dir="ltr"><div><span style="font-family:monospace,monospace">In the next set of small functions, the goal is to identify the (for llvm) wanted behavior related to aliasing.<br>(having a 32bit architecture in mind)<br><br>For every function, I have three fields:<br>- c++11 : my interpretation of the c++11/14 standard based on a previous mail from Richard Smith<br>     (This is: a combination of the known layout of a structure/union/array and the types)<br>     (the relevant section for the types is 3.10 10)<br>- llvm:   what does llvm deduce today<br>- future: what I would like to see in future<br> <br>The question to ask is: when should it be valid to REORDER the stores,  in the assumption <br>that after the function call, the second object is accessed (read from) in a legal way.<br>- NoAlias:   we are allowed to reorder the stores<br>- MayAlias:  we are _not_ allowed to reorder the stores<br><br>For the 'future' field, my personal guideline is that:<br>- if a union (sub)member is accessed (full path) and the union (or one of its members) contains a type that matches<br>  the other access (taking into account the access path), then aliasing must be assumed (possibly taken into account<br>  the offset/size of the access)<br><br>NOTE:  when the standard requires a MayAlias, and we provide a NoAlias, we a have 'wrong code' issue<br>       when the standard specifies a NoAlias, and we provide a MayAlias, we have a possible performance degradation.<br>NOTE2: for member array accesses of the same type, llvm will today always assume them as aliasing,<br>       even if the happen at different offsets. This is acceptable as it does not result in wrong code.<br>NOTE3: depending on the interpretation of the standard, more or less cases will have the 'MayAlias' label. I try<br>       to come with a guess on what the standard means, based on a previous mail from Richard Smith.<br>       (Richard, please comment for those cases where I made a wrong guess ;) )<br>NOTE4: it would be good if the standard can be extended with a set of examples, explicitly stating where reorderings<br>        are allowed and where not.<br>NOTE5: we probably want to have a similar behavior as 'gcc', and we assume that gcc follows the 'future' rules, but<br>       I was not able to deduce any useful information with '-fdump-tree-alias'. Probably I missed something :(<br>       I would be glad if somebody could extend this with information on how gcc treats the accesses.<br>NOTE6: In order to make unions really useful, llvm allows to read a union member with a different type than the one<br>       that was used to write it. Once we have a correct deduction of the aliasing relation, this should also work.<br><br><br></span></div><span style="font-family:monospace,monospace">So, please comment if you agree/disagree ;)<br></span><div><span style="font-family:monospace,monospace"><br></span></div><div><span style="font-family:monospace,monospace">Jeroen<br><br>--<br></span></div><div><span style="font-family:monospace,monospace"><br>// --------------------------------------<br>// plain types<br>void test_p00a(int* a, int* b)<br>{<br>  *a=1;<br>  *b=2;<br>  // c++11:   MayAlias<br>  // llvm:    MayAlias<br>  // future:  MayAlias<br>}<br><br>void test_p00b(int* a, short* b)<br>{<br>  *a=1;<br>  *b=2;<br><br>  // c++11:   NoAlias<br>  // llvm:    NoAlias<br>  // future:  NoAlias<br>}<br><br>void test_p00c(int* a, char* b)<br>{<br>  *a=1;<br>  *b=2;<br><br>  // c++11:   MayAlias<br>  // llvm:    MayAlias<br>  // future:  MayAlias<br>}<br><br><br>// --------------------------------------<br>// struct<br>struct S00 {<br>  char mC_0;<br>  short mS_1;<br>  int mI_2;<br>  int mI_3;<br>};<br><br>void test_s00a(struct S00* a, struct S00* b)<br>{<br>  a->mI_2=1;<br>  b->mC_0=2;<br><br>  // c++11:   NoAlias<br>  // llvm:    NoAlias<br>  // future:  NoAlias<br>}<br><br>void test_s00b(struct S00* a, struct S00* b)<br>{<br>  a->mI_2=1;<br>  b->mI_3=2;<br><br>  // c++11:   NoAlias<br>  // llvm:    NoAlias<br>  // future:  NoAlias<br>}<br><br>void test_s00c(struct S00* a, struct S00* b)<br>{<br>  a->mI_2=1;<br>  b->mI_2=2;<br><br>  // c++11:   MayAlias<br>  // llvm:    MayAlias<br>  // future:  MayAlias<br>}<br><br>void test_s00d(struct S00* a, int* b)<br>{<br>  a->mI_2=1;<br>  *b=2;<br><br>  // c++11:   MayAlias<br>  // llvm:    MayAlias<br>  // future:  MayAlias<br>}<br><br><br>void test_s00f(struct S00* a, short* b)<br>{<br>  a->mI_2=1;<br>  *b=2;<br><br>  // c++11:   NoAlias<br>  // llvm:    NoAlias<br>  // future:  NoAlias<br>}<br><br>void test_s00z(struct S00* a, char* b)<br>{<br>  // may alias<br>  a->mI_2=1;<br>  *b=2;<br><br>  // c++11:   MayAlias<br>  // llvm:    MayAlias<br>  // future:  MayAlias<br>}<br><br>// array member<br>// ------------<br>struct S03 {<br>  short mS_0;<br>  struct S00 mS00_1[4];<br>  short mS_2;<br>};<br><br><br>void test_s03b(struct S03* a, struct S03* b)<br>{<br>  a->mS00_1[0].mI_2=1;<br>  b->mS00_1[0].mI_3=2;<br><br>  // c++11:   NoAlias<br>  // llvm:    NoAlias<br>  // future:  NoAlias<br>}<br><br>void test_s03c(struct S03* a, struct S03* b)<br>{<br>  a->mS00_1[0].mI_2=1;<br>  b->mS00_1[1].mI_2=2;<br><br>  // c++11:   NoAlias<br>  // llvm:    MayAlias ******** performance<br>  // future:  NoAlias<br>}<br><br>// --------------------------------------<br>// Unions<br><br>// --------------------------------------<br>// Standard union U00<br>union U00 {<br>  short mS;<br>  int   mI;<br>};<br><br>void test_u00a(union U00* a, union U00* b)<br>{<br>  a->mS=1;<br>  b->mS=2;<br><br>  // c++11:   MayAlias<br>  // llvm:    MayAlias<br>  // future:  MayAlias<br>}<br><br>void test_u00b(union U00* a, union U00* b)<br>{<br>  a->mS=1;<br>  b->mI=2;<br><br>  // c++11:   MayAlias<br>  // llvm:    NoAlias  *********** wrong code<br>  // future:  MayAlias<br>}<br><br><br>void test_u00e(union U00* a, short* b)<br>{<br>  a->mS=1;<br>  *b=2;<br><br>  // c++11:   MayAlias<br>  // llvm:    MayAlias<br>  // future:  MayAlias<br>}<br><br>void test_u00f(union U00* a, short* b)<br>{<br>  a->mI=1;<br>  *b=2;<br><br>  // c++11:   MayAlias (??)<br>  // llvm:    NoAlias  *********** wrong code<br>  // future:  MayAlias<br>}<br><br>void test_u00i(union U00* a, long* b)<br>{<br>  a->mI=1;<br>  *b=2;<br><br>  // c++11:   NoAlias<br>  // llvm:    NoAlias<br>  // future:  NoAlias<br>}<br><br>void test_u00z0(union U00* a, char* b)<br>{<br>  a->mI=1;<br>  *b=2;<br><br>  // c++11:   MayAlias<br>  // llvm:    MayAlias<br>  // future:  MayAlias<br>}<br><br>// --------------------------------------<br>// union with array<br>union U03 {<br>  short mS[4];<br>  int mI;<br>};<br><br>void test_u03a(union U03* a, union U03* b)<br>{<br>  a->mS[0]=1;<br>  b->mS[0]=2;<br><br>  // c++11:   MayAlias<br>  // llvm:    MayAlias<br>  // future:  MayAlias<br>}<br><br>void test_u03b(union U03* a, union U03* b)<br>{<br>  a->mS[0]=1;<br>  b->mI=2;<br><br>  // c++11:   MayAlias<br>  // llvm:    NoAlias  ****** wrong code<br>  // future:  MayAlias<br>}<br><br>void test_u03d(union U03* a, union U03* b)<br>{<br>  a->mS[0]=1;<br>  b->mS[1]=2;<br><br>  // c++11:   NoAlias<br>  // llvm:    MayAlias   ****** performance<br>  // future:  NoAlias<br>}<br></span><br><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Mar 19, 2015 at 12:49 PM, Jeroen Dobbelaere <span dir="ltr"><<a href="mailto:jeroen.dobbelaere@gmail.com" target="_blank">jeroen.dobbelaere@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Mar 18, 2015 at 8:02 PM, Daniel Berlin <span dir="ltr"><<a href="mailto:dberlin@dberlin.org" target="_blank">dberlin@dberlin.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><div><div>[...]<span class=""><span><br></span>However, another point to consider is that, "C++ standard experts, at least on the GCC side, did not 
view this as saying "all accesses must have an explicit union access", 
but that..." may not be a reasonable reading of the standard. The text says, "If a program attempts to access the stored value of an object through a glvalue of other than one<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div style="font-family:arial,helvetica,sans-serif;font-size:10pt;color:rgb(0,0,0)"><span>of the following types the behavior is undefined: ...", and so I read that as saying that the access must be through a glvalue of an aggregate or union type (with a relevant type as one of its members). So the union or aggregate type *must* be explicitly present in the access. I don't believe any other interpretations, especially those which imply non-local effects, are reasonable.</span><br><br>Exactly what rule did GCC implement?<br></div></div></blockquote><div><br></div></span></div></div><span class=""><div>If you use an explicit union access, it assumes they alias,  otherwise, all bets are off.</div><div><br></div><div>Note: As you all know, I have really no dog in this fight, nor am i a language lawyer. Among other things, i'm an aliasing guy. I just do the edge of  what the language lawyers tell me is allowed :)</div><div><br></div></span></div></div></div>
</blockquote></div><br></div><div class="gmail_extra">I propose that we implement the same behavior in llvm.<br>I'm quite busy right now, but I'll try to come up with some examples later today for which we can then annotate what kind of behavior the standard would allow (using Richards interpretation), what gcc is doing, what we want to do.<br><br clear="all"></div><div class="gmail_extra">Greetings,<br></div><div class="gmail_extra"><br><div>Jeroen Dobbelaere<br></div>
</div></div>
</blockquote></div><br><br clear="all"><br>-- <br><div class="gmail_signature">Jeroen Dobbelaere<br></div>
</div></div></div></div></div>