[PATCH] D40375: Use MemorySSA in LICM to do sinking and hoisting.

Alina Sbirlea via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 22 11:35:55 PST 2017


asbirlea marked an inline comment as done.
asbirlea added a subscriber: dberlin.
asbirlea added inline comments.


================
Comment at: lib/Transforms/Scalar/LICM.cpp:846
+        // This is only called to properly update the defining access
+        MSSA->getWalker()->getClobberingMemoryAccess(NewMemUse);
+      }
----------------
george.burgess.iv wrote:
> asbirlea wrote:
> > sanjoy wrote:
> > > I'm not clear on how this works -- IIUC you're calling into `getClobberingMemoryAccess` with `NewMemUse`'s `DefiningAccess` set to `nullptr`, but:
> > > 
> > >  - Why don't we have to do this for `MemoryDef`s?
> > >  - What if `MSSA->getWalker()` is a `DoNothingMemorySSAWalker`?
> > >  - There are places where we should be crashing, like: `CachingWalker::getClobberingMemoryAccess` line 2078 that calls `getClobberingMemoryAccess(DefiningAccess, Q)` that calls `ClobberWalker::findWalker` which has `if (auto *MU = dyn_cast<MemoryUse>(Start))`.
> > AFAIU:
> > For Defs the DefiningAccess is properly updated.
> > For Uses, there is a DefiningAccess set, but that one is not optimized. When adding an access like in this case, calling getClobberingMemoryAccess will optimize it.
> > If the walker is DoNothingMemorySSAWalker, it won't optimize?
> > 
> > Pulling in george.burgess.iv to clarify, it's possible I'm missing something here.
> > 
> > IIUC you're calling into getClobberingMemoryAccess with NewMemUse's DefiningAccess set to nullptr
> 
> I'm assuming you meant `MemUse`, in which case `insertUse` sets up the defining access to something non-null.
> 
> It's sort of sketchy that we're trying to eagerly update the defining access using the walker, though. Is there a reason that we can't call `MSSA->getWalker()->getClobberingMemoryAccess(MemUse);` when we need optimized clobbers? Doing so should be incredibly cheap when the use has already been optimized, and it lets us be lazy about the work we do (if we don't need an accurate clobber for `MemUse`, we'll just never compute it)
> I'm assuming you meant MemUse, in which case insertUse sets up the defining access to something non-null.

Thanks for clarifying this.

> It's sort of sketchy that we're trying to eagerly update the defining access using the walker, though. Is there a reason that we can't call MSSA->getWalker()->getClobberingMemoryAccess(MemUse); when we need optimized clobbers? Doing so should be incredibly cheap when the use has already been optimized, and it lets us be lazy about the work we do (if we don't need an accurate clobber for MemUse, we'll just never compute it)

The reasoning here is that when making code changes such as hoist/sink, I need accesses to be (reasonably) optimized.  I'm not necessarily to looking to get full precision here, I'd be perfectly happy with an API to optimize up to the MemorySSA optimize-uses cap.
In LICM.cpp:1652 (and in the future for promotion) I'm relying on getting the defining access, not the walker->clobbering access, allowing for some imprecision in exchange for not paying the lookup time for blocks with large load/store count. 
I had come across a case where after a hoist or sink, this approach did not work for a very small testcase without using the walker to get clobbering.
So the choice I made was to use the walker ahead of time to update accesses I insert when cloning, allowing me to use getDefining afterwards.

Hopefully I clarified the intention here :). Do you think there's a better way to address this problem? I'm open to suggestions.

@dberlin
> So, this use renaming is expensive, and i'd like to understand the goal (It requires walking all stores and loads in the dominator subtree rooted at your memory access) It's really meant for when you've inserted defs that may alias existing uses.
> If your goal is to replace all uses of  an old memory access with some new memoryaccess, you want to use the replace API :)
The code here is creating a new memory access to handle cloning an access in all exit blocks, where that access may alias existing uses, so I think using the replace API isn't enough.
Please let me know if there is a way to handle this differently.


https://reviews.llvm.org/D40375





More information about the llvm-commits mailing list