patch: add readonly argument attribute

Nick Lewycky nicholas at mxc.ca
Fri Jul 5 15:39:30 PDT 2013


Chris Lattner wrote:
> Hi Nick, here's a quick concept review:
>
> On Jul 3, 2013, at 9:27 PM, Nick Lewycky<nlewycky at google.com>  wrote:
>> The attached patch implements support for 'readonly' and 'readnone' on individual pointer-typed attributes. The llvm memcpy/memmove intrinsics are given readonly on their source pointers, and FunctionAttrs is updated to label known functions with readonly/readnone where appropriate, as well as deduce the attributes from function bodies. The semantics are described in the patch to LangRef.
>
> Ok, how does this compare to AliasAnalysis::ModRefBehavior?  Can we merge those concepts into this eventually?

They're the same concepts, but of course stored on the IR. readnone maps 
to NoModRef, readonly maps to Ref.

>> These attributes don't permit any new optimization of the function to which they are applied. They do allow optimization to be applied in the caller of the function, when the pointer has not otherwise escaped.
>>
>> 'readonly' can be used to allow store-load propagation and load-load folding across calls. It requires knowing that the callee can't have the pointer through some other means (we already have capture tracking). This shows up a lot in of C++ code that takes a "const Foo&" argument.
>>
>> 'readnone' is really just along for the ride since I'm adding 'readonly' anyways, but if you'd like a justification it means the pointer isn't dereferenced but may be compared. Consider std::set<char*>, which requires a comparison operator<(char *lhs, char *rhs); That function would have 'readnone' on lhs and rhs. Furthermore, a nocapture readnone argument is a dead argument.
>
> Sure, these seem fine.  If you complete the set with a "readwrite" and "writeonly" attribute, you can more precisely model mod/ref behavior, and would allow you to introduce a function attribute analogous to "OnlyAccessesArgumentPointees".  This would basically say that the function/intrinsic *only* affects declared arguments, not global memory.

Sure, but even that isn't perfect. There are still cases like "the only 
global it touches is errno" or "only reads the rounding mode and its 
arguments". With ModRefBehavior you can install your own AliasAnalysis 
that's familiar with the relevant functions.

It took me a while to figure out what "writeonly" is good for. The 
challenge is that it doesn't state that it overwrites the whole object 
so you can't DSE against it, and the call might have other side-effects 
so you can't eliminate the call or the argument. What we can do is skip 
the call when DSE'ing upwards from the end of the pointer lifetime. That 
lets us delete both stores in:
   %A = alloca
   store to %A
   call @function(writeonly %A)
   store to %A
   ret
but not the alloca or the call to @function.

Also, I'd rather not have an explicit 'readwrite' and just leave that 
the default for unattributed arguments.

> Modeling these things properly would be useful for a lot of things, and should allow elimination of some of the special cases for intrinsics at the end of BasicAliasAnalysis::getModRefInfo.

Absolutely. Right now I have a pressing need for 'readonly' 
specifically, but I agree with the direction here.

Nick



More information about the llvm-commits mailing list