This is an archive of the discontinued LLVM Phabricator instance.

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

Authored by george.burgess.iv on Feb 24 2015, 12:11 PM.

Details

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

There are a very large number of changes, so older changes are hidden. Show Older Changes
reames added inline comments.Feb 25 2015, 10:01 AM
include/llvm/Transforms/Utils/MemorySSA.h
13

This comment will need to be expanded at some point. That can wait until the code is closer to ready though.

Correction, the comment I wanted was below. Might make sense to move some of it into the file comment or provide a forward reference.

31

I would phrase this as: links together memory access instructions such as loads, stores, ...

92

I might avoid the term "Type" here since that has a well defined meaning in LLVM. Using AccessType consistently would be clearer.

108

A bounds assertion here would be good.

130

The term "UseOperand" isn't clear to me here. Is this the link back to a def or phi?

156

I'm not sure we need an explicit def version here. Doesn't the address of the underlying instruction serve that purpose as well? (And when that instruction disappears, we need to renumber anyways.)

Thanks so much for taking a look at what i've got so far!

Hi Daniel,

One inline comment about the design. Sorry for the naiveity.

Cheers,

James

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

I don't understand this: Firstly, why must all defs have a use? 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?

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.

Update for commments received so far.

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

dberlin added inline comments.Feb 25 2015, 2:13 PM
include/llvm/Transforms/Utils/MemorySSA.h
13

fixed

31

fixed

92

Fixed

156

fixed in version i'm about to upload

This does make debugging a bit harder (IMHO), but such is life :)

Reserve space for args

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

Initialize Use lists
Fix bug in getClobberingMemoryAccess

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

hfinkel added inline comments.Feb 27 2015, 1:18 PM
lib/Transforms/Utils/MemorySSA.cpp
87

What exactly does "updated to handle call instructions properly" mean? Also, this looks like it should be a member function of AA. Can you please add it there (then we can update MDA to use it too?).

101

Part of my confusion is this: What does the call's return value have to do with the memory location(s) accessed by the call?

We do have these in AA:

static Location getLocationForSource(const MemTransferInst *MTI);
static Location getLocationForDest(const MemIntrinsic *MI);

and I imagine those would be good to use here.

But for generic calls, we don't have any facility to get a location, or list of locations, touched by the call. We can do call-site vs. call-site queries, and call-site vs. Location queries, however.

137

Can you please define here what a "false" version is? (non-aliasing?)

242

I'm likely missing something here, but why don't you just call AA->getModRefInfo for all types of instructions? The overload for Instruction* handles all of the various types:

/// getModRefInfo - Return information about whether or not an instruction may
/// read or write the specified memory location.  An instruction
/// that doesn't read or write memory may be trivially LICM'd for example.
ModRefResult getModRefInfo(const Instruction *I,
                           const Location &Loc) {
  switch (I->getOpcode()) {
  case Instruction::VAArg:  return getModRefInfo((const VAArgInst*)I, Loc);
  case Instruction::Load:   return getModRefInfo((const LoadInst*)I,  Loc);
  case Instruction::Store:  return getModRefInfo((const StoreInst*)I, Loc);
  case Instruction::Fence:  return getModRefInfo((const FenceInst*)I, Loc);
  case Instruction::AtomicCmpXchg:
    return getModRefInfo((const AtomicCmpXchgInst*)I, Loc);
  case Instruction::AtomicRMW:
    return getModRefInfo((const AtomicRMWInst*)I, Loc);
  case Instruction::Call:   return getModRefInfo((const CallInst*)I,  Loc);
  case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc);
  default:                  return NoModRef;
  }
}
270

Why are you printing the instruction addresses here? Would it be more useful to print *I?

358

Range-based for?

412

Range-based for using succ_range?

436

Range-based for here?

491

Range-based for?

540

Range-based for?

556

Maybe add here?

assert(!DT->isReachableFromEntry(BB) &&
            "Reachable block found while handling unreachable blocks");
614

Range-based for?

636

Range-based for?

638

Range-based for?

652

You're testing against an empty location? I don't think this is what you want, how about using this:

/// getModRefBehavior - Return the behavior when calling the given call site.
virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS);
688

in to -> into

689

But you don't really insert anything into the IR proper. I'd rephrase this.

718

No need for { } here.

730

Range-based for?

738

Range-based for? And you don't need the { } here.

771

Range-based for?

781

Range-based for?

Comment at: lib/Transforms/Utils/MemorySSA.cpp:357
@@ +356,3 @@
+ unsigned ID = 0;
+ for (auto I = F.begin(), E = F.end(); I != E; ++I)

+ BBNumbers[I] = ID++;

Range-based for?

BTW, at least the obvious construction of that for( auto I : F) gives:
../lib/Transforms/Utils/MemorySSA.cpp:350:13: error: call to deleted
constructor of 'llvm::BasicBlock'

for (auto I : F)
          ^ ~

../include/llvm/IR/BasicBlock.h:85:3: note: 'BasicBlock' has been
explicitly marked deleted here

BasicBlock(const BasicBlock &) = delete;
^

Is there some way to iterate over basic block instructions using range
based for that we've added?

dberlin updated this revision to Diff 20966.Mar 1 2015, 2:24 PM

Update for review comments (though not quite ready for re-review, need to document a few changes better)

Also handle call caching and clobbering better

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

majnemer added inline comments.
include/llvm/Analysis/AliasAnalysis.h
155–156 ↗(On Diff #20966)

No need for else here.

include/llvm/Transforms/Utils/MemorySSA.h
2–3

This looks strange, can you make it look like the other files?

lib/Transforms/Utils/MemorySSA.cpp
2

No need for this whitespace.

dberlin updated this revision to Diff 21154.Mar 3 2015, 4:03 PM

Move state into a structure, clean up a bit, and use structure to stop abusing Loc.Ptr as storage

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

hfinkel added inline comments.Mar 4 2015, 3:23 PM
lib/Transforms/Utils/MemorySSA.cpp
238

I had also been thinking that the logic of this else block could be moved into a utility function of AliasAnalysis. It seems to be that this is exactly what you'd want

AA->getModRefInfo(Inst1, Inst2)

to mean. Do you agree?

Add a dominance verifier, make a new alias analysis API and use it, fix a small bug in incomplete phi handling

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

Bug fix i had forgotten to commit locally

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

Add dump and verify options so we can use them for tests
Write basic tests
Remove compute live in, it's useless for memory ssa (everything is live-in since defs are uses)

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

Make MemorySSA able to be lazy, and add a non-lazy pass for tests to use
Separate out walking interface, move caching walker to use it

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

This is looking reasonable complete. Any chance we could land it in it's current form and evolve it in tree? Tracking changes is becoming quite hard.

Using this to implement a simple cross block DSE might be an interesting proof of concept. I'm not set on that idea, but it would be nice to have something in tree to show this actually working. Once we have that, we can migrate other passes to it one by one.

Update API, fix all documentation, fix use list bugs
Should be ready enough now.

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

Trigger an update so phabricator resends this review email.
This code should now be ready to go in.

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

Update MemorySSA API to allow specifying where insertion occurs

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

Update linear time phi placement algorithm for bug fixes
Add an API for adding memory uses

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

Just a friendly ping. I think i've addressed all previous comments on
MemorySSA, and have patches ready to make it used in-tree (see the
MergedLoadStoreMotion rewrite. I also have a MemCpyOptimizer rewrite
in progress).

Ok, this review excludes MemorySSA.cpp. I'll come back to that in a separate pass shortly.

I see a bunch of small issues, but nothing so far that absolutely needs to be addressed before submission. Given that a) this is an off by default change, and b) the author is a long established trusted committer, I have no problem with review comments being addresses as this evolves further in tree.

When you do submit, please separate the AA changes into their own submission. It should go in a few days before the memorySSA so that we can identify breakage in isolation.

I would also strongly prefer to see more test cases included. If nothing else, having a set of small examples for the semi obvious cases would make the usage of memory ssa much easier to understand.

include/llvm/Analysis/AliasAnalysis.h
374 ↗(On Diff #23347)

I might make this a switch so that all the cases are obviously covered and checked by the compiler.

508 ↗(On Diff #23347)

This seems like a subset of the getModRefInfo interface. Is there a strong reason it needs to be phrased differently?

include/llvm/IR/Function.h
548

Again, submit separately please.

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

Given clobbers aren't instructions, please phrase this as:
such as loads, stores, and calls, and atomics.

Also, you *really* need to update this comment to include the bits about only mayalias accesses being on the immediate use list. This is badly needed to prevent confusion.

62

This comment is now explicitly wrong.

101

Should this be part of the public interface?

118

Aren't all of these actually users not uses? Not sure there's a real distinction for memory SSA, but this might be slightly confusing by analogy to normal def-use. If there is no difference, maybe add a comment that clarifies that?

One possible interesting case, what happens if you have a partially overlapping memcpy? Is that a single user or two uses?

133

Why do these need to be friends? Shouldn't protected access be enough? I *really* dislike having friend declarations here unless they're absolutely necessary.

149

"find" seems like the wrong name here. Possible hasUse?

154

Should this possibly be a pure virtual function? 0 doesn't seem overly meaningful here.

196

Again, does this need to be public?

228

Define clobber. Preferrably using mayalias terminology. References to AA docs are fine.

261

Is this still true with the mayalias changes? If so, how does that work? Respond as a comment in code please.

270

Should this be called on a phi? Maybe llvm_unreachable?

293

Move definition to cpp please.

327

Args seems like a confusing name here. What does the PHINode class call these? Use that for consistency please.

408

When should this (and the next few routines) be used?

430

Hopefully, this is checked in an assertion somewhere?

540

Can you expand this comment? From the naming, it's not clear when I'd use one of these and why.

551

I'd suggest clarifying this as "by skipping any def which AA can prove does not alias the location(s) accessed by the instruction given"

554

This comment is unclear?

563

Dead code, please remove!

572

I'm confused, am I allowed to call getClobberingMemoryAccess on a DoNothingMemorySSAWalker? What are the semantics here?

577

"real"? As opposed to?

lib/Analysis/AliasAnalysis.cpp
351 ↗(On Diff #23347)

These *need* to submitted separately with test cases if possible.

reames added inline comments.Apr 13 2015, 10:33 AM
include/llvm/Analysis/AliasAnalysis.h
148 ↗(On Diff #23347)

This can and should go in separately.

371 ↗(On Diff #23347)

Same as above.

Ok, here's the MemorySSA.cpp parts of the review. Lots of small style comments, a couple of larger concerns. At least some of the code duplication would be nice to address before submission, though I wouldn't say it's mandatory as long as it was done quickly thereafter.

I'm uncomfortable with some of the bits inside the CachingMemorySSAWalker routines. Would you mind submitting the first version of the memory SSA code without them and then reviewing those separately? There's some very complex logic there that duplicates parts of MDA. Given how tricky MDA has been, I'm really not comfortable with the code in the walkers as it stands today without a much more careful review

lib/Transforms/Utils/MemorySSA.cpp
50

Isn't this line redundant with the above?

80

I'm skipping all the code copied from PMtR. I'm going to assume it's correct.

p.s. Any chance this could be expressed in a common template used by both places?

282

Can we use smart pointers by chance? The manual memory management seems unnecessary.

304

We no longer throw this out do we?

322

This should be pulled out in a helper lambda or otherwise commoned.

328

else if - once you do that, can't this just become:
if (def) {
} else if (use) {
} else {

llvm_unreachable()

}

416

Don't you need to add these to the per-BB list? Also, can this code be commoned with the memory SSA construction path?

428

It looks like you're not really using the instruction at all, maybe just pass the basicblock to begin with?

463

Again, can we common this somewhere? You've got this lazy creation scatter all over the place.

Accesses = ensureBBList(BB)?

505

This seems odd. Shouldn't we be putting Replacer in the spot Replacee was?

548

Did you possible mean a != here?

561

This condition really doesn't feel like a "replacement". Is it time to reconsider the interface and turn this into an assert?

572

It might be cleaner to unconditionally insert the new value, then fold single use memory phis. Having a fold single use phi utility might also be useful on the public interface.

Actually, are you expecting an invariant where such phis are always folded? If so, please update comments to say so.

612

If there are no uses, why is it required? Did you mean:
use_empty || onlySingleValue?

621

You've got this code repeated a bit. Utility function on memoryPhi?

822

Can't you just use cl opt for this?

853

smart pointer?

943

Er, huh? How can this happen? And should it?

1006

Er, what? This just seems flat out wrong. Two loads on the same thread to the same location are always ordered regardless of flags. Ordering doesn't bypass a mustalias...

Unless this is absolutely required, I would request you separate this and review it separately.

1026

I might be missing something here, but how is this not an infinite recursion on itself?

1043

This seems suspicious to me as said above.

More generally, the smarts of this routine deserve to be reviewed independently.

1084

Mild preference, change this to:
else if (CallSite CS = ...) {
} else {
}

1111

Does this optimization actually help? Just curious.

Hi Daniel,

I'm looking at making LLVM recognize an idiom that I think MemorySSA+PRE would handle. What's the status of MemorySSA?

I know you haven't had much time to work on it recently; is it in such a state that someone (me) could help progress it?

Cheers,

James

Yes, it was looked at and approved, it just needs more tests written
and the initial update infrastructure ripped out and then slowly
rebuilt.
I can send you the latest patch, which fixes a bunch of bugs/etc.

hfinkel edited edge metadata.Dec 13 2015, 2:04 AM

Yes, it was looked at and approved, it just needs more tests written
and the initial update infrastructure ripped out and then slowly
rebuilt.
I can send you the latest patch, which fixes a bunch of bugs/etc.

Can you please post it here too, so we can continue the review?

pete added a subscriber: pete.Dec 13 2015, 9:32 PM
anemet added a subscriber: anemet.Dec 14 2015, 1:27 PM
dberlin edited edge metadata.

Refactor and rewrite a lot of stuff. This is somewhat of an intermediate state, so it's a bit messier than i'd like.
This version builds but i haven't played with it in a few months, so i expect it is bitrotted and may be a bit broken.
I am updating it mainly to give someone else a chance to takeover since i'm going to be swamped for a while.

Main algorithmic changes:
We now use BFS to find nearest dominating access in the caching walker.
I've performed extensive performance testing of hybrid DFS and BFS schemes, and BFS wins every time.
A bunch of things have started being iteratorized.
The caching walker has been modified a bit. The current caching scheme is fast, but can't easily be invalidated on a per-access basis.
The overhead of simple schemes that supported that level of invalidation was *quite* large.
(the ideal caching storage scheme here is actually quadtrees).

The caching walker now uses the same phi translation mechanism that memorydepedenceanalysis does.
I'm not sure this is a good thing, as that phi translation mechanism is ... strange and weird and has weird optimizations embedded in it.
It may be better to get worse optimization to start and clean that stuff up.

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

Also note: BFS or a hybrid DFS scheme is required to actually fulfill the
API guarantee we make - that we will give you the nearest dominating access.
DFS may find an access that is dominating but not the nearest dominating
one, depending on what paths it follows.

Thanks for the update!

Quick comment (just so I don't forget), there are a few places that have:

assert(N < 10000 && ..)

that need to become actual conservative bailouts instead of asserts.

lib/Transforms/Utils/MemorySSA.cpp
1285

You might also want to check AA->pointsToConstantMemory here.

Yeah, these were just debugging asserts. They are there so i got asserts
on infinite loops and could bugpoint the testcases.
There shouldn't be any bugs left (most of the infinite loops were due to
inconsistency between the iterator and phitransaddr in what the result of
phi translation was. Now that they use the same thing, there is no
inconsistency) :)

They should definitely be removed, and i've run memoryssa across google's
codebase without them triggering.

I'm pretty sure i won't get to this patch in the next 6 months, though i'm
trying to find someone on my side to take it over. If someone else wants
to, that'd be awesome as well.

dberlin updated this revision to Diff 44284.Jan 7 2016, 3:52 PM

Fix comments, remove DFS, update tests to work again (aliasing got too smart)

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

hfinkel added inline comments.Jan 7 2016, 4:27 PM
lib/Transforms/Utils/MemorySSA.cpp
1125

This algorithm in getClobberingMemoryAccess does not seem correct. If we have this:

   [ entry ]
       |
      ...
       |
   (clobbering access - a)
      ...
  /          \
...         (clobbering access - b)
 |              |
...           ....
 \              /
        ...
 (starting access)

UpwardsBFSWalkAccess seems to walk upward until it finds its first clobbering access, and returns that when found. In the case above, if we find clobbering access (b) first, then we're okay, because we'll pick some dominating def farther down the path which is on all paths to both dominating accesses.

But, if we hit clobbering access (a) first, then we'll accept that (incorrectly) as the new final access, because it dominates the original. However, not all paths to all aliasing defs terminate (or pass through) that access.

I think that you can continue the walk so that you search the entire subgraph to make sure that all paths terminate at the same aliasing def, and only in that case, use it (and, in that case, you know it must dominate).

My attempts to think up a good solution to the more-general problem have thus-far been stymied by this situation:

[entry]
  |
.....
(clobbering access - b)
 |
....   ________________________________
  \   /                                                               |
   (x)                                                               |
 ......                                                               |
    |                                                                 |
    |    ______________________                 |
     \   /                                        |                   |
(starting access)                        |                   |
     ...                                           |                   |
 (clobbering access - a)              |                   |
    ...                                            |                   |
    | |                                            |                   |
    | |______________________|                   |
    |                                                                  |
    |_________________________________|

The idea is that the block with the starting access also later has a clobbering access (a). This block is one of its own predecessors, but that's not the only path from clobbering access (a) back to the starting access. And furthermore, the other path flows through other blocks that do properly dominate the starting access. Thus, even if you were to pick a def (or phi) on the path from the starting access through its dominating predecessor, say at (x), and even though there are paths to all aliasing defs along that route, you'd still be wrong because there exists a path to clobbering access (a) that does not contain (x) (the path following the inner-loop backedge).

Thoughts? (am I off base here?)

hliao added a subscriber: hliao.Jan 7 2016, 10:49 PM

In-progress update

This brings back the DFS code and starts to update the BFS code to do the right thing with phi nodes.
Given the structure of the SSA graph and our requirements, i'm pretty positive both DFS and BFS will give correct results (and testing them against each other bears this out, though is not exhaustive).

Given that, and how ugly the BFS code is now starting to become to support the phi node rules, i'm tempted to get rid of it and just stick with DFS.

Thoughts welcome :)

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

Remove BFS code, fix a bug in DFS code.

(Updating so gbiv can take over)

Updating D7864: This patch introduces MemorySSA, a virtual SSA form for memory.

Details on what it looks like are in MemorySSA.h

george.burgess.iv commandeered this revision.Feb 1 2016, 11:50 AM
george.burgess.iv added a reviewer: dberlin.

It turns out that *can* steal revisions -- yay.

Taking ownership, killing D16743

Added Danny's patch that makes everything a User, as well as all of the updates published originally in the now-abandoned D16743.

Addressed all feedback in D16743, as well.

dberlin edited edge metadata.Feb 1 2016, 2:46 PM

You need

static inline bool classof(const Value *V) {
<right stuff>
}

For each of the classes. I only pasted it into memorydef, but without it, walking over operands and casting uses will not work.

But other than that, LGTM, i don't really have anything to add.
Thanks for taking this on!

george.burgess.iv edited edge metadata.
george.burgess.iv marked 71 inline comments as done.
  • Marked dead feedback as done, responded to others, will respond to remaining non-done + unanswered by tomorrow
  • Fixed Danny's comment about having classof(Value*)
  • Moved initialize[...]Pass methods to fix a bug with how we were trying to link things
  • Ripped out some optimizations (e.g. checks for invariant loads, etc.) because those seem mildly controversial, and can be added in a later patch

Thanks for the LGTM, Danny.

First wave of responses...

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

Because it breaks code like (ripped from MemoryDef::print(raw_ostream &)):

MemoryAccess *UO = getDefiningAccess();
if (UO && UO->getID()) // Breaks
  // ...

...Because protected doesn't let you call protected methods on other MemoryAccesses. You can call them on yourself, or you can call them on other MemoryDefs. That's all.

Do you think it would be better to make getID() public, or to keep the friend declarations? I'm happy with either.

152

It wasn't entirely an isa relationship. It's now refactored to be more clear.

294

Definition of MemoryPhi::setIncomingValue is now substantially smaller. Leaving in header, unless you'd still like to see it moved.

409

Update API has been removed for now.

lib/Transforms/Utils/MemorySSA.cpp
81

Comment is on code that seems to have been removed.

88

Comment is on code that seems to have been removed.

153

Comment is on code that seems to have been removed.

622

Now only exists in one place AFAICT.

964

Nuked possiblyAffectedBy from orbit; it's an optimization that can be readded later.

964

Do you still hold this opinion? (Potentially dubious is now in CachingMemorySSAWalker::instructionClobbersQuery)

964

Marked with a TODO so we can look into that when we have users of MemorySSA/a more complete API/...

964

Seems old; we now use DFS. Marking as done, but added a test case of your second example.

964

I think it's better to get MemorySSA in and work on little optimizations like this after that. Removed the invariant check (but kept the test as an XFAIL), to be readded in the near future as a set of enhancements.

george.burgess.iv marked 10 inline comments as done.Feb 1 2016, 5:36 PM

After further investigation, the rest of the comments seem to be dead/already addressed, too; marked them as done.

Also, wow. Responding to comments at the bottom *really* didn't go well. I thought it would reflow them, but apparently not. Sorry about that. :/

Either way, I'll leave this open for a bit, in case anyone has any other remarks. Assuming Danny's LGTM is sufficient to let me commit, I'll do so lateish Wednesday if there are no objections by then. :)

Trying to make the comment/response chain at the bottom look less confusing...

reames

Er, what? This just seems flat out wrong. Two loads on the same thread to the same location are always ordered regardless of flags. Ordering doesn't bypass a mustalias...
Unless this is absolutely required, I would request you separate this and review it separately.

Nuked possiblyAffectedBy from orbit; it's an optimization that can be readded later.

Does this optimization actually help? Just curious.

Marked with a TODO so we can look into that when we have users of MemorySSA/a more complete API/...

This seems suspicious to me as said above.
More generally, the smarts of this routine deserve to be reviewed independently.

possiblyAffectedBy was removed, so I think this comment doesn't apply anymore (nor does my initial response to it). :)

hfinkel

You might also want to check AA->pointsToConstantMemory here.

I think it's better to get MemorySSA in and work on little optimizations like this after that. Removed the invariant check (but kept the test as an XFAIL), to be readded in the near future as a set of enhancements. (Good point, though!)

This algorithm in getClobberingMemoryAccess does not seem correct [...]

Seems old; we now use DFS. Marking as done, but added a test case of your second example.

reames accepted this revision.Feb 1 2016, 5:44 PM
reames added a reviewer: reames.

Explicitly LGTM as well. I'm really looking forward to having this in tree so that we can start experimenting and iterating on top of it.

I don't think we're going to be ready to switch the default for a while yet, but being able to iterate and work through the bugs in tree is going to be very empowering and will likely speedup progress.

p.s. What's your planned next step? I'd suggest implementing a very simple pass which just runs obvious peepholes over the MemorySSA representation. (e.g. a MemCombine pass). My suspicion is that will be a good way to stress the implementation and might even be profitable enough to just turn on by default. In particular, a pass that got the easy forms of cross block DSE would be very useful..

This revision is now accepted and ready to land.Feb 1 2016, 5:44 PM

FWIW: My plan was going to start to replace some of the existing
memorydependence users which are O(N^2) and ugly with simpler O(N)
algorithms using MemorySSA

Explicitly LGTM as well. I'm really looking forward to having this in tree so that we can start experimenting and iterating on top of it.

Thanks! (Also, naturally, thanks to everyone who reviewed/commented/... :) )

I don't think we're going to be ready to switch the default for a while yet, but being able to iterate and work through the bugs in tree is going to be very empowering and will likely speedup progress.

It seems that there are a number of people who are concerned about subtle bugs (both in MemorySSA, and in user code -- especially if this lets us optimize code in new and exciting ways). So, I agree that making this opt-in for a time is a good idea.

What's your planned next step? I'd suggest implementing a very simple pass which just runs obvious peepholes over the MemorySSA representation. (e.g. a MemCombine pass). My suspicion is that will be a good way to stress the implementation and might even be profitable enough to just turn on by default. In particular, a pass that got the easy forms of cross block DSE would be very useful.

I don't have any plans. If we want to port existing passes soon, we'll either need an update API, or we'll need to restrict ourselves to passes that don't use the update API. Also, we'll need a wrapper that either queries MemDep or MemorySSA if we want to have a global "use MemorySSA?" flag. If we think making a simple MemorySSA-based DSE pass would be a better first step, I'm fine doing that, as well. Same thing goes for readding the optimizations that were stripped out today.

So long as progress is made, I'm happy. :)

Excellent progress.

As Danny mentioned, the O(N^2) behavior of some MemoryDependence users
are biting us badly in some cases. For instance, some of the C++
source takes forever to compile with profile instrumentation turned on
and the root cause is due to that. Replacing those with memSSA based
algorithms will have very large (good) impact.

thanks,

David

I don't have any plans. If we want to port existing passes soon, we'll
either need an update API, or we'll need to restrict ourselves to passes
that don't use the update API.

FWIW: For the passes i played with converting, timing compute memssa + use
it vs memdep, for basically all testcases i could find, the time difference
was in the noise.
For larger cases, memssa is a straight win.
This is because most of the memdep passes are walking a ton of blocks/insts
repeatedly anyway.

Also, we'll need a wrapper that either queries MemDep or MemorySSA if we
want to have a global "use MemorySSA?" flag.

I'm not sure such a flag makes sense, given the above. I'm not sure you
*want* to try to alternate between them, because a lot of your order of
magnitude speedups will come from doing things fundamentally different
than random querying (IE move to more "SSA-like" algorithms).

(Though i expect using memssa as a straight replacement will still likely
be faster).

If we think making a simple MemorySSA-based DSE pass would be a better

first step, I'm fine doing that, as well. Same thing goes for readding the
optimizations that were stripped out today.

If you do the optimizations, i'm happy to start to convert passes. I was
going to just do them in close to the order necessary to preserve memssa
from beginning to end of opts that use it, but happy to do whatever.

(mergedloadstoremotion and memcpyoptimizer are the easiest things to
convert and will give speedups).

Converting most passes requires building an update API, and converting a
few of them and seeing what they want out of updating is the best way i can
think of to design that API.

(You can see where i played with it in the mergedloadstoremotion mpass).

So long as progress is made, I'm happy. :)

http://reviews.llvm.org/D7864

This revision was automatically updated to reflect the committed changes.
jlebar added a subscriber: jlebar.Mar 1 2016, 5:55 PM

I'm seeing an asan failure in one of the tests added here. I'm building from tip, clean tree, linux x86-64.

-- Testing: 1 of 15992 tests, 1 threads --
FAIL: LLVM-Unit :: Transforms/Utils/UtilsTests/MemorySSA.RemoveMemoryAccess (1 of 1)
******************** TEST 'LLVM-Unit :: Transforms/Utils/UtilsTests/MemorySSA.RemoveMemoryAccess' FAILED ********************
Note: Google Test filter = MemorySSA.RemoveMemoryAccess
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from MemorySSA
[ RUN      ] MemorySSA.RemoveMemoryAccess
=================================================================
==5162==ERROR: AddressSanitizer: heap-use-after-free on address 0x60800000bb68 at pc 0x000000c96299 bp 0x7ffea8a84a90 sp 0x7ffea8a84a88
READ of size 8 at 0x60800000bb68 thread T0
  #0 0xc96298 in llvm::MemoryAccess::getBlock() const /usr/local/google/home/jlebar/llvm/src/include/llvm/Transforms/Utils/MemorySSA.h:116:34
  #1 0xc96298 in llvm::MemorySSA::removeFromLookups(llvm::MemoryAccess*) /usr/local/google/home/jlebar/llvm/src/lib/Transforms/Utils/MemorySSA.cpp:469
  #2 0x58ffee in MemorySSA_RemoveMemoryAccess_Test::TestBody() /usr/local/google/home/jlebar/llvm/src/unittests/Transforms/Utils/MemorySSA.cpp:65:3
  #3 0xd66ec3 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2145:12
  #4 0xd66ec3 in testing::Test::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2161
  #5 0xd6b854 in testing::TestInfo::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2309:5
  #6 0xd6cb16 in testing::TestCase::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2416:5
  #7 0xd85c7a in testing::internal::UnitTestImpl::RunAllTests() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:4207:11
  #8 0xd84eaf in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2145:12
  #9 0xd84eaf in testing::UnitTest::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:3841
  #10 0xd3cc67 in main /usr/local/google/home/jlebar/llvm/src/utils/unittest/UnitTestMain/TestMain.cpp:47:10
  #11 0x7fc886a0dec4 in __libc_start_main /build/eglibc-3GlaMS/eglibc-2.19/csu/libc-start.c:287
  #12 0x54bd09 in _start (/usr/local/google/home/jlebar/code/llvm/asan/unittests/Transforms/Utils/UtilsTests+0x54bd09)

0x60800000bb68 is located 72 bytes inside of 96-byte region [0x60800000bb20,0x60800000bb80)
freed by thread T0 here:
  #0 0x4c734b in operator delete(void*) (/usr/local/google/home/jlebar/code/llvm/asan/unittests/Transforms/Utils/UtilsTests+0x4c734b)
  #1 0xc9602e in llvm::ilist_node_traits<llvm::MemoryAccess>::deleteNode(llvm::MemoryAccess*) /usr/local/google/home/jlebar/llvm/src/include/llvm/ADT/ilist.h:160:39
  #2 0xc9602e in llvm::iplist<llvm::MemoryAccess, llvm::ilist_traits<llvm::MemoryAccess> >::erase(llvm::ilist_iterator<llvm::MemoryAccess>) /usr/local/google/home/jlebar/llvm/src/include/llvm/ADT/ilist.h:466
  #3 0xc9602e in llvm::iplist<llvm::MemoryAccess, llvm::ilist_traits<llvm::MemoryAccess> >::erase(llvm::MemoryAccess*) /usr/local/google/home/jlebar/llvm/src/include/llvm/ADT/ilist.h:470
  #4 0xc9602e in llvm::MemorySSA::removeFromLookups(llvm::MemoryAccess*) /usr/local/google/home/jlebar/llvm/src/lib/Transforms/Utils/MemorySSA.cpp:467
  #5 0x58ffee in MemorySSA_RemoveMemoryAccess_Test::TestBody() /usr/local/google/home/jlebar/llvm/src/unittests/Transforms/Utils/MemorySSA.cpp:65:3
  #6 0xd66ec3 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2145:12
  #7 0xd66ec3 in testing::Test::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2161
  #8 0xd6b854 in testing::TestInfo::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2309:5
  #9 0xd6cb16 in testing::TestCase::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2416:5
  #10 0xd85c7a in testing::internal::UnitTestImpl::RunAllTests() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:4207:11
  #11 0xd84eaf in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2145:12
  #12 0xd84eaf in testing::UnitTest::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:3841
  #13 0xd3cc67 in main /usr/local/google/home/jlebar/llvm/src/utils/unittest/UnitTestMain/TestMain.cpp:47:10
  #14 0x7fc886a0dec4 in __libc_start_main /build/eglibc-3GlaMS/eglibc-2.19/csu/libc-start.c:287

previously allocated by thread T0 here:
  #0 0x4c6e0b in operator new(unsigned long) (/usr/local/google/home/jlebar/code/llvm/asan/unittests/Transforms/Utils/UtilsTests+0x4c6e0b)
  #1 0xa7ec05 in llvm::User::allocateFixedOperandUser(unsigned long, unsigned int, unsigned int) /usr/local/google/home/jlebar/llvm/src/lib/IR/User.cpp:129:7
  #2 0xa7ec05 in llvm::User::operator new(unsigned long, unsigned int) /usr/local/google/home/jlebar/llvm/src/lib/IR/User.cpp:147
  #3 0xc92784 in llvm::MemoryDef::operator new(unsigned long) /usr/local/google/home/jlebar/llvm/src/include/llvm/Transforms/Utils/MemorySSA.h:271:41
  #4 0xc92784 in llvm::MemorySSA::createNewAccess(llvm::Instruction*, bool) /usr/local/google/home/jlebar/llvm/src/lib/Transforms/Utils/MemorySSA.cpp:378
  #5 0xc9098f in llvm::MemorySSA::buildMemorySSA(llvm::AAResults*, llvm::DominatorTree*) /usr/local/google/home/jlebar/llvm/src/lib/Transforms/Utils/MemorySSA.cpp:260:26
  #6 0x58f91b in MemorySSA_RemoveMemoryAccess_Test::TestBody() /usr/local/google/home/jlebar/llvm/src/unittests/Transforms/Utils/MemorySSA.cpp:55:29
  #7 0xd66ec3 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2145:12
  #8 0xd66ec3 in testing::Test::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2161
  #9 0xd6b854 in testing::TestInfo::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2309:5
  #10 0xd6cb16 in testing::TestCase::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2416:5
  #11 0xd85c7a in testing::internal::UnitTestImpl::RunAllTests() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:4207:11
  #12 0xd84eaf in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2145:12
  #13 0xd84eaf in testing::UnitTest::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:3841
  #14 0xd3cc67 in main /usr/local/google/home/jlebar/llvm/src/utils/unittest/UnitTestMain/TestMain.cpp:47:10
  #15 0x7fc886a0dec4 in __libc_start_main /build/eglibc-3GlaMS/eglibc-2.19/csu/libc-start.c:287

SUMMARY: AddressSanitizer: heap-use-after-free /usr/local/google/home/jlebar/llvm/src/include/llvm/Transforms/Utils/MemorySSA.h:116 llvm::MemoryAccess::getBlock() const
Shadow bytes around the buggy address:
0x0c107fff9710: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c107fff9720: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c107fff9730: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c107fff9740: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c107fff9750: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa
=>0x0c107fff9760: fa fa fa fa fd fd fd fd fd fd fd fd fd[fd]fd fd
0x0c107fff9770: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 00
0x0c107fff9780: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c107fff9790: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c107fff97a0: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c107fff97b0: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 03 fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable:           00
Partially addressable: 01 02 03 04 05 06 07 
Heap left redzone:       fa
Heap right redzone:      fb
Freed heap region:       fd
Stack left redzone:      f1
Stack mid redzone:       f2
Stack right redzone:     f3
Stack partial redzone:   f4
Stack after return:      f5
Stack use after scope:   f8
Global redzone:          f9
Global init order:       f6
Poisoned by user:        f7
Container overflow:      fc
ASan internal:           fe
==5162==ABORTING

********************
Testing Time: 0.56s
********************
Failing Tests (1):
  LLVM-Unit :: Transforms/Utils/UtilsTests/MemorySSA.RemoveMemoryAccess

Unexpected Failures: 1

Thanks for the report -- looking into it now :)

It seems that the test in question wasn't introduced by this patch, but the fix seems somewhat trivial, so my attempt was checked in as r262452. Please let me know if that didn't end up fixing it (I lack an ASAN-instrumented build of LLVM :) ).

Please let me know if that didn't end up fixing it (I lack an ASAN-instrumented build of LLVM :) ).

Works now, although now that it's fixed asan is showing me memory leaks. :) One seems to be in the test itself, but another appears to be in the actual code.

Clearly not as urgent, but here's the report:

********************
FAIL: LLVM-Unit :: Transforms/Utils/UtilsTests/MemorySSA.RemoveMemoryAccess (15985 of 15994)
******************** TEST 'LLVM-Unit :: Transforms/Utils/UtilsTests/MemorySSA.RemoveMemoryAccess' FAILED ********************
Note: Google Test filter = MemorySSA.RemoveMemoryAccess
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from MemorySSA
[ RUN      ] MemorySSA.RemoveMemoryAccess
[       OK ] MemorySSA.RemoveMemoryAccess (25 ms)
[----------] 1 test from MemorySSA (25 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (26 ms total)
[  PASSED  ] 1 test.

=================================================================
==147403==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 304 byte(s) in 1 object(s) allocated from:
    #0 0x4c66ab in operator new(unsigned long) (/usr/local/google/home/jlebar/code/llvm/asan/unittests/Transforms/Utils/UtilsTests+0x4c66ab)
    #1 0xc89da5 in llvm::MemorySSA::buildMemorySSA(llvm::AAResults*, llvm::DominatorTree*) /usr/local/google/home/jlebar/llvm/src/lib/Transforms/Utils/MemorySSA.cpp:234:3
    #2 0x58f1eb in MemorySSA_RemoveMemoryAccess_Test::TestBody() /usr/local/google/home/jlebar/llvm/src/unittests/Transforms/Utils/MemorySSA.cpp:55:29
    #3 0xd60843 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2145:12
    #4 0xd60843 in testing::Test::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2161
    #5 0xd651d4 in testing::TestInfo::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2309:5
    #6 0xd66496 in testing::TestCase::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2416:5
    #7 0xd7f5fa in testing::internal::UnitTestImpl::RunAllTests() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:4207:11
    #8 0xd7e82f in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2145:12
    #9 0xd7e82f in testing::UnitTest::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:3841
    #10 0xd365e7 in main /usr/local/google/home/jlebar/llvm/src/utils/unittest/UnitTestMain/TestMain.cpp:47:10
    #11 0x7fb091525ec4 in __libc_start_main /build/eglibc-3GlaMS/eglibc-2.19/csu/libc-start.c:287

Indirect leak of 1024 byte(s) in 1 object(s) allocated from:
    #0 0x4c66ab in operator new(unsigned long) (/usr/local/google/home/jlebar/code/llvm/asan/unittests/Transforms/Utils/UtilsTests+0x4c66ab)
    #1 0x58e7b8 in MemorySSA_RemoveMemoryAccess_Test::TestBody() /usr/local/google/home/jlebar/llvm/src/unittests/Transforms/Utils/MemorySSA.cpp:53:3
    #2 0xd60843 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2145:12
    #3 0xd60843 in testing::Test::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2161
    #4 0xd651d4 in testing::TestInfo::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2309:5
    #5 0xd66496 in testing::TestCase::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2416:5
    #6 0xd7f5fa in testing::internal::UnitTestImpl::RunAllTests() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:4207:11
    #7 0xd7e82f in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2145:12
    #8 0xd7e82f in testing::UnitTest::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:3841
    #9 0xd365e7 in main /usr/local/google/home/jlebar/llvm/src/utils/unittest/UnitTestMain/TestMain.cpp:47:10
    #10 0x7fb091525ec4 in __libc_start_main /build/eglibc-3GlaMS/eglibc-2.19/csu/libc-start.c:287

ndirect leak of 32 byte(s) in 1 object(s) allocated from:
    #0 0x4c66ab in operator new(unsigned long) (/usr/local/google/home/jlebar/code/llvm/asan/unittests/Transforms/Utils/UtilsTests+0x4c66ab)
    #1 0x58e777 in MemorySSA_RemoveMemoryAccess_Test::TestBody() /usr/local/google/home/jlebar/llvm/src/unittests/Transforms/Utils/MemorySSA.cpp:52:3
    #2 0xd60843 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2145:12
    #3 0xd60843 in testing::Test::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2161
    #4 0xd651d4 in testing::TestInfo::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2309:5
    #5 0xd66496 in testing::TestCase::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2416:5
    #6 0xd7f5fa in testing::internal::UnitTestImpl::RunAllTests() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:4207:11
    #7 0xd7e82f in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2145:12
    #8 0xd7e82f in testing::UnitTest::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:3841
    #9 0xd365e7 in main /usr/local/google/home/jlebar/llvm/src/utils/unittest/UnitTestMain/TestMain.cpp:47:10
    #10 0x7fb091525ec4 in __libc_start_main /build/eglibc-3GlaMS/eglibc-2.19/csu/libc-start.c:287

Indirect leak of 16 byte(s) in 1 object(s) allocated from:
    #0 0x4c66ab in operator new(unsigned long) (/usr/local/google/home/jlebar/code/llvm/asan/unittests/Transforms/Utils/UtilsTests+0x4c66ab)
    #1 0x58ee7f in void llvm::AAResults::addAAResult<llvm::BasicAAResult>(llvm::BasicAAResult&) /usr/local/google/home/jlebar/llvm/src/include/llvm/Analysis/AliasAnalysis.h:173:5
    #2 0x58ee7f in MemorySSA_RemoveMemoryAccess_Test::TestBody() /usr/local/google/home/jlebar/llvm/src/unittests/Transforms/Utils/MemorySSA.cpp:54
    #3 0xd60843 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2145:12
    #4 0xd60843 in testing::Test::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2161
    #5 0xd651d4 in testing::TestInfo::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2309:5
    #6 0xd66496 in testing::TestCase::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2416:5
    #7 0xd7f5fa in testing::internal::UnitTestImpl::RunAllTests() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:4207:11
    #8 0xd7e82f in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2145:12
    #9 0xd7e82f in testing::UnitTest::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:3841
    #10 0xd365e7 in main /usr/local/google/home/jlebar/llvm/src/utils/unittest/UnitTestMain/TestMain.cpp:47:10
    #11 0x7fb091525ec4 in __libc_start_main /build/eglibc-3GlaMS/eglibc-2.19/csu/libc-start.c:287

Indirect leak of 8 byte(s) in 1 object(s) allocated from:
    #0 0x4c66ab in operator new(unsigned long) (/usr/local/google/home/jlebar/code/llvm/asan/unittests/Transforms/Utils/UtilsTests+0x4c66ab)
    #1 0x592596 in __gnu_cxx::new_allocator<std::unique_ptr<llvm::AAResults::Concept, std::default_delete<llvm::AAResults::Concept> > >::allocate(unsigned long, void const*) /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/ext/new_allocator.h:104:27
    #2 0x592596 in std::_Vector_base<std::unique_ptr<llvm::AAResults::Concept, std::default_delete<llvm::AAResults::Concept> >, std::allocator<std::unique_ptr<llvm::AAResults::Concept, std::default_delete<llvm::AAResults::Concept> > > >::_M_allocate(unsigned long) /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_vector.h:168
    #3 0x592596 in void std::vector<std::unique_ptr<llvm::AAResults::Concept, std::default_delete<llvm::AAResults::Concept> >, std::allocator<std::unique_ptr<llvm::AAResults::Concept, std::default_delete<
llvm::AAResults::Concept> > > >::_M_emplace_back_aux<llvm::AAResults::Model<llvm::BasicAAResult>*>(llvm::AAResults::Model<llvm::BasicAAResult>*&&) /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/vector.tcc:404
    #4 0x58f1cd in void std::vector<std::unique_ptr<llvm::AAResults::Concept, std::default_delete<llvm::AAResults::Concept> >, std::allocator<std::unique_ptr<llvm::AAResults::Concept, std::default_delete<
llvm::AAResults::Concept> > > >::emplace_back<llvm::AAResults::Model<llvm::BasicAAResult>*>(llvm::AAResults::Model<llvm::BasicAAResult>*&&) /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/vector.tcc:101:4
    #5 0x58f1cd in void llvm::AAResults::addAAResult<llvm::BasicAAResult>(llvm::BasicAAResult&) /usr/local/google/home/jlebar/llvm/src/include/llvm/Analysis/AliasAnalysis.h:173
    #6 0x58f1cd in MemorySSA_RemoveMemoryAccess_Test::TestBody() /usr/local/google/home/jlebar/llvm/src/unittests/Transforms/Utils/MemorySSA.cpp:54
    #7 0xd60843 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2145:12
    #8 0xd60843 in testing::Test::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2161
    #9 0xd651d4 in testing::TestInfo::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2309:5
    #10 0xd66496 in testing::TestCase::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2416:5
    #11 0xd7f5fa in testing::internal::UnitTestImpl::RunAllTests() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:4207:11
    #12 0xd7e82f in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:2145:12
    #13 0xd7e82f in testing::UnitTest::Run() /usr/local/google/home/jlebar/llvm/src/utils/unittest/googletest/src/gtest.cc:3841
    #14 0xd365e7 in main /usr/local/google/home/jlebar/llvm/src/utils/unittest/UnitTestMain/TestMain.cpp:47:10
    #15 0x7fb091525ec4 in __libc_start_main /build/eglibc-3GlaMS/eglibc-2.19/csu/libc-start.c:287

SUMMARY: AddressSanitizer: 1384 byte(s) leaked in 5 allocation(s).

Actually, sigh, we didn't do that already because we hand them back to the
user as well.
Anyway, i'm working up a patch to fix these.

This should hopefully fix all the leaks and asan errors (there is one real
bug here).
It is asan clean on OSX now, i am building on linux to do the leak check.