This is an archive of the discontinued LLVM Phabricator instance.

Fix a missing memoryssa update in breakLoopBackedge
ClosedPublic

Authored by reames on Sep 1 2021, 8:56 AM.

Details

Summary

This is a case I'd missed in 6a8237. The odd bit here is that missing the edge removal update seems to produce MemorySSA which verifies, but is still corrupt in a way which bothers following passes. I wasn't able to reduce a single pass test case, which is why the reported test case is taken as is.

Posting for review to make sure there's nothing "interesting" about the use of the updater classes. The invariants on these are a bit subtle, and I want a second opinion.

Diff Detail

Event Timeline

reames created this revision.Sep 1 2021, 8:56 AM
reames requested review of this revision.Sep 1 2021, 8:56 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 1 2021, 8:56 AM
nikic added inline comments.Sep 1 2021, 9:52 AM
llvm/lib/Transforms/Utils/LoopUtils.cpp
751

I think there may be a preference to let MSSAU also update DT for performance reasons, along the lines of:

if (MSSA)
  MSSAU->applyUpdates({{DominatorTree::Delete, Latch, Header}}, DT, /*UpdateDT*/true);
else
  DT.applyUpdates({{DominatorTree::Delete, Latch, Header}});

But I'm not sure how important this is. @asbirlea will know...

The reason the verification didn't trigger right after LoopDeletion is that it's under EXPENSIVE_CHECKS (in verifyOrderingDominationAndDefUses). MSSA is incorrect (without this change) after LoopDeletion.

llvm/lib/Transforms/Utils/LoopUtils.cpp
751

Yes, ideally, let the MSSAU handle DT updates as well.

I'll send a change to the MSSAUpdater shortly so it doesn't matter as much when only deleting edges. I'll be ok with the code as is after that change (right now, with this patch, the deleted edge is readded during the MSSA update and then redeleted).
In general, best practice is to have them updated together.

asbirlea accepted this revision.Sep 1 2021, 4:03 PM

(a10409fe23c35a7eed0f39d12624af229d3877e1 resolves the way deleted edges are handled when there are no inserts)

This revision is now accepted and ready to land.Sep 1 2021, 4:03 PM
reames added a comment.Sep 1 2021, 4:57 PM

The reason the verification didn't trigger right after LoopDeletion is that it's under EXPENSIVE_CHECKS (in verifyOrderingDominationAndDefUses). MSSA is incorrect (without this change) after LoopDeletion.

FYI, this is not the sole issue. I manually added a call to MSSA->verifyMemorySSA() unconditionally to the end of the pass, and it did not catch this.

This revision was landed with ongoing or failed builds.Sep 1 2021, 4:59 PM
This revision was automatically updated to reflect the committed changes.

The reason the verification didn't trigger right after LoopDeletion is that it's under EXPENSIVE_CHECKS (in verifyOrderingDominationAndDefUses). MSSA is incorrect (without this change) after LoopDeletion.

FYI, this is not the sole issue. I manually added a call to MSSA->verifyMemorySSA() unconditionally to the end of the pass, and it did not catch this.

I'm sorry, I didn't fully parse this.
Adding MSSA->verifyMemorySSA() unconditionally to the end of the pass will not catch this. You need to enable EXPENSIVE_CHECKS (or uncomment the ifdefs inside verifyOrderingDominationAndDefUses for this case, there's more in another verify method). Part of the verification is disabled, even in debug build.
Or "by not sole issue" did you mean there's an additional issue not fixed by this patch?

reames added a comment.Sep 1 2021, 5:17 PM

The reason the verification didn't trigger right after LoopDeletion is that it's under EXPENSIVE_CHECKS (in verifyOrderingDominationAndDefUses). MSSA is incorrect (without this change) after LoopDeletion.

FYI, this is not the sole issue. I manually added a call to MSSA->verifyMemorySSA() unconditionally to the end of the pass, and it did not catch this.

I'm sorry, I didn't fully parse this.
Adding MSSA->verifyMemorySSA() unconditionally to the end of the pass will not catch this. You need to enable EXPENSIVE_CHECKS (or uncomment the ifdefs inside verifyOrderingDominationAndDefUses for this case, there's more in another verify method). Part of the verification is disabled, even in debug build.
Or "by not sole issue" did you mean there's an additional issue not fixed by this patch?

I'd meant that a missing call to verify memory SSA was not the sole issue. Your explanation explains why an expensive checks build found this, but local testing (on an asserts build) did not.

However, please change this. Calling verifyMemorySSA should not change behavior based on EXPENSIVE_CHECKS!! EXPENSIVE_CHECKS can decide whether to call verify, or even change a "how hard" flag to the verify routine, but a manual call to verify, should verify. It's an idiomatic pattern for all of our analyzes to be able to scatter verify calls under debug options, and have that locally catch problems in assert builds.

anna added a subscriber: anna.EditedSep 2 2021, 9:06 AM

The reason the verification didn't trigger right after LoopDeletion is that it's under EXPENSIVE_CHECKS (in verifyOrderingDominationAndDefUses). MSSA is incorrect (without this change) after LoopDeletion.

FYI, this is not the sole issue. I manually added a call to MSSA->verifyMemorySSA() unconditionally to the end of the pass, and it did not catch this.

I'm sorry, I didn't fully parse this.
Adding MSSA->verifyMemorySSA() unconditionally to the end of the pass will not catch this. You need to enable EXPENSIVE_CHECKS (or uncomment the ifdefs inside verifyOrderingDominationAndDefUses for this case, there's more in another verify method). Part of the verification is disabled, even in debug build.
Or "by not sole issue" did you mean there's an additional issue not fixed by this patch?

I'd meant that a missing call to verify memory SSA was not the sole issue. Your explanation explains why an expensive checks build found this, but local testing (on an asserts build) did not.

However, please change this. Calling verifyMemorySSA should not change behavior based on EXPENSIVE_CHECKS!! EXPENSIVE_CHECKS can decide whether to call verify, or even change a "how hard" flag to the verify routine, but a manual call to verify, should verify. It's an idiomatic pattern for all of our analyzes to be able to scatter verify calls under debug options, and have that locally catch problems in assert builds.

I agree with Philip, so currently, unconditionally calling MSSA verification does some verification, but isn't clear "how much" and we don't have a way to call the more comprehensive one without enabling EXPENSIVE_CHECKS.
@asbirlea, I had a slightly different problem :) I assumed that if we build llvm without EXPENSIVE_CHECKS and commented out the macro where we set VerifyMemorySSA, we should get the *entire* verification for MemorySSA (https://github.com/llvm/llvm-project/blob/main/llvm/lib/Analysis/MemorySSA.cpp#L88). If there are additional verifications inside MSSA verifier functionality which is *separately* guarded under EXPENSIVE_CHECKS, that isn't intuitive.

Could we pls separate out into two different verification levels such as how we do for DT (Fast versus Full) and the developer places this the Full version under EXPENSIVE_CHECKS when we call the verification routines in passes. This also lets us know exactly what verification we're getting and we can just comment out EXPENSIVE_CHECKS for debugging bugs in specific passes. Example: https://github.com/llvm/llvm-project/blob/main/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp#L609

The reason the verification didn't trigger right after LoopDeletion is that it's under EXPENSIVE_CHECKS (in verifyOrderingDominationAndDefUses). MSSA is incorrect (without this change) after LoopDeletion.

FYI, this is not the sole issue. I manually added a call to MSSA->verifyMemorySSA() unconditionally to the end of the pass, and it did not catch this.

I'm sorry, I didn't fully parse this.
Adding MSSA->verifyMemorySSA() unconditionally to the end of the pass will not catch this. You need to enable EXPENSIVE_CHECKS (or uncomment the ifdefs inside verifyOrderingDominationAndDefUses for this case, there's more in another verify method). Part of the verification is disabled, even in debug build.
Or "by not sole issue" did you mean there's an additional issue not fixed by this patch?

I'd meant that a missing call to verify memory SSA was not the sole issue. Your explanation explains why an expensive checks build found this, but local testing (on an asserts build) did not.

However, please change this. Calling verifyMemorySSA should not change behavior based on EXPENSIVE_CHECKS!! EXPENSIVE_CHECKS can decide whether to call verify, or even change a "how hard" flag to the verify routine, but a manual call to verify, should verify. It's an idiomatic pattern for all of our analyzes to be able to scatter verify calls under debug options, and have that locally catch problems in assert builds.

I agree with Philip, so currently, unconditionally calling MSSA verification does some verification, but isn't clear "how much" and we don't have a way to call the more comprehensive one without enabling EXPENSIVE_CHECKS.
@asbirlea, I had a slightly different problem :) I assumed that if we build llvm without EXPENSIVE_CHECKS and commented out the macro where we set VerifyMemorySSA, we should get the *entire* verification for MemorySSA (https://github.com/llvm/llvm-project/blob/main/llvm/lib/Analysis/MemorySSA.cpp#L88). If there are additional verifications inside MSSA verifier functionality which is *separately* guarded under EXPENSIVE_CHECKS, that isn't intuitive.

Could we pls separate out into two different verification levels such as how we do for DT (Fast versus Full) and the developer places this the Full version under EXPENSIVE_CHECKS when we call the verification routines in passes. This also lets us know exactly what verification we're getting and we can just comment out EXPENSIVE_CHECKS for debugging bugs in specific passes. Example: https://github.com/llvm/llvm-project/blob/main/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp#L609

Thank you for the suggestion, I'll send a patch for that.

Sent in https://reviews.llvm.org/rGb759381b7515 based on your suggestion. Much appreciated!