This is an archive of the discontinued LLVM Phabricator instance.

This patch hijacks Danny's MemorySSA, a virtual SSA form for memory. Details on what it looks like are in MemorySSA.h
AbandonedPublic

Authored by george.burgess.iv on Jan 29 2016, 5:51 PM.

Details

Reviewers
nlewycky
hfinkel
Summary

Note: This is a continued review from D7864. I can’t figure out how to take ownership of that revision, so I made my own. Reviewers/subscribers were taken from said revision.

Changes to the prior patch:

Did a minor overhaul of the code + added tests. On the whole, the algorithms are the same.

Changes in more words:

  • Took out the update API at Danny’s request
  • Added a few tests, including the case that Hal mentioned (at multiple-backedges-hal.ll )
  • Added an abstract MemoryUseOrDef class to more cleanly separate MemoryUses from MemoryDefs
  • A few minor bug fixes
  • A few minor optimizations (took out some virtual functions, stored things in e.g. PointerIntPairs, ...)
  • Minor refactors throughout in an attempt to improve code clarity and robustness

There are a few FIXMEs scattered about that I’ll address before committing, and a few that I won’t (read: no plans to fix the FIXMEs in MemoryAccess before upstreaming this. That will probably come when MemorySSA becomes more mature/has most of its APIs ironed out and implemented).

If anything seems sketchy, please let me know. I’m about 98% sure I know how everything’s meant to work, so I could certainly be wrong. :)

Any suggestions for more test cases are appreciated, as well. I plan to add a few more prior to upstreaming, but this is more or less what I could come up with.

Old summary:

There is no grand scheme to use this across LLVM (at least, that i have).
The main purposees for it are to clean and speed up things like MemoryDependenceAnalysis
(which spends a lot of time walking to find use/defs of memory, etc), and to
be able to provide load value numbering to GVN (and PRE).
Secondarily, it may be possible to speed up some of the other load/store
motion passes using it.

Note that creation of MemorySSA is linear time and space relative to the IR
size. It uses the same linear time phi placement algorithm PromoteMemoryToRegisters does
(though sadly, not the same code because abstracting PromoteMemoryToRegisters
is not easy since we don't derive the memory access classes from things
like Value, etc)

It's lived both as a utility that passes could create and delete, and as a pass.
In the current patch, it's a functionpass that things can require
as an analysis.
Happy to put it back to being a utility, not sure which makes more sense.
I only have GVN using it right now.

As a small note: The immediate-use lists are ugly right now. Suggestions for how to do
that better welcome.

Anyway, happy to answer any questions, and not looking to commit this tomorrow,
more it got to the point where i think it would be good to get some other eyes
on it.

Diff Detail

Event Timeline

george.burgess.iv retitled this revision from to This patch hijacks Danny's MemorySSA, a virtual SSA form for memory. Details on what it looks like are in MemorySSA.h.
george.burgess.iv updated this object.
george.burgess.iv added subscribers: davidxl, hliao, anemet and 9 others.
davidxl added inline comments.Jan 29 2016, 10:06 PM
include/llvm/Transforms/Utils/MemorySSA.h
16

nit: missing period.

18

nit: missing period at the end.

186

In the context when user_begin() is called, the memoryAccess must be a def. Given that assumption, you can safely DownCast the memoryAccess to MemoryDef -- the problem is both Def and Phi need to be handled.

203

I have another suggestion of the hierarchy:

Strictly speaking a MemoryDef and MemoryUse is not the IsA relationship, but a hasA relationship -- basically a memory def is not a use, but it has any implicit may use to model the may-kill. With that in mind, it is probably not a good idea to factor out UseOrDef out as the common ancestor of MemoryDef and MemoryUse. Instead:

  1. MemoryDef should have a pointer to a memoryUse instance
  2. MemoryDef and Phi Node should have a common ancestor DefOrPhi as drawn above.

Pros: the userList can now be moved into DefOrPhi
Cons: get|setDefininingAccess method now needs to be declared as virtual in MemoryAccess base and overridden in MemoryUse and MemoryDef. For MemoryDef, it just need to forward the call to the memoryUse it owns.

To avoid virtual call, the memoryAccess can do dispatching via DownCasting depending on memoryAccess type.

333

Is this redundant? There is one in base class.

Note: You can commandeer the old revision.
In the drop down near the comment box, select "commandeer revision" and you
will take it over.

I would suggest doing that to keep the history going :)

george.burgess.iv abandoned this revision.Feb 1 2016, 11:54 AM
george.burgess.iv marked 3 inline comments as done.

Commandeered D7864, as requested.

include/llvm/Transforms/Utils/MemorySSA.h
186

Marking as done, assuming that we want to go with dannyb's "everything is a subclass of User" approach. :)

203

Marking as done, assuming that we want to go with dannyb's "everything is a subclass of User" approach.

333

Nice catch! Remnant of trying different designs.