[llvm-dev] [RFC] Adding a globalmemonly attribute for functions that only access global memory

Johannes Doerfert via llvm-dev llvm-dev at lists.llvm.org
Tue Sep 14 12:00:45 PDT 2021


On 9/14/21 1:03 PM, Philip Reames wrote:
>
> On 9/14/21 9:50 AM, Johannes Doerfert via llvm-dev wrote:
>> Hi Nicolai,
>>
>> On 9/13/21 11:59 AM, Nicolai Hähnle via llvm-dev wrote:
>>> Hi Mugilan,
>>>
>>> I think this is an interesting direction. I've recently put some 
>>> thought
>>> into the memory attributes you mention for unrelated reasons, and found
>>> that the various XYZonly attributes don't compose well, while noXYZ
>>> attributes compose better.The reason is simple. With what you're 
>>> proposing,
>>> we end up with:
>>>
>>> * argmemonly
>>> * inaccessiblememonly
>>> * inaccessibleorargmemonly
>>> * globalmemonly
>>>
>>> There are 4 attributes talking about 3 types of memory. Clearly, 
>>> there are
>>> orthogonality issues. First of all, glancing at your patch, your new
>>> attribute should really be called inaccessibleorglobalmemonly. What if
>>> somebody wants argorglobalmemonly? Do they add yet another 
>>> attribute? That
>>> way lies madness.
>>
>> Agreed. We actually wanted to use this to make the point that we
>> need to switch up the scheme :)
>>
>> That said, I think the handling of globalmemonly should be discussed
>> and merged (after refinement) as it will be reused whatever the later
>> scheme will be.
>>
>>
>>> If we instead take a step back, we can recognize that there are 
>>> different
>>> "paths" of accessing memory:
>>>
>>> * arg
>>> * global
>>> * inaccessible
>>> * indirect (i.e., via a pointer loaded from memory)
>>> * other (e.g., pointer returned by black box function)
>>>
>>> These could map very nicely onto noXYZ attributes. You end up 5 
>>> attributes:
>>> noargmem, noglobalmem, noinaccessiblemem, noindirectmem, noothermem. 
>>> Nicely
>>> composable, in particular today's attribute are mapped as follows:
>>>
>>> * argmemonly -> noglobalmem noinaccessiblemem noindirectmem noothermem
>>> * inaccessiblememonly -> noargmem noglobalmem noindirectmem noothermem
>>> * inaccessibleorargmemonly -> noglobalmem noindirectmem noothermem
>>> * globalmemonly -> noargmem noindirectmem noothermem (remember, you 
>>> seem to
>>> want to allow access to inaccessible memory here)
>>>
>>> More importantly, the 5 attributes can express any future desired
>>> combination, e.g. a function that accesses memory through argument
>>> pointers, and through pointers loaded from there (transitively) is:
>>> noglobalmem noinaccessiblemem noothermem
>>>
>>> Thoughts?
>>
>> I was thinking we go with a bitfield but otherwise I'm with you. This
>> is the Attributor AAMemoryLocation encoding:
>>
>> ```
>>     /// Encoding of different locations that could be accessed by a 
>> memory
>>     /// access.
>>     enum {
>>      ALL_LOCATIONS = 0,
>>      NO_LOCAL_MEM = 1 << 0,
>>      NO_CONST_MEM = 1 << 1,
>>      NO_GLOBAL_INTERNAL_MEM = 1 << 2,
>>      NO_GLOBAL_EXTERNAL_MEM = 1 << 3,
>>      NO_GLOBAL_MEM = NO_GLOBAL_INTERNAL_MEM | NO_GLOBAL_EXTERNAL_MEM,
>>      NO_ARGUMENT_MEM = 1 << 4,
>>      NO_INACCESSIBLE_MEM = 1 << 5,
>>      NO_MALLOCED_MEM = 1 << 6,
>>      NO_UNKOWN_MEM = 1 << 7,
>>      NO_LOCATIONS = NO_LOCAL_MEM | NO_CONST_MEM | 
>> NO_GLOBAL_INTERNAL_MEM |
>>                     NO_GLOBAL_EXTERNAL_MEM | NO_ARGUMENT_MEM |
>>                     NO_INACCESSIBLE_MEM | NO_MALLOCED_MEM | 
>> NO_UNKOWN_MEM,
>>     }
>> ```
>>
>> I was thinking to use this, or a variation of that, as the argument 
>> of an attribute. Thus,
>>   `access_locations(~(NO_GLOBAL_MEM | NO_ARGUMENT_MEM))`
>> to express argument and global memory is potentially accessed.
>>
>> That said, I *also* want us to allow to use this interface for 
>> "special memory locations".
>> What I mean is for example a special "location" for things like 
>> intrinsics:
>>   `llvm.assume` writes only to bit "LLVM_ASSUME_MEM"
>>   `llvm.launder.invariant.group` writes only to bit 
>> "LLVM_LAUNDER_INVARIANT_GROUP" (D109548)
>>   ...
>> This way they stop to interfere with each other and other effects.
>
> This last piece reads like a separate change to me.  I wouldn't want 
> to tie the inversion with this extension.

My hope was to do this step by step.

So actually advance something with this patch set and start the 
discussion for a generalization.

If we decide right away to change the global handling we might skip 
parts of this patch set though.


> Having said that, let me bike shed your separate proposal.  :)
>
> If we had an attribute which allowed a specific list of globals 
> potentially aliased, and introduced a set of predefined symbolic 
> global names, we could solve this use case and also handle the more 
> general "but this function has a known aliasing set!" use case as 
> well.  In pseudo IR, consider:
>
> @G = external global i32
>
> declare void @restricted() globalmayalias(@G, @llvm.assume_control)
>
> In fact, the original motivation for the globalmemonly proposal could 
> be alternatively solved with:
>
> @errno = external global i32
>
> declare void @mathfunc(float, float) globalmayalias(@errno)
>
I like this, it solves almost all the "global memory" use cases with 
more precision than the proposal here.
IIRC, this was what I proposed to Mugilan first but we figured it might 
be easier to do it in multiple steps.

That said, I'd also want us to use explicit enumartations or 
`argmemonly` and `inaccessiblememonly`:
   `accessed_args(/* ArgNo */ 0, /* ArgNo */ 3)`
   `accessed_inaccessible_mem(/* ALL */ -1)`
   `accessed_inaccessible_mem(/* llvm.assume_control */ 0x01)`

Maybe if we have globalmayalias and the "control" bits are internal we 
might not need inaccessible memory anymore, that would be even better.

~ Johannes


>>
>> I hope this makes some sense.
>>
>> ~ Johannes
>>
>>
>>
>>>
>>> Cheers,
>>> Nicolai
>>>
>>> On Sat, Sep 11, 2021 at 9:16 PM Mugilan Ganesan via llvm-dev <
>>> llvm-dev at lists.llvm.org> wrote:
>>>
>>>> Hello everyone,
>>>>
>>>> We propose the addition of a GlobalMemOnly attribute to LLVM.
>>>>
>>>> Definition:
>>>>
>>>> This attribute indicates that the only memory accessed inside a 
>>>> function,
>>>> that is visible to the callee, is global memory. If the function 
>>>> reads or
>>>> writes other memory that is visible to the callee, the behavior is
>>>> undefined.
>>>>
>>>> Motivation:
>>>>
>>>> Memory attributes already exist for specifying the memory locations
>>>> accessed by a function, such as ArgMemOnly and InacessibleMemOnly.
>>>> Similarly, there are attributes for describing memory behaviour, 
>>>> such as
>>>> ReadOnly and WriteOnly.
>>>>
>>>> However, no attributes exist for differentiating the types of memory
>>>> objects that functions can access, such as global objects and objects
>>>> created by alloca. We would like to start by introducing an 
>>>> attribute to
>>>> deal with functions that only access global objects.
>>>>
>>>> The addition of the GlobalMemOnly attribute can benefit LLVM as 
>>>> follows:
>>>>
>>>> 1. Improves Alias Analysis, since this information can be used to 
>>>> improve
>>>> the determination of aliasing between functions and memory 
>>>> locations that
>>>> point to global objects.
>>>>
>>>> 2. Provides Transforms with greater information: many math lib 
>>>> calls only
>>>> modify the global variable errno. Unnecessary loads of the call 
>>>> arguments
>>>> can therefore be removed, since the calls will have no side-effects 
>>>> on them.
>>>>
>>>> Patches Overview:
>>>>
>>>> 1. Definition of GlobalMemOnly in the AsmParser, IR, and LLVM 
>>>> Bitcode. It
>>>> is also defined in the LangRef.
>>>>
>>>> https://reviews.llvm.org/D109644
>>>>
>>>> 2. Support is added to Alias Analysis. If a function is 
>>>> GlobalMemOnly and
>>>> a memory location does not point to a global object, getModRefInfo can
>>>> infer that no aliasing between the function and the location can 
>>>> occur.
>>>> This patch also adds a regression test for BasicAA.
>>>>
>>>> https://reviews.llvm.org/D109647
>>>>
>>>> 3. Certain math lib calls are assigned GlobalMemOnly, since they only
>>>> modify the global variable errno. These calls include common 
>>>> functions,
>>>> such as atan, exp, and log.
>>>>
>>>> https://reviews.llvm.org/D109648
>>>>
>>>> Please let us know of any thoughts you may have regarding this 
>>>> attribute’s
>>>> implementation and use cases. We believe that it can strengthen LLVM’s
>>>> alias analysis and optimization passes if added.
>>>>
>>>> Thanks,
>>>> Mugilan
>>>> _______________________________________________
>>>> LLVM Developers mailing list
>>>> llvm-dev at lists.llvm.org
>>>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>>>
>>>
>>>
>>> _______________________________________________
>>> LLVM Developers mailing list
>>> llvm-dev at lists.llvm.org
>>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>> _______________________________________________
>> LLVM Developers mailing list
>> llvm-dev at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev


More information about the llvm-dev mailing list