Skip to content

Commit c9b4169

Browse files
authored
[LifetimeSafety] Optimize fact storage with IDs and vector-based lookup (#165963)
Optimize the FactManager and DataflowAnalysis classes by using vector-based storage with ID-based lookups instead of maps. - Added a `FactID` type using the `utils::ID` template to uniquely identify facts - Modified `Fact` class to store and manage IDs - Changed `FactManager` to use vector-based storage indexed by block ID instead of a map - Updated `DataflowAnalysis` to use vector-based storage for states instead of maps - Modified lookups to use ID-based indexing for better performance Improves compile time hit on long-tail targets like `tools/clang/lib/CodeGen/CMakeFiles/obj.clangCodeGen.dir/TargetBuiltins/RISCV.cpp.o`​ from [21%](http://llvm-compile-time-tracker.com/compare_clang.php?from=6e25a04027ca786b7919657c7df330a33985ceea&to=20b42efa277c8b1915db757863e1fc26531cfd53&stat=instructions%3Au&sortBy=absolute-difference) to [3.2%](http://llvm-compile-time-tracker.com/compare_clang.php?from=6e25a04027ca786b7919657c7df330a33985ceea&to=d2d1cd1109c3a85344457bfff6f092ae7b96b211&stat=instructions%3Au&sortBy=absolute-difference)
1 parent 5314d99 commit c9b4169

File tree

4 files changed

+38
-21
lines changed

4 files changed

+38
-21
lines changed

clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@
1616

1717
#include "clang/Analysis/Analyses/LifetimeSafety/Loans.h"
1818
#include "clang/Analysis/Analyses/LifetimeSafety/Origins.h"
19+
#include "clang/Analysis/Analyses/LifetimeSafety/Utils.h"
1920
#include "clang/Analysis/AnalysisDeclContext.h"
2021
#include "clang/Analysis/CFG.h"
2122
#include "llvm/ADT/SmallVector.h"
2223
#include "llvm/Support/Debug.h"
2324
#include <cstdint>
2425

2526
namespace clang::lifetimes::internal {
27+
28+
using FactID = utils::ID<struct FactTag>;
29+
2630
/// An abstract base class for a single, atomic lifetime-relevant event.
2731
class Fact {
2832

@@ -48,6 +52,7 @@ class Fact {
4852

4953
private:
5054
Kind K;
55+
FactID ID;
5156

5257
protected:
5358
Fact(Kind K) : K(K) {}
@@ -56,6 +61,9 @@ class Fact {
5661
virtual ~Fact() = default;
5762
Kind getKind() const { return K; }
5863

64+
void setID(FactID ID) { this->ID = ID; }
65+
FactID getID() const { return ID; }
66+
5967
template <typename T> const T *getAs() const {
6068
if (T::classof(this))
6169
return static_cast<const T *>(this);
@@ -183,22 +191,26 @@ class TestPointFact : public Fact {
183191

184192
class FactManager {
185193
public:
194+
void init(const CFG &Cfg) {
195+
assert(BlockToFacts.empty() && "FactManager already initialized");
196+
BlockToFacts.resize(Cfg.getNumBlockIDs());
197+
}
198+
186199
llvm::ArrayRef<const Fact *> getFacts(const CFGBlock *B) const {
187-
auto It = BlockToFactsMap.find(B);
188-
if (It != BlockToFactsMap.end())
189-
return It->second;
190-
return {};
200+
return BlockToFacts[B->getBlockID()];
191201
}
192202

193203
void addBlockFacts(const CFGBlock *B, llvm::ArrayRef<Fact *> NewFacts) {
194204
if (!NewFacts.empty())
195-
BlockToFactsMap[B].assign(NewFacts.begin(), NewFacts.end());
205+
BlockToFacts[B->getBlockID()].assign(NewFacts.begin(), NewFacts.end());
196206
}
197207

198208
template <typename FactType, typename... Args>
199209
FactType *createFact(Args &&...args) {
200210
void *Mem = FactAllocator.Allocate<FactType>();
201-
return new (Mem) FactType(std::forward<Args>(args)...);
211+
FactType *Res = new (Mem) FactType(std::forward<Args>(args)...);
212+
Res->setID(NextFactID++);
213+
return Res;
202214
}
203215

204216
void dump(const CFG &Cfg, AnalysisDeclContext &AC) const;
@@ -214,16 +226,19 @@ class FactManager {
214226
/// \note This is intended for testing only.
215227
llvm::StringMap<ProgramPoint> getTestPoints() const;
216228

229+
unsigned getNumFacts() const { return NextFactID.Value; }
230+
217231
LoanManager &getLoanMgr() { return LoanMgr; }
218232
const LoanManager &getLoanMgr() const { return LoanMgr; }
219233
OriginManager &getOriginMgr() { return OriginMgr; }
220234
const OriginManager &getOriginMgr() const { return OriginMgr; }
221235

222236
private:
237+
FactID NextFactID{0};
223238
LoanManager LoanMgr;
224239
OriginManager OriginMgr;
225-
llvm::DenseMap<const clang::CFGBlock *, llvm::SmallVector<const Fact *>>
226-
BlockToFactsMap;
240+
/// Facts for each CFG block, indexed by block ID.
241+
llvm::SmallVector<llvm::SmallVector<const Fact *>> BlockToFacts;
227242
llvm::BumpPtrAllocator FactAllocator;
228243
};
229244
} // namespace clang::lifetimes::internal

clang/lib/Analysis/LifetimeSafety/Dataflow.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,10 @@ class DataflowAnalysis {
6767
llvm::DenseMap<const CFGBlock *, Lattice> InStates;
6868
/// The dataflow state after a basic block is processed.
6969
llvm::DenseMap<const CFGBlock *, Lattice> OutStates;
70-
/// The dataflow state at a Program Point.
70+
/// Dataflow state at each program point, indexed by Fact ID.
7171
/// In a forward analysis, this is the state after the Fact at that point has
7272
/// been applied, while in a backward analysis, it is the state before.
73-
llvm::DenseMap<ProgramPoint, Lattice> PerPointStates;
73+
llvm::SmallVector<Lattice> PointToState;
7474

7575
static constexpr bool isForward() { return Dir == Direction::Forward; }
7676

@@ -86,6 +86,8 @@ class DataflowAnalysis {
8686
Derived &D = static_cast<Derived &>(*this);
8787
llvm::TimeTraceScope Time(D.getAnalysisName());
8888

89+
PointToState.resize(FactMgr.getNumFacts());
90+
8991
using Worklist =
9092
std::conditional_t<Dir == Direction::Forward, ForwardDataflowWorklist,
9193
BackwardDataflowWorklist>;
@@ -116,7 +118,9 @@ class DataflowAnalysis {
116118
}
117119

118120
protected:
119-
Lattice getState(ProgramPoint P) const { return PerPointStates.lookup(P); }
121+
Lattice getState(ProgramPoint P) const {
122+
return PointToState[P->getID().Value];
123+
}
120124

121125
std::optional<Lattice> getInState(const CFGBlock *B) const {
122126
auto It = InStates.find(B);
@@ -144,12 +148,12 @@ class DataflowAnalysis {
144148
if constexpr (isForward()) {
145149
for (const Fact *F : Facts) {
146150
State = transferFact(State, F);
147-
PerPointStates[F] = State;
151+
PointToState[F->getID().Value] = State;
148152
}
149153
} else {
150154
for (const Fact *F : llvm::reverse(Facts)) {
151155
// In backward analysis, capture the state before applying the fact.
152-
PerPointStates[F] = State;
156+
PointToState[F->getID().Value] = State;
153157
State = transferFact(State, F);
154158
}
155159
}

clang/lib/Analysis/LifetimeSafety/Facts.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ void TestPointFact::dump(llvm::raw_ostream &OS, const LoanManager &,
6464

6565
llvm::StringMap<ProgramPoint> FactManager::getTestPoints() const {
6666
llvm::StringMap<ProgramPoint> AnnotationToPointMap;
67-
for (const CFGBlock *Block : BlockToFactsMap.keys()) {
68-
for (const Fact *F : getFacts(Block)) {
67+
for (const auto &BlockFacts : BlockToFacts) {
68+
for (const Fact *F : BlockFacts) {
6969
if (const auto *TPF = F->getAs<TestPointFact>()) {
7070
StringRef PointName = TPF->getAnnotation();
7171
assert(AnnotationToPointMap.find(PointName) ==
@@ -88,12 +88,9 @@ void FactManager::dump(const CFG &Cfg, AnalysisDeclContext &AC) const {
8888
// Print blocks in the order as they appear in code for a stable ordering.
8989
for (const CFGBlock *B : *AC.getAnalysis<PostOrderCFGView>()) {
9090
llvm::dbgs() << " Block B" << B->getBlockID() << ":\n";
91-
auto It = BlockToFactsMap.find(B);
92-
if (It != BlockToFactsMap.end()) {
93-
for (const Fact *F : It->second) {
94-
llvm::dbgs() << " ";
95-
F->dump(llvm::dbgs(), LoanMgr, OriginMgr);
96-
}
91+
for (const Fact *F : getFacts(B)) {
92+
llvm::dbgs() << " ";
93+
F->dump(llvm::dbgs(), LoanMgr, OriginMgr);
9794
}
9895
llvm::dbgs() << " End of Block\n";
9996
}

clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ void LifetimeSafetyAnalysis::run() {
4141
const CFG &Cfg = *AC.getCFG();
4242
DEBUG_WITH_TYPE("PrintCFG", Cfg.dump(AC.getASTContext().getLangOpts(),
4343
/*ShowColors=*/true));
44+
FactMgr.init(Cfg);
4445

4546
FactsGenerator FactGen(FactMgr, AC);
4647
FactGen.run();

0 commit comments

Comments
 (0)