[CGSCC] Properly handle invalidating analyses for invalidated SCCs

Currently if we mark an SCC as invalid, if we haven't set UR.UpdatedC, we won't propagate the PreservedAnalyses up to the parent pass (adaptor/pass manager).

In the provided test case, we inline the function into itself then delete it as it has no users. The SCC is marked as invalid without providing a replacement UR.UpdatedC. Then the CGSCC pass manager and adaptor discard the PreservedAnalyses. Instead, handle PreservedAnalyses first before bailing due to the invalid SCC.

Fixes crashes due to out of date analyses.
This commit is contained in:
Arthur Eubanks 2022-09-21 09:04:06 -07:00
parent f3222be4fc
commit f77342693b
2 changed files with 31 additions and 11 deletions

View File

@ -100,22 +100,23 @@ PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &,
ResultFAMCP->updateFAM(FAM);
}
// Intersect the final preserved analyses to compute the aggregate
// preserved set for this pass manager.
PA.intersect(PassPA);
// If the CGSCC pass wasn't able to provide a valid updated SCC, the
// current SCC may simply need to be skipped if invalid.
if (UR.InvalidatedSCCs.count(C)) {
LLVM_DEBUG(dbgs() << "Skipping invalidated root or island SCC!\n");
break;
}
// Check that we didn't miss any update scenario.
assert(C->begin() != C->end() && "Cannot have an empty SCC!");
// Update the analysis manager as each pass runs and potentially
// invalidates analyses.
AM.invalidate(*C, PassPA);
// Finally, we intersect the final preserved analyses to compute the
// aggregate preserved set for this pass manager.
PA.intersect(std::move(PassPA));
}
// Before we mark all of *this* SCC's analyses as preserved below, intersect
@ -290,12 +291,20 @@ ModuleToPostOrderCGSCCPassAdaptor::run(Module &M, ModuleAnalysisManager &AM) {
FAM);
}
// Intersect with the cross-SCC preserved set to capture any
// cross-SCC invalidation.
UR.CrossSCCPA.intersect(PassPA);
// Intersect the preserved set so that invalidation of module
// analyses will eventually occur when the module pass completes.
PA.intersect(PassPA);
// If the CGSCC pass wasn't able to provide a valid updated SCC,
// the current SCC may simply need to be skipped if invalid.
if (UR.InvalidatedSCCs.count(C)) {
LLVM_DEBUG(dbgs() << "Skipping invalidated root or island SCC!\n");
break;
}
// Check that we didn't miss any update scenario.
assert(C->begin() != C->end() && "Cannot have an empty SCC!");
@ -307,13 +316,6 @@ ModuleToPostOrderCGSCCPassAdaptor::run(Module &M, ModuleAnalysisManager &AM) {
// processed.
CGAM.invalidate(*C, PassPA);
// Then intersect the preserved set so that invalidation of module
// analyses will eventually occur when the module pass completes.
// Also intersect with the cross-SCC preserved set to capture any
// cross-SCC invalidation.
UR.CrossSCCPA.intersect(PassPA);
PA.intersect(std::move(PassPA));
// The pass may have restructured the call graph and refined the
// current SCC and/or RefSCC. We need to update our current SCC and
// RefSCC pointers to follow these. Also, when the current SCC is

View File

@ -0,0 +1,18 @@
; RUN: opt -passes='require<no-op-module>,inline' < %s -S -debug-pass-manager 2>&1 | FileCheck %s
; CHECK: Invalidating analysis: NoOpModuleAnalysis
; CHECK: ModuleID
; CHECK-NOT: define
define linkonce_odr i32 @f(i1 %0) {
br i1 %0, label %2, label %4
2: ; preds = %1
%3 = call i32 @f(i1 false)
br label %4
4: ; preds = %2, %1
ret i32 0
}