This is an archive of the discontinued LLVM Phabricator instance.

[MemorySSA] Add APIs to MemoryPhis to delete incoming blocks/values, and an updater API to remove blocks.
ClosedPublic

Authored by asbirlea on Jun 20 2018, 3:20 PM.

Details

Summary

MemoryPhis now have APIs analogous to BB Phis to remove an incoming value/block.
The MemorySSAUpdater uses the above APIs when updating MemorySSA given a set of dead blocks about to be deleted.

Diff Detail

Repository
rL LLVM

Event Timeline

asbirlea created this revision.Jun 20 2018, 3:20 PM

Thanks for this!

include/llvm/Analysis/MemorySSA.h
566 ↗(On Diff #152179)

nit: I don't think we encourage const on value params

566 ↗(On Diff #152179)

Naming nit: do you think it would be good to call out that these methods don't preserve the Phi's operand ordering? If so, please add either an unordered prefix/suffix to these.

(I've no issue with the swap-and-pop_back idiom; I just want it to be obvious at each callsite that the order might be changed)

568 ↗(On Diff #152179)

Nit: The parens around (I < E) are unnecessary (and on line 569 + 585 + 597)

570 ↗(On Diff #152179)

Please add a comment explaining why (I'm assuming it's something like "otherwise, we should just be deleting the Phi outright")

lib/Analysis/MemorySSAUpdater.cpp
501 ↗(On Diff #152179)

nit: if (TerminatorInst *TI = BB->getTerminator()).

Do we expect to see broken IR here, though? It's my impression that BBs should always have a terminator when they're in a complete-enough state.

If yes, please add a comment explaining how broken we expect our IR to be when this method is called. :)

514 ↗(On Diff #152179)

Do we need to look this up on every iteration?

519 ↗(On Diff #152179)

This is already done in Value::~Value(), which should be called by MemorySSA::removeFromLists. Does it need to be repeated here? (Especially given that we skip this extra check for Uses.)

524 ↗(On Diff #152179)

cast<MemoryAccess>

531 ↗(On Diff #152179)

Can we set this to nullptr instead, like Value::dropAllReferences does? (I also think this could be simplified a fair amount if we swapped to dropAllReferences in the loop above + a deletion pass after that, but if that's inferior to this somehow, I'm happy to accept this approach. Value's dtor should cover the "User must be deleted too." assert for us)

538 ↗(On Diff #152179)

In the interest of getting rid of soon-to-be-dangling pointers, we should probably remove all of DeadBlocks from MemorySSA::BlockNumberingValid, too.

I think that would fit best in MemorySSA::removeFromLists, though

asbirlea updated this revision to Diff 152548.Jun 22 2018, 3:15 PM
asbirlea marked 9 inline comments as done.

Address comments.

asbirlea added inline comments.Jun 22 2018, 3:16 PM
lib/Analysis/MemorySSAUpdater.cpp
501 ↗(On Diff #152179)

TI should be null for empty blocks. I don't have a use case, but it seemed a reasonable safety check. I can remove it if you think it's unnecessary.
I extended the header comment with the amount of "broken-ness" to be expected :).

531 ↗(On Diff #152179)

Added dropAllReferences above, only updating lists here.

538 ↗(On Diff #152179)

Added in MemorySSA::removeFromLookups where BlockNumbering is also updated.

asbirlea updated this revision to Diff 152551.Jun 22 2018, 3:57 PM

nit: format.

include/llvm/Analysis/MemorySSAUpdater.h
153 ↗(On Diff #152551)

Did you mean "predecessor edges"?

lib/Analysis/MemorySSA.cpp
1576 ↗(On Diff #152551)

The numbering is still valid even if we remove MA, though :)

We don't really care if the numbering has gaps. We only care that the block numbers increase as you iterate through an AccessList.

lib/Analysis/MemorySSAUpdater.cpp
501 ↗(On Diff #152179)

Personally, I have a slight preference for asserting that the IR is well-formed until we know that we can't, but if you'd prefer to have a check here, I'm OK with that.

asbirlea updated this revision to Diff 152962.Jun 26 2018, 2:15 PM
asbirlea marked 7 inline comments as done.

Address comments.

lib/Analysis/MemorySSA.cpp
1576 ↗(On Diff #152551)

You're right :). Moved to removeFromLists.

lib/Analysis/MemorySSAUpdater.cpp
501 ↗(On Diff #152179)

Ack, adding an assert. If I find a usecase later, I'll change it to a check.

LGTM with one remaining nit. Thanks again!

lib/Analysis/MemorySSA.cpp
1623 ↗(On Diff #152962)

Nit: can we put this in the if (Accesses->empty()) block?

I think the purpose is just to guard us from dangling pointers, and the only time we should (reasonably) carry a dangling pointer here is if we're removing the last access from this block.

This revision is now accepted and ready to land.Jun 26 2018, 2:44 PM
asbirlea updated this revision to Diff 152993.Jun 26 2018, 5:46 PM
asbirlea marked 3 inline comments as done.

Address comment. Thank you for the review!

This revision was automatically updated to reflect the committed changes.