<div dir="ltr">FYI, <a href="http://reviews.llvm.org/D8487">http://reviews.llvm.org/D8487</a> will fix your non-union testcase.<div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Mar 20, 2015 at 11:08 AM, 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:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Fri, Mar 20, 2015 at 5:50 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:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><div><div>On Fri, Mar 20, 2015 at 9:06 AM, 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-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><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></span></div></div></blockquote><div><br></div></div></div><div>-alias is the dump for field-sensitive points-to, not "all alias info".</div><div>These are all incoming arguments, so non-IPA points-to will tell you nothing.</div><div> <br></div><div>But it does, of course, know things are in different places in each one:<br>for test3_s03c, for example, it computes:<br><div><br></div><div>a = &NONLOCAL</div><div>b = &NONLOCAL</div><div> derefaddrtmp = &NONLOCAL<br></div></div><div><div> *a + 64 = derefaddrtmp</div><div> *b + 160 = derefaddrtmp<br></div></div><div><br></div><div><div> a(D), points-to non-local, points-to vars: { }</div><div> b(D), points-to non-local, points-to vars: { }</div></div><div><br></div><div><br></div><div>IE they point to nothing locally, but may point to any non-local variable.</div><div><br></div><div><br></div><div>That is the best answer you can give these cases.</div><span><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><span style="font-family:monospace,monospace"> I would be glad if somebody could extend this with information on how gcc treats the accesses.<br></span></div></div></blockquote><div><br></div></span><div>This would be complicated.</div><div>GCC builds a simple initial memory SSA form, but isn't going to disambiguate it until an optimization asks for it to be disambiguated.</div><div><br></div><div>Since there is nothing to optimize in your cases, i can't tell you whether it thinks they alias easily.</div><div>I did take the one case you have below, and added a load, to determine aliasing.</div><span><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><span style="font-family:monospace,monospace">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><br></div></div></blockquote></span><span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><span style="font-family:monospace,monospace">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></span></div></div></blockquote><div><br></div></span><div>I actually don't understand why we get this wrong now :)<br></div></div></div></div></blockquote><div><br></div></div></div><div>One main issue is that arrays are stored as 'char' type in the tbaa struct info.<br></div><div>The access itself then starts from a unknown location inside the array. So, both the member type of an array are lost, as is the (in this case) fixed offset in the tbaa path information.<br><br>This can be fixed with a combination of improved tbaa struct information, tbaa path information and analysis (which we will need to do anyway to get the union testcases right).<br></div><span class=""><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>This should be pretty trivial offset calculation.</div><div><br></div><div>I transformed this into:<br><div>int test_s03c(struct S03* a, struct S03* b)</div><span><div>{</div><div> a->mS00_1[0].mI_2=1;</div><div> b->mS00_1[1].mI_2=2;</div></span></div><div> return a->mS00_1[0].mI_2;</div><div>}</div><div><br></div><div>To see if GCC believes the second store clobbers the first store (IE whether it thinks they alias).</div><div>It does not believe that, and will replace the return statement with "return 1";<br></div><div><br></div><div>So GCC correctly determines "NoAlias" in this case.</div><div><br></div></div></div></div></blockquote></span><div><br>ah ! that is good way to find out what gcc makes of it.<br> <br></div><span class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div></div><div>We definitely do not.</div><div><br></div><div>GVN says:<br>GVN: load i32 %7 is clobbered by store i32 2, i32* %6, align 4<br></div><div><br></div><div>and does *not* replace the return value with 1.</div><div><br></div><div>We should fix this.</div><div><br></div><div>BasicAA, sadly, has to walk backwards because it is stateless. </div><div>It would be easier to walk forwards once, compute the actual offsets being accessed by the GEPs, and map that to the loads/stores for later usage. Then it is a constant time check for struct related aliasing like this.</div><div>This isn't going to get invalidated all that often (only things like load widening/etc would change the offsets)</div><div><br></div><div><br></div><div>Anyway, i looked into BasicAA, and it fails in aliasGeps.</div><div><br>The logic in there confuses the heck out of me.<br></div><div><br></div><div>It seems to go to a lot of trouble, and steadfastly refuses to believe that if you have two pointers whose underlying object is a struct argument, and which are accessed using GEP's at provably different offsets, they can't alias.</div><div>This is wrong.</div><div><br></div><div>In the case of arguments (or identified function locals) that are struct types, it doesn't matter whether the underlying pointers are must or may alias, it matters what the offset,size of the access is.</div><div><br></div><div>In particular, there should be an else branch after this block:<br><br></div><div><div> if (PreciseBaseAlias == NoAlias) {</div></div><div><br></div><div><br></div><div>that says "if they [offsets, sizes] don't overlap different, and UnderlyingV1/V2 is an identified local, they can't alias)</div><div><br></div><div>(if it can't figure out what the underlying object is, conservatively, the right thing to do is say MayAlias)</div><div><br></div><div><br></div><div>I'll play with adding some logic here that does the right thing.</div><div><br></div><div><br></div><div>The of your answers rest looks sane to me.<br></div><div><br></div></div></div></div>
</blockquote></span></div><br><br clear="all"></div><div class="gmail_extra">Greetings,<span class="HOEnZb"><font color="#888888"><br></font></span></div><span class="HOEnZb"><font color="#888888"><div class="gmail_extra">-- <br><div>Jeroen Dobbelaere<br></div>
</div></font></span></div>
</blockquote></div><br></div>