Skip to content

Commit d409411

Browse files
committed
Track validity of pass results
Running tests with expensive checks enabled exhibits some problems with verification of pass results. First, the pass verification may require results of analysis that are not available. For instance, verification of loop info requires results of dominator tree analysis. A pass may be marked as conserving loop info but does not need to be dependent on DominatorTreePass. When a pass manager tries to verify that loop info is valid, it needs dominator tree, but corresponding analysis may be already destroyed as no user of it remained. Another case is a pass that is skipped. For instance, entities with linkage available_externally do not need code generation and such passes are skipped for them. In this case result verification must also be skipped. To solve these problems this change introduces a special flag to the Pass structure to mark passes that have valid results. If this flag is reset, verifications dependent on the pass result are skipped. Differential Revision: https://reviews.llvm.org/D27190 llvm-svn: 291882
1 parent d30e6f7 commit d409411

File tree

11 files changed

+67
-17
lines changed

11 files changed

+67
-17
lines changed

llvm/include/llvm/Pass.h

+30-6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#ifndef LLVM_PASS_H
3030
#define LLVM_PASS_H
3131

32+
#include <assert.h>
3233
#include <string>
3334

3435
namespace llvm {
@@ -82,17 +83,40 @@ class Pass {
8283
AnalysisResolver *Resolver; // Used to resolve analysis
8384
const void *PassID;
8485
PassKind Kind;
86+
bool Executed;
87+
8588
void operator=(const Pass&) = delete;
8689
Pass(const Pass &) = delete;
8790

8891
public:
8992
explicit Pass(PassKind K, char &pid)
90-
: Resolver(nullptr), PassID(&pid), Kind(K) { }
93+
: Resolver(nullptr), PassID(&pid), Kind(K), Executed(false) { }
9194
virtual ~Pass();
9295

93-
9496
PassKind getPassKind() const { return Kind; }
9597

98+
/// Returns true if the pass has already executed.
99+
///
100+
/// For an analysis pass it means the result is available. If the function
101+
/// returns false, the pass was not run, was skipped or freed.
102+
///
103+
bool isExecuted() const { return Executed; }
104+
105+
/// Marks the pass as executed or not.
106+
///
107+
/// A pass should be marked as executed, if its 'runOn*' method successfully
108+
/// finished. When the pass is not needed anymore, it is marked as
109+
/// 'non-executed', it takes place in \c freePass. It also occurs when the
110+
/// pass is skipped for some reason.
111+
///
112+
/// The flag should be set prior to call to 'runOn*' method. If it decides
113+
/// that the pass should be skipped, it will reset the flag.
114+
///
115+
void setExecuted(bool x) {
116+
assert(x || !getAsImmutablePass()); // Immutable pass cannot be invalidated.
117+
Executed = x;
118+
}
119+
96120
/// getPassName - Return a nice clean name for a pass. This usually
97121
/// implemented in terms of the name that is registered by one of the
98122
/// Registration templates, but can be overloaded directly.
@@ -279,8 +303,7 @@ class ImmutablePass : public ModulePass {
279303
///
280304
bool runOnModule(Module &) override { return false; }
281305

282-
explicit ImmutablePass(char &pid)
283-
: ModulePass(pid) {}
306+
explicit ImmutablePass(char &pid) : ModulePass(pid) { setExecuted(true); }
284307

285308
// Force out-of-line virtual method.
286309
~ImmutablePass() override;
@@ -316,8 +339,9 @@ class FunctionPass : public Pass {
316339
protected:
317340
/// Optional passes call this function to check whether the pass should be
318341
/// skipped. This is the case when Attribute::OptimizeNone is set or when
319-
/// optimization bisect is over the limit.
320-
bool skipFunction(const Function &F) const;
342+
/// optimization bisect is over the limit. It also resets flag Executed on
343+
/// the pass.
344+
bool skipFunction(const Function &F);
321345
};
322346

323347

llvm/include/llvm/PassAnalysisSupport.h

+5
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@ AnalysisType *Pass::getAnalysisIfAvailable() const {
206206
Pass *ResultPass = Resolver->getAnalysisIfAvailable(PI, true);
207207
if (!ResultPass) return nullptr;
208208

209+
if (!ResultPass->isExecuted())
210+
return nullptr;
211+
209212
// Because the AnalysisType may not be a subclass of pass (for
210213
// AnalysisGroups), we use getAdjustedAnalysisPointer here to potentially
211214
// adjust the return pointer (because the class may multiply inherit, once
@@ -234,6 +237,8 @@ AnalysisType &Pass::getAnalysisID(AnalysisID PI) const {
234237
assert (ResultPass &&
235238
"getAnalysis*() called on an analysis that was not "
236239
"'required' by pass!");
240+
assert(ResultPass->isExecuted() &&
241+
"getAnalysis*() called on an analysis that was freed");
237242

238243
// Because the AnalysisType may not be a subclass of pass (for
239244
// AnalysisGroups), we use getAdjustedAnalysisPointer here to potentially

llvm/lib/Analysis/CallGraphSCCPass.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ bool CGPassManager::RunAllPassesOnSCC(CallGraphSCC &CurSCC, CallGraph &CG,
414414
initializeAnalysisImpl(P);
415415

416416
// Actually run this pass on the current SCC.
417+
P->setExecuted(true);
417418
Changed |= RunPassOnSCC(P, CurSCC, CG,
418419
CallGraphUpToDate, DevirtualizedCall);
419420

llvm/lib/Analysis/LoopInfo.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -722,8 +722,10 @@ void LoopInfoWrapperPass::verifyAnalysis() const {
722722
// checking by default, LoopPass has been taught to call verifyLoop manually
723723
// during loop pass sequences.
724724
if (VerifyLoopInfo) {
725-
auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
726-
LI.verify(DT);
725+
if (auto *Analysis = getAnalysisIfAvailable<DominatorTreeWrapperPass>()) {
726+
auto &DT = Analysis->getDomTree();
727+
LI.verify(DT);
728+
}
727729
}
728730
}
729731

llvm/lib/Analysis/LoopPass.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ bool LPPassManager::runOnFunction(Function &F) {
198198
PassManagerPrettyStackEntry X(P, *CurrentLoop->getHeader());
199199
TimeRegion PassTimer(getPassTimer(P));
200200

201+
P->setExecuted(true);
201202
Changed |= P->runOnLoop(CurrentLoop, *this);
202203
}
203204
LoopWasDeleted = CurrentLoop->isInvalid();

llvm/lib/CodeGen/MachineDominators.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ void MachineDominatorTree::releaseMemory() {
6969
}
7070

7171
void MachineDominatorTree::verifyAnalysis() const {
72-
if (VerifyMachineDomInfo)
72+
if (VerifyMachineDomInfo && isExecuted())
7373
verifyDomTree();
7474
}
7575

llvm/lib/CodeGen/MachineFunctionPass.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@ Pass *MachineFunctionPass::createPrinterPass(raw_ostream &O,
3838
bool MachineFunctionPass::runOnFunction(Function &F) {
3939
// Do not codegen any 'available_externally' functions at all, they have
4040
// definitions outside the translation unit.
41-
if (F.hasAvailableExternallyLinkage())
41+
if (F.hasAvailableExternallyLinkage()) {
42+
setExecuted(false);
4243
return false;
44+
}
4345

4446
MachineModuleInfo &MMI = getAnalysis<MachineModuleInfo>();
4547
MachineFunction &MF = MMI.getMachineFunction(F);

llvm/lib/IR/LegacyPassManager.cpp

+15-3
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,9 @@ void PMDataManager::freePass(Pass *P, StringRef Msg,
955955
AvailableAnalysis.erase(Pos);
956956
}
957957
}
958+
959+
if (!P->getAsImmutablePass())
960+
P->setExecuted(false);
958961
}
959962

960963
/// Add pass P into the PassVector. Update
@@ -1293,6 +1296,7 @@ bool BBPassManager::runOnFunction(Function &F) {
12931296
PassManagerPrettyStackEntry X(BP, *I);
12941297
TimeRegion PassTimer(getPassTimer(BP));
12951298

1299+
BP->setExecuted(true);
12961300
LocalChanged |= BP->runOnBasicBlock(*I);
12971301
}
12981302

@@ -1459,7 +1463,9 @@ bool FunctionPassManagerImpl::run(Function &F) {
14591463

14601464
initializeAllAnalysisInfo();
14611465
for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) {
1462-
Changed |= getContainedManager(Index)->runOnFunction(F);
1466+
FPPassManager *P = getContainedManager(Index);
1467+
P->setExecuted(true);
1468+
Changed |= P->runOnFunction(F);
14631469
F.getContext().yield();
14641470
}
14651471

@@ -1510,6 +1516,7 @@ bool FPPassManager::runOnFunction(Function &F) {
15101516
PassManagerPrettyStackEntry X(FP, F);
15111517
TimeRegion PassTimer(getPassTimer(FP));
15121518

1519+
FP->setExecuted(true);
15131520
LocalChanged |= FP->runOnFunction(F);
15141521
}
15151522

@@ -1530,8 +1537,10 @@ bool FPPassManager::runOnFunction(Function &F) {
15301537
bool FPPassManager::runOnModule(Module &M) {
15311538
bool Changed = false;
15321539

1533-
for (Function &F : M)
1540+
for (Function &F : M) {
1541+
setExecuted(true);
15341542
Changed |= runOnFunction(F);
1543+
}
15351544

15361545
return Changed;
15371546
}
@@ -1587,6 +1596,7 @@ MPPassManager::runOnModule(Module &M) {
15871596
PassManagerPrettyStackEntry X(MP, M);
15881597
TimeRegion PassTimer(getPassTimer(MP));
15891598

1599+
MP->setExecuted(true);
15901600
LocalChanged |= MP->runOnModule(M);
15911601
}
15921602

@@ -1690,7 +1700,9 @@ bool PassManagerImpl::run(Module &M) {
16901700

16911701
initializeAllAnalysisInfo();
16921702
for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) {
1693-
Changed |= getContainedManager(Index)->runOnModule(M);
1703+
MPPassManager *P = getContainedManager(Index);
1704+
P->setExecuted(true);
1705+
Changed |= P->runOnModule(M);
16941706
M.getContext().yield();
16951707
}
16961708

llvm/lib/IR/Pass.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -146,13 +146,16 @@ PassManagerType FunctionPass::getPotentialPassManagerType() const {
146146
return PMT_FunctionPassManager;
147147
}
148148

149-
bool FunctionPass::skipFunction(const Function &F) const {
150-
if (!F.getContext().getOptBisect().shouldRunPass(this, F))
149+
bool FunctionPass::skipFunction(const Function &F) {
150+
if (!F.getContext().getOptBisect().shouldRunPass(this, F)) {
151+
setExecuted(false);
151152
return true;
153+
}
152154

153155
if (F.hasFnAttribute(Attribute::OptimizeNone)) {
154156
DEBUG(dbgs() << "Skipping pass '" << getPassName() << "' on function "
155157
<< F.getName() << "\n");
158+
setExecuted(false);
156159
return true;
157160
}
158161
return false;

llvm/test/CodeGen/Generic/externally_available.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: llc < %s | not grep test_
1+
; RUN: llc -verify-machine-dom-info < %s | not grep test_
22

33
; test_function should not be emitted to the .s file.
44
define available_externally i32 @test_function() {

llvm/test/CodeGen/Mips/mul.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: llc -march=mipsel -mattr=mips16 -relocation-model=pic -O3 < %s | FileCheck %s -check-prefix=16
1+
; RUN: llc -march=mipsel -mattr=mips16 -relocation-model=pic -O3 -verify-loop-info < %s | FileCheck %s -check-prefix=16
22

33
@iiii = global i32 5, align 4
44
@jjjj = global i32 -6, align 4

0 commit comments

Comments
 (0)