Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Passes/StandardInstrumentations.cpp
Show First 20 Lines • Show All 1,069 Lines • ▼ Show 20 Lines | |||||
bool PreservedCFGCheckerInstrumentation::CFG::invalidate( | bool PreservedCFGCheckerInstrumentation::CFG::invalidate( | ||||
Function &F, const PreservedAnalyses &PA, | Function &F, const PreservedAnalyses &PA, | ||||
FunctionAnalysisManager::Invalidator &) { | FunctionAnalysisManager::Invalidator &) { | ||||
auto PAC = PA.getChecker<PreservedCFGCheckerAnalysis>(); | auto PAC = PA.getChecker<PreservedCFGCheckerAnalysis>(); | ||||
return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>() || | return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>() || | ||||
PAC.preservedSet<CFGAnalyses>()); | PAC.preservedSet<CFGAnalyses>()); | ||||
} | } | ||||
static SmallVector<Function *, 1> GetFunctions(Any IR) { | |||||
SmallVector<Function *, 1> Functions; | |||||
if (const auto **MaybeF = any_cast<const Function *>(&IR)) { | |||||
Functions.push_back(*const_cast<Function **>(MaybeF)); | |||||
} else if (const auto **MaybeM = any_cast<const Module *>(&IR)) { | |||||
for (Function &F : **const_cast<Module **>(MaybeM)) | |||||
Functions.push_back(&F); | |||||
} | |||||
return Functions; | |||||
} | |||||
void PreservedCFGCheckerInstrumentation::registerCallbacks( | void PreservedCFGCheckerInstrumentation::registerCallbacks( | ||||
PassInstrumentationCallbacks &PIC, FunctionAnalysisManager &FAM) { | PassInstrumentationCallbacks &PIC, ModuleAnalysisManager &MAM) { | ||||
if (!VerifyAnalysisInvalidation) | if (!VerifyAnalysisInvalidation) | ||||
return; | return; | ||||
FAM.registerPass([&] { return PreservedCFGCheckerAnalysis(); }); | bool Registered = false; | ||||
FAM.registerPass([&] { return PreservedFunctionHashAnalysis(); }); | PIC.registerBeforeNonSkippedPassCallback([this, &MAM, Registered]( | ||||
StringRef P, Any IR) mutable { | |||||
PIC.registerBeforeNonSkippedPassCallback( | |||||
[this, &FAM](StringRef P, Any IR) { | |||||
#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS | #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS | ||||
assert(&PassStack.emplace_back(P)); | assert(&PassStack.emplace_back(P)); | ||||
#endif | #endif | ||||
(void)this; | (void)this; | ||||
const auto **F = any_cast<const Function *>(&IR); | |||||
if (!F) | |||||
return; | |||||
auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>( | |||||
*const_cast<Module *>(unwrapModule(IR, /*Force=*/true))) | |||||
.getManager(); | |||||
if (!Registered) { | |||||
FAM.registerPass([&] { return PreservedCFGCheckerAnalysis(); }); | |||||
FAM.registerPass([&] { return PreservedFunctionHashAnalysis(); }); | |||||
Registered = true; | |||||
} | |||||
for (Function *F : GetFunctions(IR)) { | |||||
// Make sure a fresh CFG snapshot is available before the pass. | // Make sure a fresh CFG snapshot is available before the pass. | ||||
FAM.getResult<PreservedCFGCheckerAnalysis>(*const_cast<Function *>(*F)); | FAM.getResult<PreservedCFGCheckerAnalysis>(*F); | ||||
FAM.getResult<PreservedFunctionHashAnalysis>( | FAM.getResult<PreservedFunctionHashAnalysis>(*F); | ||||
*const_cast<Function *>(*F)); | } | ||||
}); | }); | ||||
PIC.registerAfterPassInvalidatedCallback( | PIC.registerAfterPassInvalidatedCallback( | ||||
[this](StringRef P, const PreservedAnalyses &PassPA) { | [this](StringRef P, const PreservedAnalyses &PassPA) { | ||||
#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS | #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS | ||||
assert(PassStack.pop_back_val() == P && | assert(PassStack.pop_back_val() == P && | ||||
"Before and After callbacks must correspond"); | "Before and After callbacks must correspond"); | ||||
#endif | #endif | ||||
(void)this; | (void)this; | ||||
}); | }); | ||||
PIC.registerAfterPassCallback([this, &FAM](StringRef P, Any IR, | PIC.registerAfterPassCallback([this, &MAM](StringRef P, Any IR, | ||||
const PreservedAnalyses &PassPA) { | const PreservedAnalyses &PassPA) { | ||||
#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS | #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS | ||||
assert(PassStack.pop_back_val() == P && | assert(PassStack.pop_back_val() == P && | ||||
"Before and After callbacks must correspond"); | "Before and After callbacks must correspond"); | ||||
#endif | #endif | ||||
(void)this; | (void)this; | ||||
const auto **MaybeF = any_cast<const Function *>(&IR); | // We have to get the FAM via the MAM, rather than directly use a passed in | ||||
if (!MaybeF) | // FAM because if MAM has not cached the FAM, it won't invalidate function | ||||
return; | // analyses in FAM. | ||||
Function &F = *const_cast<Function *>(*MaybeF); | auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>( | ||||
*const_cast<Module *>(unwrapModule(IR, /*Force=*/true))) | |||||
.getManager(); | |||||
for (Function *F : GetFunctions(IR)) { | |||||
if (auto *HashBefore = | if (auto *HashBefore = | ||||
FAM.getCachedResult<PreservedFunctionHashAnalysis>(F)) { | FAM.getCachedResult<PreservedFunctionHashAnalysis>(*F)) { | ||||
if (HashBefore->Hash != StructuralHash(F)) { | if (HashBefore->Hash != StructuralHash(*F)) { | ||||
report_fatal_error(formatv( | report_fatal_error(formatv( | ||||
"Function @{0} changed by {1} without invalidating analyses", | "Function @{0} changed by {1} without invalidating analyses", | ||||
F.getName(), P)); | F->getName(), P)); | ||||
} | } | ||||
} | } | ||||
auto CheckCFG = [](StringRef Pass, StringRef FuncName, | auto CheckCFG = [](StringRef Pass, StringRef FuncName, | ||||
const CFG &GraphBefore, const CFG &GraphAfter) { | const CFG &GraphBefore, const CFG &GraphAfter) { | ||||
if (GraphAfter == GraphBefore) | if (GraphAfter == GraphBefore) | ||||
return; | return; | ||||
dbgs() << "Error: " << Pass | dbgs() | ||||
<< "Error: " << Pass | |||||
<< " does not invalidate CFG analyses but CFG changes detected in " | << " does not invalidate CFG analyses but CFG changes detected in " | ||||
"function @" | "function @" | ||||
<< FuncName << ":\n"; | << FuncName << ":\n"; | ||||
CFG::printDiff(dbgs(), GraphBefore, GraphAfter); | CFG::printDiff(dbgs(), GraphBefore, GraphAfter); | ||||
report_fatal_error(Twine("CFG unexpectedly changed by ", Pass)); | report_fatal_error(Twine("CFG unexpectedly changed by ", Pass)); | ||||
}; | }; | ||||
if (auto *GraphBefore = FAM.getCachedResult<PreservedCFGCheckerAnalysis>(F)) | if (auto *GraphBefore = | ||||
CheckCFG(P, F.getName(), *GraphBefore, | FAM.getCachedResult<PreservedCFGCheckerAnalysis>(*F)) | ||||
CFG(&F, /* TrackBBLifetime */ false)); | CheckCFG(P, F->getName(), *GraphBefore, | ||||
CFG(F, /* TrackBBLifetime */ false)); | |||||
} | |||||
}); | }); | ||||
} | } | ||||
void VerifyInstrumentation::registerCallbacks( | void VerifyInstrumentation::registerCallbacks( | ||||
PassInstrumentationCallbacks &PIC) { | PassInstrumentationCallbacks &PIC) { | ||||
PIC.registerAfterPassCallback( | PIC.registerAfterPassCallback( | ||||
[this](StringRef P, Any IR, const PreservedAnalyses &PassPA) { | [this](StringRef P, Any IR, const PreservedAnalyses &PassPA) { | ||||
if (isIgnored(P) || P == "VerifierPass") | if (isIgnored(P) || P == "VerifierPass") | ||||
▲ Show 20 Lines • Show All 1,013 Lines • ▼ Show 20 Lines | if (!isInteresting(IR, PassID, PIC.getPassNameForClassName(PassID))) { | ||||
return; | return; | ||||
} | } | ||||
OS << " Started ***\n"; | OS << " Started ***\n"; | ||||
unwrapAndPrint(OS, IR); | unwrapAndPrint(OS, IR); | ||||
}); | }); | ||||
} | } | ||||
void StandardInstrumentations::registerCallbacks( | void StandardInstrumentations::registerCallbacks( | ||||
PassInstrumentationCallbacks &PIC, FunctionAnalysisManager *FAM) { | PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM) { | ||||
PrintIR.registerCallbacks(PIC); | PrintIR.registerCallbacks(PIC); | ||||
PrintPass.registerCallbacks(PIC); | PrintPass.registerCallbacks(PIC); | ||||
TimePasses.registerCallbacks(PIC); | TimePasses.registerCallbacks(PIC); | ||||
OptNone.registerCallbacks(PIC); | OptNone.registerCallbacks(PIC); | ||||
OptPassGate.registerCallbacks(PIC); | OptPassGate.registerCallbacks(PIC); | ||||
PrintChangedIR.registerCallbacks(PIC); | PrintChangedIR.registerCallbacks(PIC); | ||||
PseudoProbeVerification.registerCallbacks(PIC); | PseudoProbeVerification.registerCallbacks(PIC); | ||||
if (VerifyEach) | if (VerifyEach) | ||||
Verify.registerCallbacks(PIC); | Verify.registerCallbacks(PIC); | ||||
PrintChangedDiff.registerCallbacks(PIC); | PrintChangedDiff.registerCallbacks(PIC); | ||||
WebsiteChangeReporter.registerCallbacks(PIC); | WebsiteChangeReporter.registerCallbacks(PIC); | ||||
ChangeTester.registerCallbacks(PIC); | ChangeTester.registerCallbacks(PIC); | ||||
PrintCrashIR.registerCallbacks(PIC); | PrintCrashIR.registerCallbacks(PIC); | ||||
if (FAM) | if (MAM) | ||||
PreservedCFGChecker.registerCallbacks(PIC, *FAM); | PreservedCFGChecker.registerCallbacks(PIC, *MAM); | ||||
// TimeProfiling records the pass running time cost. | // TimeProfiling records the pass running time cost. | ||||
// Its 'BeforePassCallback' can be appended at the tail of all the | // Its 'BeforePassCallback' can be appended at the tail of all the | ||||
// BeforeCallbacks by calling `registerCallbacks` in the end. | // BeforeCallbacks by calling `registerCallbacks` in the end. | ||||
// Its 'AfterPassCallback' is put at the front of all the | // Its 'AfterPassCallback' is put at the front of all the | ||||
// AfterCallbacks by its `registerCallbacks`. This is necessary | // AfterCallbacks by its `registerCallbacks`. This is necessary | ||||
// to ensure that other callbacks are not included in the timings. | // to ensure that other callbacks are not included in the timings. | ||||
TimeProfilingPasses.registerCallbacks(PIC); | TimeProfilingPasses.registerCallbacks(PIC); | ||||
Show All 13 Lines |