Skip to content

Commit ed49f31

Browse files
Max Andriychukovdiiuv
authored andcommitted
Introduce AnalysisDeclContext to avoid repetetive CFG construction
1 parent a1352d1 commit ed49f31

10 files changed

Lines changed: 99 additions & 68 deletions

File tree

include/clad/Differentiator/DiffPlanner.h

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,19 @@
88
#include "clad/Differentiator/Timers.h"
99

1010
#include "clang/AST/Decl.h"
11+
#include "clang/AST/DeclBase.h"
1112
#include "clang/AST/ExprCXX.h"
1213
#include "clang/AST/RecursiveASTVisitor.h"
14+
#include "clang/Analysis/AnalysisDeclContext.h"
1315

1416
#include "llvm/ADT/DenseSet.h"
17+
#include "llvm/ADT/SmallVector.h"
1518
#include "llvm/Support/Compiler.h"
1619
#include "llvm/Support/SaveAndRestore.h"
1720
#include "llvm/Support/raw_ostream.h"
1821

1922
#include <iterator>
23+
#include <memory>
2024
#include <set>
2125

2226
namespace clang {
@@ -31,7 +35,8 @@ class Type;
3135
} // namespace clang
3236

3337
namespace clad {
34-
38+
using OwnedAnalysisContexts =
39+
llvm::SmallVector<std::unique_ptr<clang::AnalysisDeclContext>, 4>;
3540
/// A struct containing information about request to differentiate a function.
3641
struct DiffRequest {
3742
private:
@@ -123,6 +128,8 @@ struct DiffRequest {
123128
/// This will be particularly useful for pushforward and pullback functions.
124129
bool DeclarationOnly = false;
125130

131+
clang::AnalysisDeclContext* m_AnalysisDC;
132+
126133
/// Recomputes `DiffInputVarsInfo` using the current values of data members.
127134
///
128135
/// Differentiation parameters info is computed by parsing the argument
@@ -146,6 +153,8 @@ struct DiffRequest {
146153
// Note that CallContext is always different and we should ignore it.
147154
// CustomDerivative is an Expr* and is not always equal even if
148155
// the set of overloads is the same.
156+
// Including AnalysisDC would complicate constructing requests to find the
157+
// existing once.
149158
return Function == other.Function &&
150159
BaseFunctionName == other.BaseFunctionName &&
151160
CurrentDerivativeOrder == other.CurrentDerivativeOrder &&
@@ -178,6 +187,10 @@ struct DiffRequest {
178187
std::string ComputeDerivativeName() const;
179188
bool HasIndependentParameter(const clang::ParmVarDecl* PVD) const;
180189

190+
std::set<clang::SourceLocation>& getToBeRecorded() const {
191+
m_TbrRunInfo.HasAnalysisRun = true;
192+
return m_TbrRunInfo.ToBeRecorded;
193+
}
181194
void addVariedDecl(const clang::VarDecl* init) {
182195
m_ActivityRunInfo.VariedDecls.insert(init);
183196
}
@@ -190,6 +203,7 @@ struct DiffRequest {
190203
std::set<const clang::VarDecl*>& getUsefulDecls() const {
191204
return m_UsefulRunInfo.UsefulDecls;
192205
}
206+
bool HasTbrAnalysisRun() const { return m_TbrRunInfo.HasAnalysisRun; }
193207
};
194208

195209
using DiffInterval = std::vector<clang::SourceRange>;
@@ -210,7 +224,10 @@ struct DiffRequest {
210224
/// Graph to store the dependencies between different requests.
211225
///
212226
clad::DynamicGraph<DiffRequest>& m_DiffRequestGraph;
213-
227+
/// Map that contains all AnalysisDeclContext for all declrations.
228+
/// Essentially needed for prolonging the lifetime of
229+
/// unique_ptr<clang::AnalysisDeclContext>.
230+
OwnedAnalysisContexts& m_AllAnalysisDC;
214231
/// If set it means that we need to find the called functions and
215232
/// add them for implicit diff.
216233
///
@@ -228,7 +245,7 @@ struct DiffRequest {
228245
public:
229246
DiffCollector(clang::DeclGroupRef DGR, DiffInterval& Interval,
230247
clad::DynamicGraph<DiffRequest>& requestGraph, clang::Sema& S,
231-
RequestOptions& opts);
248+
RequestOptions& opts, OwnedAnalysisContexts& AllAnalysisDC);
232249
bool VisitCallExpr(clang::CallExpr* E);
233250
bool VisitDeclRefExpr(clang::DeclRefExpr* DRE);
234251
bool VisitCXXConstructExpr(clang::CXXConstructExpr* e);

lib/Differentiator/ActivityAnalyzer.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,10 @@ using namespace clang;
66
namespace clad {
77

88
void VariedAnalyzer::Analyze(const FunctionDecl* FD) {
9-
// Build the CFG (control-flow graph) of FD.
10-
clang::CFG::BuildOptions Options;
11-
m_CFG = clang::CFG::buildCFG(FD, FD->getBody(), &m_Context, Options);
12-
13-
m_BlockData.resize(m_CFG->size());
9+
m_BlockData.resize(m_AnalysisDC->getCFG()->size());
1410
// Set current block ID to the ID of entry the block.
15-
CFGBlock* entry = &m_CFG->getEntry();
16-
m_CurBlockID = entry->getBlockID();
11+
CFGBlock& entry = m_AnalysisDC->getCFG()->getEntry();
12+
m_CurBlockID = entry.getBlockID();
1713
m_BlockData[m_CurBlockID] = createNewVarsData({});
1814
for (const VarDecl* i : m_VariedDecls)
1915
m_BlockData[m_CurBlockID]->insert(i);
@@ -38,7 +34,7 @@ void mergeVarsData(std::set<const clang::VarDecl*>* targetData,
3834
}
3935

4036
CFGBlock* VariedAnalyzer::getCFGBlockByID(unsigned ID) {
41-
return *(m_CFG->begin() + ID);
37+
return *(m_AnalysisDC->getCFG()->begin() + ID);
4238
}
4339

4440
void VariedAnalyzer::AnalyzeCFGBlock(const CFGBlock& block) {

lib/Differentiator/ActivityAnalyzer.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define CLAD_DIFFERENTIATOR_ACTIVITYANALYZER_H
33

44
#include "clang/AST/RecursiveASTVisitor.h"
5+
#include "clang/Analysis/AnalysisDeclContext.h"
56
#include "clang/Analysis/CFG.h"
67

78
#include "clad/Differentiator/CladUtils.h"
@@ -35,8 +36,7 @@ class VariedAnalyzer : public clang::RecursiveASTVisitor<VariedAnalyzer> {
3536

3637
clang::CFGBlock* getCFGBlockByID(unsigned ID);
3738

38-
clang::ASTContext& m_Context;
39-
std::unique_ptr<clang::CFG> m_CFG;
39+
clang::AnalysisDeclContext* m_AnalysisDC;
4040
std::vector<std::unique_ptr<VarsData>> m_BlockData;
4141
unsigned m_CurBlockID{};
4242
std::set<unsigned> m_CFGQueue;
@@ -55,9 +55,9 @@ class VariedAnalyzer : public clang::RecursiveASTVisitor<VariedAnalyzer> {
5555

5656
public:
5757
/// Constructor
58-
VariedAnalyzer(clang::ASTContext& Context,
58+
VariedAnalyzer(clang::AnalysisDeclContext* AnalysisDC,
5959
std::set<const clang::VarDecl*>& Decls)
60-
: m_VariedDecls(Decls), m_Context(Context) {}
60+
: m_VariedDecls(Decls), m_AnalysisDC(AnalysisDC) {}
6161

6262
/// Destructor
6363
~VariedAnalyzer() = default;

lib/Differentiator/DiffPlanner.cpp

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#include "clang/AST/ExprCXX.h"
2222
#include "clang/AST/ExprObjC.h"
2323
#include "clang/AST/RecursiveASTVisitor.h"
24-
#include "clang/Analysis/CallGraph.h"
24+
#include "clang/Analysis/AnalysisDeclContext.h"
2525
#include "clang/Basic/IdentifierTable.h"
2626
#include "clang/Basic/LLVM.h" // isa, dyn_cast
2727
#include "clang/Basic/SourceLocation.h"
@@ -32,6 +32,7 @@
3232
#include "clang/Sema/TemplateDeduction.h"
3333

3434
#include <algorithm>
35+
#include <memory>
3536
#include <string>
3637
#include <utility>
3738

@@ -273,9 +274,10 @@ DeclRefExpr* getArgFunction(CallExpr* call, Sema& SemaRef) {
273274

274275
DiffCollector::DiffCollector(DeclGroupRef DGR, DiffInterval& Interval,
275276
clad::DynamicGraph<DiffRequest>& requestGraph,
276-
clang::Sema& S, RequestOptions& opts)
277-
: m_Interval(Interval), m_DiffRequestGraph(requestGraph), m_Sema(S),
278-
m_Options(opts) {
277+
clang::Sema& S, RequestOptions& opts,
278+
OwnedAnalysisContexts& AllAnalysisDC)
279+
: m_Interval(Interval), m_DiffRequestGraph(requestGraph),
280+
m_AllAnalysisDC(AllAnalysisDC), m_Sema(S), m_Options(opts) {
279281

280282
if (Interval.empty())
281283
return;
@@ -648,13 +650,11 @@ DeclRefExpr* getArgFunction(CallExpr* call, Sema& SemaRef) {
648650
if (E->getType()->isPointerType())
649651
return true;
650652

651-
if (!m_TbrRunInfo.HasAnalysisRun && !isLambdaCallOperator(Function)) {
653+
if (!m_TbrRunInfo.HasAnalysisRun && !isLambdaCallOperator(Function) &&
654+
Function->isDefined()) {
652655
TimedAnalysisRegion R("TBR " + BaseFunctionName);
653-
654-
TBRAnalyzer analyzer(Function->getASTContext(),
655-
m_TbrRunInfo.ToBeRecorded);
656-
analyzer.Analyze(Function);
657-
m_TbrRunInfo.HasAnalysisRun = true;
656+
TBRAnalyzer analyzer(m_AnalysisDC, getToBeRecorded());
657+
analyzer.Analyze(*this);
658658
}
659659
auto found = m_TbrRunInfo.ToBeRecorded.find(E->getBeginLoc());
660660
return found != m_TbrRunInfo.ToBeRecorded.end();
@@ -1214,22 +1214,27 @@ DeclRefExpr* getArgFunction(CallExpr* call, Sema& SemaRef) {
12141214
request.Function = request.Function->getDefinition();
12151215

12161216
if (!LookupCustomDerivativeDecl(request)) {
1217-
if (m_TopMostReq->EnableVariedAnalysis &&
1218-
m_TopMostReq->Mode == DiffMode::reverse) {
1217+
clang::CFG::BuildOptions Options;
1218+
std::unique_ptr<AnalysisDeclContext> AnalysisDC =
1219+
std::make_unique<AnalysisDeclContext>(
1220+
/*AnalysisDeclContextManager=*/nullptr, request.Function,
1221+
Options);
1222+
1223+
if (m_TopMostReq->EnableVariedAnalysis) {
12191224
TimedAnalysisRegion R("VA " + request.BaseFunctionName);
1220-
VariedAnalyzer analyzer(request.Function->getASTContext(),
1221-
request.getVariedDecls());
1225+
VariedAnalyzer analyzer(AnalysisDC.get(), request.getVariedDecls());
12221226
analyzer.Analyze(request.Function);
12231227
}
12241228

12251229
if (m_TopMostReq->EnableUsefulAnalysis) {
12261230
TimedAnalysisRegion R("UA " + request.BaseFunctionName);
1227-
1228-
UsefulAnalyzer analyzer(request.Function->getASTContext(),
1229-
request.getUsefulDecls());
1231+
UsefulAnalyzer analyzer(AnalysisDC.get(), request.getUsefulDecls());
12301232
analyzer.Analyze(request.Function);
12311233
}
12321234

1235+
m_AllAnalysisDC.push_back(std::move(AnalysisDC));
1236+
request.m_AnalysisDC = m_AllAnalysisDC.back().get();
1237+
12331238
// Recurse into call graph.
12341239
TraverseFunctionDeclOnce(request.Function);
12351240
}
@@ -1313,9 +1318,19 @@ DeclRefExpr* getArgFunction(CallExpr* call, Sema& SemaRef) {
13131318
if (m_Sema.isStdInitializerList(recordTy, /*elemType=*/nullptr))
13141319
return true;
13151320

1316-
if (!LookupCustomDerivativeDecl(request))
1321+
if (!LookupCustomDerivativeDecl(request)) {
1322+
clang::CFG::BuildOptions Options;
1323+
std::unique_ptr<AnalysisDeclContext> AnalysisDC =
1324+
std::make_unique<AnalysisDeclContext>(
1325+
/*AnalysisDeclContextManager=*/nullptr, request.Function,
1326+
Options);
1327+
// FIXME: Add proper support for objects in VA and UA.
1328+
m_AllAnalysisDC.push_back(std::move(AnalysisDC));
1329+
request.m_AnalysisDC = m_AllAnalysisDC.back().get();
1330+
13171331
// Recurse into call graph.
13181332
TraverseFunctionDeclOnce(request.Function);
1333+
}
13191334
m_DiffRequestGraph.addNode(request, /*isSource=*/true);
13201335

13211336
return true;

lib/Differentiator/TBRAnalyzer.cpp

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,12 @@
88
#include "clang/AST/Expr.h"
99
#include "clang/AST/ExprCXX.h"
1010
#include "clang/AST/OperationKinds.h"
11+
#include "clang/Analysis/CFG.h"
1112
#include "clang/Basic/LLVM.h"
1213

14+
#include "clad/Differentiator/Compatibility.h"
15+
#include "clad/Differentiator/DiffPlanner.h"
16+
1317
#include "llvm/ADT/SmallVector.h"
1418
#include "llvm/Support/Casting.h"
1519
#include "llvm/Support/Debug.h"
@@ -251,6 +255,7 @@ void TBRAnalyzer::addVar(const clang::VarDecl* VD, bool forceNonRefType) {
251255
varType = arrayParam->getOriginalType();
252256
else
253257
varType = VD->getType();
258+
254259
// If varType represents auto or auto*, get the type of init.
255260
if (utils::IsAutoOrAutoPtrType(varType))
256261
varType = VD->getInit()->getType();
@@ -294,19 +299,16 @@ TBRAnalyzer::getVarDataFromDecl(const clang::VarDecl* VD) {
294299
return nullptr;
295300
}
296301

297-
void TBRAnalyzer::Analyze(const FunctionDecl* FD) {
298-
// Build the CFG (control-flow graph) of FD.
299-
clang::CFG::BuildOptions Options;
300-
m_CFG = clang::CFG::buildCFG(FD, FD->getBody(), &m_Context, Options);
301-
302-
m_BlockData.resize(m_CFG->size());
303-
m_BlockPassCounter.resize(m_CFG->size(), 0);
302+
void TBRAnalyzer::Analyze(const DiffRequest& request) {
303+
m_BlockData.resize(request.m_AnalysisDC->getCFG()->size());
304+
m_BlockPassCounter.resize(request.m_AnalysisDC->getCFG()->size(), 0);
304305

305306
// Set current block ID to the ID of entry the block.
306-
auto* entry = &m_CFG->getEntry();
307-
m_CurBlockID = entry->getBlockID();
307+
CFGBlock& entry = request.m_AnalysisDC->getCFG()->getEntry();
308+
m_CurBlockID = entry.getBlockID();
308309
m_BlockData[m_CurBlockID] = std::unique_ptr<VarsData>(new VarsData());
309310

311+
const FunctionDecl* FD = request.Function;
310312
// If we are analysing a non-static method, add a VarData for 'this' pointer
311313
// (it is represented with nullptr).
312314
const auto* MD = dyn_cast<CXXMethodDecl>(FD);
@@ -331,13 +333,13 @@ void TBRAnalyzer::Analyze(const FunctionDecl* FD) {
331333
m_CurBlockID = *IDIter;
332334
m_CFGQueue.erase(IDIter);
333335

334-
CFGBlock& nextBlock = *getCFGBlockByID(m_CurBlockID);
336+
CFGBlock& nextBlock = *getCFGBlockByID(request.m_AnalysisDC, m_CurBlockID);
335337
VisitCFGBlock(nextBlock);
336338
}
337339
#ifndef NDEBUG
338340
for (int id = m_CurBlockID; id >= 0; --id) {
339341
LLVM_DEBUG(llvm::dbgs() << "\n-----BLOCK" << id << "-----\n\n");
340-
for (auto succ : getCFGBlockByID(id)->succs())
342+
for (auto succ : getCFGBlockByID(request.m_AnalysisDC, id)->succs())
341343
if (succ)
342344
LLVM_DEBUG(llvm::dbgs() << "successor: " << succ->getBlockID() << "\n");
343345
}
@@ -409,8 +411,8 @@ void TBRAnalyzer::VisitCFGBlock(const CFGBlock& block) {
409411
LLVM_DEBUG(llvm::dbgs() << "Leaving block " << block.getBlockID() << "\n");
410412
}
411413

412-
CFGBlock* TBRAnalyzer::getCFGBlockByID(unsigned ID) {
413-
return *(m_CFG->begin() + ID);
414+
CFGBlock* TBRAnalyzer::getCFGBlockByID(AnalysisDeclContext* ADC, unsigned ID) {
415+
return *(ADC->getCFG()->begin() + ID);
414416
}
415417

416418
TBRAnalyzer::VarsData*
@@ -566,9 +568,11 @@ bool TBRAnalyzer::TraverseDeclStmt(DeclStmt* DS) {
566568
if (auto* VD = dyn_cast<VarDecl>(D)) {
567569
addVar(VD);
568570
if (clang::Expr* init = VD->getInit()) {
571+
569572
setMode(Mode::kMarkingMode);
570573
TraverseStmt(init);
571574
resetMode();
575+
572576
auto& VDExpr = getCurBlockVarsData()[VD];
573577
// if the declared variable is ref type attach its VarData to the
574578
// VarData of the RHS variable.

0 commit comments

Comments
 (0)