[PATCH] This patch introduces MemorySSA, a virtual SSA form for memory.Details on what it looks like are in MemorySSA.h

Daniel Berlin dberlin at dberlin.org
Wed Feb 25 11:42:34 PST 2015


Also, as a natural followup, i'll pointed out  that GCC experimented with
must/may defs (IE we have MemoryMustDef to represent strong updates, and
MemoryMayDef to everything else), as well as a separate MemoryKill (for
inline assembly we didn't understand or instructions that were "clobbers of
all memory").

It also allowed for multiple "heap versions" to be live at once (To try to
reduce the length of the chains).
This required multiple memorydefs/uses on a single instruction, as well as
multiple phis

In practice, nothing used any of these distinctions to any good effect.
In the end, they all just wanted to walk the chains, and having multiple
heap versions means walking more chains (even if some are shorter), so in
the end it did not end up making the compiler faster, but it did make it
more complicated :)

After roughly 10-12 years (i forget how long it's been) of playing with
different options, GCC is also  now back to just MemoryDef and MemoryUse,
and a single heap version.




On Wed, Feb 25, 2015 at 11:32 AM, Daniel Berlin <dberlin at dberlin.org> wrote:

>
>
> On Wed, Feb 25, 2015 at 11:31 AM, Daniel Berlin <dberlin at dberlin.org>
> wrote:
>
>>
>>
>> On Wed, Feb 25, 2015 at 11:05 AM, James Molloy <james.molloy at arm.com>
>> wrote:
>>
>>> Hi Daniel,
>>>
>>> One inline comment about the design. Sorry for the naiveity.
>>>
>>> Cheers,
>>>
>>> James
>>>
>>>
>>> ================
>>> Comment at: include/llvm/Transforms/Utils/MemorySSA.h:150
>>> @@ +149,3 @@
>>> +// All defs also have a use
>>> +class MemoryDef : public MemoryUse {
>>> +public:
>>> ----------------
>>> I don't understand this: Firstly, why must all defs have a use?
>>
>>
>> So let me first give the theoretical answer:
>>
>> MemorySSA is, abstractly about heap versions.
>> Every store generates a new heap version.
>> Every use is associated with a give heap version
>> In order to be able to know what the heap version was prior to a given
>> store, the def is also a use.
>>
>>
> It is intended
>>
>          ^ not
>
>
>> to perfectly represent the semantics of the actual memory operations, but
>> give a way to have factored use-def chains over memory operations that you
>> can disambiguate without needing to walk back through all instructions in
>> the CFG to find clobbers.
>>
>>
>> Practically:
>>
>> Because you need some way to link def-def, or else you have nowhere to
>> walk if the current store is a "false def" for a given load.
>>
>> IE given
>>
>> store @a, %c
>> store @b, %d
>> load @a
>>
>> MemorySSA for this will be:
>>
>> ; 1 = MemoryDef(0)
>> store @a, %c
>> ;2 = MemoryDef(1)
>> store @b, %d
>> ;MemoryUse(2)
>> %e = load @a
>>
>> When you walk from the load at %e, you  get to the store at  2=
>> MemoryDef(1), say "does this really alias my load", get "no", and want to
>> keep going.  You can do this, because there is a def-def chain, so you go
>> from 2 = MemoryDef(1) to 1 = MemoryDef(0), ask the same question, get
>> "yes", and stop.
>>
>> If def's did not have uses, it would look like this instead:
>>
>> ; 1 = MemoryDef()
>> store @a, %c
>> ;2 = MemoryDef()
>> store @b, %d
>> ;MemoryUse(2)
>> %e = load @a
>>
>>
>> Now you do the same walk.
>> You get to the store at 2 = MemoryDef(), query whether it is a real
>> alias, get "no", and you are stuck, because you have no chain that leads
>> back to the next store :)
>>
>>
>>
>>
>> We can store without loading the resulting value back.
>>
>>
>>> Secondly, you've used inheritance which is an "is-a" relationship. Is
>>> there something fundamental I'm missing here?
>>>
>>
>>
>> All memorydefs are in fact, memoryuses as well.
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150225/9f033987/attachment.html>


More information about the llvm-commits mailing list