Skip to content

Commit 05ac596

Browse files
committed
[arc] Cache isARCInertBB in an analysis called ProgramTerminationAnalysis.
One important property that we take advantage of in ARC is that along certain paths we know that the language leaks memory meaning that these blocks are effectively inert from ARC's perspective. In general these leaking blocks are when we know that the program is going to terminate fatally through something along the lines of fatalError. This analysis just serves as a cache of this information since it is starting to become used in multiple parts of the pass pipeline.
1 parent f4c7fa4 commit 05ac596

File tree

3 files changed

+89
-0
lines changed

3 files changed

+89
-0
lines changed

include/swift/SILAnalysis/Analysis.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ ANALYSIS(Loop)
3535
ANALYSIS(LoopRegion)
3636
ANALYSIS(PostDominance)
3737
ANALYSIS(PostOrder)
38+
ANALYSIS(ProgramTermination)
3839
ANALYSIS(RCIdentity)
3940
ANALYSIS(SideEffect)
4041

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//===--- ProgramTerminationAnalysis.h -------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
///
13+
/// \file
14+
///
15+
/// This is an analysis which determines if a block is a "program terminating
16+
/// block". Define a program terminating block is defined as follows:
17+
///
18+
/// 1. A block at whose end point according to the SIL model, the program must
19+
/// end. An example of such a block is one that includes a call to fatalError.
20+
/// 2. Any block that is joint post-dominated by program terminating blocks.
21+
///
22+
/// For now we only identify instances of 1. But the analysis could be extended
23+
/// appropriately via simple dataflow or through the use of post-dominator
24+
/// trees.
25+
///
26+
//===----------------------------------------------------------------------===//
27+
28+
#ifndef SWIFT_SILANALYSIS_PROGRAMTERMINATIONANALYSIS_H
29+
#define SWIFT_SILANALYSIS_PROGRAMTERMINATIONANALYSIS_H
30+
31+
#include "swift/SILAnalysis/Analysis.h"
32+
#include "swift/SILAnalysis/ARCAnalysis.h"
33+
#include "llvm/ADT/SmallPtrSet.h"
34+
35+
namespace swift {
36+
37+
class ProgramTerminationFunctionInfo {
38+
llvm::SmallPtrSet<SILBasicBlock *, 4> ProgramTerminatingBlocks;
39+
40+
public:
41+
ProgramTerminationFunctionInfo(SILFunction *F) {
42+
for (auto &BB : *F) {
43+
if (!isARCInertTrapBB(&BB))
44+
continue;
45+
ProgramTerminatingBlocks.insert(&BB);
46+
}
47+
}
48+
49+
bool isProgramTerminatingBlock(SILBasicBlock *BB) {
50+
return ProgramTerminatingBlocks.count(BB);
51+
}
52+
};
53+
54+
class ProgramTerminationAnalysis
55+
: public FunctionAnalysisBase<ProgramTerminationFunctionInfo> {
56+
public:
57+
ProgramTerminationAnalysis(SILModule *M)
58+
: FunctionAnalysisBase<ProgramTerminationFunctionInfo>(
59+
AnalysisKind::ProgramTermination) {}
60+
61+
ProgramTerminationAnalysis(const ProgramTerminationAnalysis &) = delete;
62+
ProgramTerminationAnalysis &
63+
operator=(const ProgramTerminationAnalysis &) = delete;
64+
65+
static bool classof(const SILAnalysis *S) {
66+
return S->getKind() == AnalysisKind::ProgramTermination;
67+
}
68+
69+
virtual void initialize(SILPassManager *PM) override {}
70+
71+
virtual ProgramTerminationFunctionInfo *
72+
newFunctionAnalysis(SILFunction *F) override {
73+
return new ProgramTerminationFunctionInfo(F);
74+
}
75+
76+
virtual bool shouldInvalidate(SILAnalysis::InvalidationKind K) override {
77+
return K & InvalidationKind::Branches;
78+
}
79+
};
80+
81+
} // end swift namespace
82+
83+
#endif

lib/SILAnalysis/Analysis.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "swift/SILAnalysis/PostOrderAnalysis.h"
1919
#include "swift/SILAnalysis/CallGraphAnalysis.h"
2020
#include "swift/SILAnalysis/ClassHierarchyAnalysis.h"
21+
#include "swift/SILAnalysis/ProgramTerminationAnalysis.h"
2122
#include "swift/AST/Module.h"
2223
#include "swift/AST/SILOptions.h"
2324
#include "swift/SIL/SILModule.h"
@@ -60,3 +61,7 @@ SILAnalysis *swift::createClassHierarchyAnalysis(SILModule *M) {
6061
SILAnalysis *swift::createBasicCalleeAnalysis(SILModule *M) {
6162
return new BasicCalleeAnalysis(M);
6263
}
64+
65+
SILAnalysis *swift::createProgramTerminationAnalysis(SILModule *M) {
66+
return new ProgramTerminationAnalysis(M);
67+
}

0 commit comments

Comments
 (0)