<div dir="ltr"><div><div>Hi,<br><br></div>This email is in continuation to the mail thread <a href="http://lists.llvm.org/pipermail/llvm-dev/2015-December/092996.html">http://lists.llvm.org/pipermail/llvm-dev/2015-December/092996.html</a>, to propose a new function attribute that can convey that a function maintains state, but this state is inaccessible to the rest of the program under compilation.<br><br></div>Such a flag could be added to most libc/system calls such as printf/malloc/free. (libc and system calls do access/modify internal variables such as errno).<br><div><div><br></div><div>Example attributes (in addition to what are already set):<br></div><div>malloc/free: HasInaccessibleState, ReadNone<br></div><div>printf: HasInaccessibleState, ArgMemOnly<br></div><div>realloc: HasInaccessibleState, ReadOnly (not sure).<br><br></div><div>The intention behind introducing this attribute is to relax the conditions in GlobalsAA as below:<br></div><div>(this code is in GlobalsAAResult::AnalyzeCallGraph)<br></div><div><pre>       if (F->isDeclaration()) {
         // Try to get mod/ref behaviour from function attributes.
-        if (F->doesNotAccessMemory()) {
+        if (F->doesNotAccessMemory() || F->onlyAccessesArgMemory()) {
           // Can't do better than that!
         } else if (F->onlyReadsMemory()) {
           FunctionEffect |= Ref;
           if (!F->isIntrinsic())
             // This function might call back into the module and read a global -
             // consider every global as possibly being read by this function.
             FR.MayReadAnyGlobal = true;
         } else {
           FunctionEffect |= ModRef;
           // Can't say anything useful unless it's an intrinsic - they don't
           // read or write global variables of the kind considered here.
           KnowNothing = !F->isIntrinsic();
         }
         continue;
       }</pre>This relaxation allows functions that (transitively) call library functions (such as printf/malloc) to still maintain and propagate GlobalsAA info. In general, this adds more precision to the description of these functions. <br><br></div><div>Concerns regarding impact on other optimizations (I'm repeating a few examples that Hal mentioned earlier).<br><br>1. <br>><span class="im">A readnone 
function is one whose output is a function only of its inputs, and if 
you have this:<br>
><br>
>  int *x = malloc(4);<br>
>  *x = 2;<br>
>  int *y = malloc(4);<br>
>  *y = 4;<br>
</span><span class="im">> you certainly don't want EarlyCSE to replace the 
second call to malloc with the result of the first (which it will 
happily do if you mark malloc as readnone).<br><br></span></div><div><span style="color:rgb(0,0,0)"><span class="im"><span style="color:rgb(0,0,0)">For malloc, even though ReadNone is set now (as proposed above), EarlyCSE should be taught to respect the HasInaccessibleState and not combine functions that maintain internal states.</span> <span style="color:rgb(0,0,0)">Similarly other optimizations (such as DCE) must be taught to respect the flag.</span><br><br>2.<br></span></span><span style="color:rgb(0,0,0)"><span class="im">>void foo(char * restrict s1, char * restrict s2) {<br>
>  printf(s1);<br>
>  printf(s2);<br>>}<br>
<br>>If printf is argmemonly, then we could interchange the two printf calls.<br><br></span></span></div><div><span class="im"><span style="color:rgb(0,0,0)">In this example too, printf maintains an internal state, preventing the calls from being internchanged</span>. <span style="color:rgb(0,0,0)">Also, it is now correct to add ArgMemOnly to printf as it does not access any other program memory.</span> <br><br>3.<br></span>>For malloc this is still a problem, in the following sense, if we have:<br>
><br>>  p1 = malloc(really_big);<br>>  ...<br>>  free(p1);<br>
><br>> p2 = malloc(really_big);<br>>  ...<br>> free(p2);<br>
>allowing a transformation into:<br>
>   p1 = malloc(really_big);<br>>   p2 = malloc(really_big);<br>
>    ...<br>
>   free(p1); free(p2);<br>
>could be problematic.</div><div><span class="im"><br></span></div><div><span class="im"><span style="color:rgb(0,0,0)">Both free and malloc would be marked with having an internal state. This should prevent this kind of an optimization</span>. <span style="color:rgb(0,0,0)">Note that having the ReadNone attribute should not cause problems anymore.</span><br></span></div><div><span class="im"><br></span></div><div><div><div class="gmail_signature"><div dir="ltr">  - Vaivaswatha<br></div></div></div>
</div></div></div>