Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add Useful Analysis to the forward mode #1120

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/clad/Differentiator/CladConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ enum opts : unsigned {
disable_tbr = 1 << (ORDER_BITS + 3),
enable_va = 1 << (ORDER_BITS + 5),
disable_va = 1 << (ORDER_BITS + 6),
enable_ua = 1 << (ORDER_BITS + 7),
disable_ua = 1 << (ORDER_BITS + 8),

// Specifying whether we only want the diagonal of the hessian.
diagonal_only = 1 << (ORDER_BITS + 4),
Expand Down
11 changes: 11 additions & 0 deletions include/clad/Differentiator/DiffPlanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,16 @@ struct DiffRequest {
bool HasAnalysisRun = false;
} m_ActivityRunInfo;

mutable struct UsefulRunInfo {
std::set<const clang::VarDecl*> UsefulDecls;
std::set<const clang::FunctionDecl*> UsefulFuncs;
bool HasAnalysisRun = false;
} m_UsefulRunInfo;

public:
/// Function to be differentiated.
const clang::FunctionDecl* Function = nullptr;
bool ReqAdj = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'ReqAdj' has public visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  bool ReqAdj = true;
       ^

/// Name of the base function to be differentiated. Can be different from
/// function->getNameAsString() when higher-order derivatives are computed.
std::string BaseFunctionName = {};
Expand All @@ -65,6 +72,7 @@ struct DiffRequest {
/// A flag to enable TBR analysis during reverse-mode differentiation.
bool EnableTBRAnalysis = false;
bool EnableVariedAnalysis = false;
bool EnableUsefulAnalysis = false;
ovdiiuv marked this conversation as resolved.
Show resolved Hide resolved
/// Puts the derived function and its code in the diff call
void updateCall(clang::FunctionDecl* FD, clang::FunctionDecl* OverloadedFD,
clang::Sema& SemaRef);
Expand Down Expand Up @@ -123,6 +131,7 @@ struct DiffRequest {
CallContext == other.CallContext && Args == other.Args &&
Mode == other.Mode && EnableTBRAnalysis == other.EnableTBRAnalysis &&
EnableVariedAnalysis == other.EnableVariedAnalysis &&
EnableUsefulAnalysis == other.EnableUsefulAnalysis &&
DVI == other.DVI && use_enzyme == other.use_enzyme &&
DeclarationOnly == other.DeclarationOnly;
}
Expand All @@ -141,6 +150,7 @@ struct DiffRequest {

bool shouldBeRecorded(clang::Expr* E) const;
bool shouldHaveAdjoint(const clang::VarDecl* VD) const;
bool shouldHaveAdjointForw(const clang::VarDecl* VD) const;
};

using DiffInterval = std::vector<clang::SourceRange>;
Expand All @@ -150,6 +160,7 @@ struct DiffRequest {
/// TBR analysis during reverse-mode differentiation.
bool EnableTBRAnalysis = false;
bool EnableVariedAnalysis = false;
bool EnableUsefulAnalysis = false;
};

class DiffCollector: public clang::RecursiveASTVisitor<DiffCollector> {
Expand Down
24 changes: 21 additions & 3 deletions lib/Differentiator/BaseForwardModeVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1063,7 +1063,14 @@
// If DRE is of type pointer, then the derivative is a null pointer.
if (clonedDRE->getType()->isPointerType())
return StmtDiff(clonedDRE, nullptr);

if (auto* i = dyn_cast<VarDecl>(DRE->getDecl())) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'auto *i' can be declared as 'const auto *i' [readability-qualified-auto]

Suggested change
if (auto* i = dyn_cast<VarDecl>(DRE->getDecl())) {
if (const auto* i = dyn_cast<VarDecl>(DRE->getDecl())) {

if (!m_DiffReq.shouldHaveAdjointForw(i))
return StmtDiff(clonedDRE, nullptr);

Check warning on line 1069 in lib/Differentiator/BaseForwardModeVisitor.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/BaseForwardModeVisitor.cpp#L1069

Added line #L1069 was not covered by tests
}

QualType literalTy = utils::GetValueType(clonedDRE->getType());

return StmtDiff(clonedDRE, ConstantFolder::synthesizeLiteral(
literalTy, m_Context, /*val=*/0));
}
Expand Down Expand Up @@ -1208,6 +1215,7 @@
}

llvm::SmallVector<Expr*, 16> pushforwardFnArgs;
//
pushforwardFnArgs.insert(pushforwardFnArgs.end(), CallArgs.begin(),
CallArgs.end());
pushforwardFnArgs.insert(pushforwardFnArgs.end(), diffArgs.begin(),
Expand Down Expand Up @@ -1284,6 +1292,7 @@
pushforwardFnRequest.BaseFunctionName = utils::ComputeEffectiveFnName(FD);
// Silence diag outputs in nested derivation process.
pushforwardFnRequest.VerboseDiags = false;
pushforwardFnRequest.EnableUsefulAnalysis = m_DiffReq.EnableUsefulAnalysis;

// Check if request already derived in DerivedFunctions.
FunctionDecl* pushforwardFD =
Expand Down Expand Up @@ -1446,7 +1455,8 @@
derivedR = BuildParens(derivedR);
opDiff = BuildOp(opCode, derivedL, derivedR);
} else if (BinOp->isAssignmentOp()) {
if (Ldiff.getExpr_dx()->isModifiableLvalue(m_Context) != Expr::MLV_Valid) {
if (Ldiff.getExpr_dx() &&
Ldiff.getExpr_dx()->isModifiableLvalue(m_Context) != Expr::MLV_Valid) {
diag(DiagnosticsEngine::Warning, BinOp->getEndLoc(),
"derivative of an assignment attempts to assign to unassignable "
"expr, assignment ignored");
Expand Down Expand Up @@ -1575,11 +1585,16 @@
VarDecl* VDDerived =
BuildVarDecl(VD->getType(), "_d_" + VD->getNameAsString(), initDx,
VD->isDirectInit(), /*TSI=*/nullptr, VD->getInitStyle());
m_Variables.emplace(VDClone, BuildDeclRef(VDDerived));

if (!m_DiffReq.shouldHaveAdjointForw(VD))
VDDerived = nullptr;

Check warning on line 1590 in lib/Differentiator/BaseForwardModeVisitor.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/BaseForwardModeVisitor.cpp#L1590

Added line #L1590 was not covered by tests
else
m_Variables.emplace(VDClone, BuildDeclRef(VDDerived));
return DeclDiff<VarDecl>(VDClone, VDDerived);
}

StmtDiff BaseForwardModeVisitor::VisitDeclStmt(const DeclStmt* DS) {
// llvm::errs() << "\nVisitDeclStmt";
llvm::SmallVector<Decl*, 4> decls;
llvm::SmallVector<Decl*, 4> declsDiff;
// If the type is marked as non_differentiable, skip generating its derivative
Expand Down Expand Up @@ -1642,7 +1657,8 @@
if (VDDiff.getDecl()->getDeclName() != VD->getDeclName())
m_DeclReplacements[VD] = VDDiff.getDecl();
decls.push_back(VDDiff.getDecl());
declsDiff.push_back(VDDiff.getDecl_dx());
if (m_DiffReq.shouldHaveAdjointForw(VD))
declsDiff.push_back(VDDiff.getDecl_dx());
} else if (auto* SAD = dyn_cast<StaticAssertDecl>(D)) {
DeclDiff<StaticAssertDecl> SADDiff = DifferentiateStaticAssertDecl(SAD);
if (SADDiff.getDecl())
Expand All @@ -1661,6 +1677,8 @@
DSClone = BuildDeclStmt(decls);
if (!declsDiff.empty())
DSDiff = BuildDeclStmt(declsDiff);
// llvm::errs() << "\n=====";
// DSDiff->dump();
return StmtDiff(DSClone, DSDiff);
}

Expand Down
1 change: 1 addition & 0 deletions lib/Differentiator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ llvm_add_library(cladDifferentiator
ReverseModeVisitor.cpp
TBRAnalyzer.cpp
StmtClone.cpp
UsefulAnalyzer.cpp
VectorForwardModeVisitor.cpp
VectorPushForwardModeVisitor.cpp
Version.cpp
Expand Down
31 changes: 31 additions & 0 deletions lib/Differentiator/DiffPlanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "ActivityAnalyzer.h"
#include "TBRAnalyzer.h"
#include "UsefulAnalyzer.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
Expand Down Expand Up @@ -636,6 +637,26 @@
return found != m_ActivityRunInfo.ToBeRecorded.end();
}

bool DiffRequest::shouldHaveAdjointForw(const VarDecl* VD) const {
if (!EnableUsefulAnalysis)
return true;

if (!m_UsefulRunInfo.HasAnalysisRun) {

Check warning on line 644 in lib/Differentiator/DiffPlanner.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/DiffPlanner.cpp#L644

Added line #L644 was not covered by tests

UsefulAnalyzer analyzer(Function->getASTContext(),
m_UsefulRunInfo.UsefulDecls,
m_UsefulRunInfo.UsefulFuncs);
analyzer.Analyze(Function);
m_UsefulRunInfo.HasAnalysisRun = true;

Check warning on line 650 in lib/Differentiator/DiffPlanner.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/DiffPlanner.cpp#L646-L650

Added lines #L646 - L650 were not covered by tests
// llvm::errs() << "ToBeRecorded: ";
// for (auto* i : m_UsefulRunInfo.UsefulDecls)
// llvm::errs() << i->getNameAsString() << " ";
// llvm::errs() << "\n";
}
auto found = m_UsefulRunInfo.UsefulDecls.find(VD);
return found != m_UsefulRunInfo.UsefulDecls.end();

Check warning on line 657 in lib/Differentiator/DiffPlanner.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/DiffPlanner.cpp#L655-L657

Added lines #L655 - L657 were not covered by tests
}

bool DiffCollector::VisitCallExpr(CallExpr* E) {
// Check if we should look into this.
// FIXME: Generated code does not usually have valid source locations.
Expand Down Expand Up @@ -669,6 +690,8 @@
bool disable_tbr_in_req = false;
bool enable_va_in_req = false;
bool disable_va_in_req = false;
bool enable_ua_in_req = false;
bool disable_ua_in_req = false;
if (!A->getAnnotation().equals("E") &&
FD->getTemplateSpecializationArgs()) {
const auto template_arg = FD->getTemplateSpecializationArgs()->get(0);
Expand All @@ -689,6 +712,10 @@
clad::HasOption(bitmasked_opts_value, clad::opts::enable_va);
disable_va_in_req =
clad::HasOption(bitmasked_opts_value, clad::opts::disable_va);
enable_ua_in_req =
clad::HasOption(bitmasked_opts_value, clad::opts::enable_ua);
disable_ua_in_req =
clad::HasOption(bitmasked_opts_value, clad::opts::disable_ua);
if (enable_tbr_in_req && disable_tbr_in_req) {
utils::EmitDiag(m_Sema, DiagnosticsEngine::Error, endLoc,
"Both enable and disable TBR options are specified.");
Expand All @@ -711,6 +738,10 @@
} else {
request.EnableVariedAnalysis = m_Options.EnableVariedAnalysis;
}
if (enable_ua_in_req || disable_ua_in_req)
request.EnableUsefulAnalysis = enable_ua_in_req && !disable_ua_in_req;

Check warning on line 742 in lib/Differentiator/DiffPlanner.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/DiffPlanner.cpp#L742

Added line #L742 was not covered by tests
else
request.EnableUsefulAnalysis = m_Options.EnableUsefulAnalysis;
if (clad::HasOption(bitmasked_opts_value, clad::opts::diagonal_only)) {
if (!A->getAnnotation().equals("H")) {
utils::EmitDiag(m_Sema, DiagnosticsEngine::Error, endLoc,
Expand Down
1 change: 0 additions & 1 deletion lib/Differentiator/PushForwardModeVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ StmtDiff PushForwardModeVisitor::VisitReturnStmt(const ReturnStmt* RS) {
// If there is no return value, we must not attempt to differentiate
if (!RS->getRetValue())
return nullptr;

StmtDiff retValDiff = Visit(RS->getRetValue());
Expr* retVal = retValDiff.getExpr();
Expr* retVal_dx = retValDiff.getExpr_dx();
Expand Down
156 changes: 156 additions & 0 deletions lib/Differentiator/UsefulAnalyzer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#include "UsefulAnalyzer.h"

using namespace clang;

namespace clad {

void UsefulAnalyzer::Analyze(const FunctionDecl* FD) {

Check warning on line 7 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L7

Added line #L7 was not covered by tests
// Build the CFG (control-flow graph) of FD.
clang::CFG::BuildOptions Options;
m_CFG = clang::CFG::buildCFG(FD, FD->getBody(), &m_Context, Options);

Check warning on line 10 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L9-L10

Added lines #L9 - L10 were not covered by tests

m_BlockData.resize(m_CFG->size());

Check warning on line 12 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L12

Added line #L12 was not covered by tests
// Set current block ID to the ID of entry the block.
CFGBlock* exit = &m_CFG->getExit();
m_CurBlockID = exit->getBlockID();
m_BlockData[m_CurBlockID] = createNewVarsData({});
for (const VarDecl* i : m_UsefulDecls)
m_BlockData[m_CurBlockID]->insert(i);

Check warning on line 18 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L14-L18

Added lines #L14 - L18 were not covered by tests
// Add the entry block to the queue.
m_CFGQueue.insert(m_CurBlockID);

Check warning on line 20 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L20

Added line #L20 was not covered by tests

// Visit CFG blocks in the queue until it's empty.
while (!m_CFGQueue.empty()) {
auto IDIter = m_CFGQueue.begin();
m_CurBlockID = *IDIter;
m_CFGQueue.erase(IDIter);
CFGBlock& nextBlock = *getCFGBlockByID(m_CurBlockID);
AnalyzeCFGBlock(nextBlock);

Check warning on line 28 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L23-L28

Added lines #L23 - L28 were not covered by tests
}
}

Check warning on line 30 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L30

Added line #L30 was not covered by tests

CFGBlock* UsefulAnalyzer::getCFGBlockByID(unsigned ID) {
return *(m_CFG->begin() + ID);

Check warning on line 33 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L32-L33

Added lines #L32 - L33 were not covered by tests
}

bool UsefulAnalyzer::isUseful(const VarDecl* VD) const {
const VarsData& curBranch = getCurBlockVarsData();
return curBranch.find(VD) != curBranch.end();

Check warning on line 38 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L36-L38

Added lines #L36 - L38 were not covered by tests
}

void UsefulAnalyzer::copyVarToCurBlock(const clang::VarDecl* VD) {
VarsData& curBranch = getCurBlockVarsData();
curBranch.insert(VD);
}

Check warning on line 44 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L41-L44

Added lines #L41 - L44 were not covered by tests

static void mergeVarsData(std::set<const clang::VarDecl*>* targetData,

Check warning on line 46 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L46

Added line #L46 was not covered by tests
std::set<const clang::VarDecl*>* mergeData) {
for (const clang::VarDecl* i : *mergeData)
targetData->insert(i);
*mergeData = *targetData;
}

Check warning on line 51 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L48-L51

Added lines #L48 - L51 were not covered by tests

void UsefulAnalyzer::AnalyzeCFGBlock(const CFGBlock& block) {

Check warning on line 53 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L53

Added line #L53 was not covered by tests

for (auto ib = block.end(); ib != block.begin() - 1; ib--) {
if (ib->getKind() == clang::CFGElement::Statement) {

Check warning on line 56 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L55-L56

Added lines #L55 - L56 were not covered by tests

const clang::Stmt* S = ib->castAs<clang::CFGStmt>().getStmt();

Check warning on line 58 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L58

Added line #L58 was not covered by tests
// The const_cast is inevitable, since there is no
// ConstRecusiveASTVisitor.
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
TraverseStmt(const_cast<clang::Stmt*>(S));

Check warning on line 62 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L62

Added line #L62 was not covered by tests
}
}

for (const clang::CFGBlock::AdjacentBlock pred : block.preds()) {
if (!pred)
continue;
auto& predData = m_BlockData[pred->getBlockID()];
if (!predData)
predData = createNewVarsData(*m_BlockData[block.getBlockID()]);

Check warning on line 71 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L66-L71

Added lines #L66 - L71 were not covered by tests

bool shouldPushPred = true;
if (pred->getBlockID() < block.getBlockID()) {
if (m_LoopMem == *m_BlockData[block.getBlockID()])
shouldPushPred = false;

Check warning on line 76 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L73-L76

Added lines #L73 - L76 were not covered by tests

for (const VarDecl* i : *m_BlockData[block.getBlockID()])
m_LoopMem.insert(i);

Check warning on line 79 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L78-L79

Added lines #L78 - L79 were not covered by tests
}

if (shouldPushPred)
m_CFGQueue.insert(pred->getBlockID());

Check warning on line 83 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L82-L83

Added lines #L82 - L83 were not covered by tests

mergeVarsData(predData.get(), m_BlockData[block.getBlockID()].get());

Check warning on line 85 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L85

Added line #L85 was not covered by tests
}

for (const VarDecl* i : *m_BlockData[block.getBlockID()])
m_UsefulDecls.insert(i);
}

Check warning on line 90 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L88-L90

Added lines #L88 - L90 were not covered by tests

bool UsefulAnalyzer::VisitBinaryOperator(BinaryOperator* BinOp) {
Expr* L = BinOp->getLHS();
Expr* R = BinOp->getRHS();
const auto opCode = BinOp->getOpcode();
if (BinOp->isAssignmentOp()) {
m_Useful = false;
TraverseStmt(L);
m_Marking = m_Useful;
TraverseStmt(R);
m_Marking = false;
} else if (opCode == BO_Add || opCode == BO_Sub || opCode == BO_Mul ||

Check warning on line 102 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L92-L102

Added lines #L92 - L102 were not covered by tests
opCode == BO_Div) {
for (auto* subexpr : BinOp->children())
if (!isa<BinaryOperator>(subexpr))
TraverseStmt(subexpr);

Check warning on line 106 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L104-L106

Added lines #L104 - L106 were not covered by tests
}
return true;

Check warning on line 108 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L108

Added line #L108 was not covered by tests
}

bool UsefulAnalyzer::VisitDeclStmt(DeclStmt* DS) {
for (Decl* D : DS->decls()) {
if (auto* VD = dyn_cast<VarDecl>(D)) {
if (isUseful(VD)) {
m_Useful = true;
m_Marking = true;

Check warning on line 116 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L111-L116

Added lines #L111 - L116 were not covered by tests
}
if (Expr* init = cast<VarDecl>(D)->getInit())
TraverseStmt(init);
m_Marking = false;

Check warning on line 120 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L118-L120

Added lines #L118 - L120 were not covered by tests
}
}
return true;

Check warning on line 123 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L123

Added line #L123 was not covered by tests
}

bool UsefulAnalyzer::VisitReturnStmt(ReturnStmt* RS) {
m_Useful = true;
m_Marking = true;
auto* rv = RS->getRetValue();
TraverseStmt(rv);
return true;

Check warning on line 131 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L126-L131

Added lines #L126 - L131 were not covered by tests
}

bool UsefulAnalyzer::VisitCallExpr(CallExpr* CE) {
if (m_Useful)
return true;
FunctionDecl* FD = CE->getDirectCallee();
m_UsefulFuncs.insert(FD);
return true;

Check warning on line 139 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L134-L139

Added lines #L134 - L139 were not covered by tests
}

bool UsefulAnalyzer::VisitDeclRefExpr(DeclRefExpr* DRE) {
auto* VD = dyn_cast<VarDecl>(DRE->getDecl());
if (!VD)
return true;

Check warning on line 145 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L142-L145

Added lines #L142 - L145 were not covered by tests

if (isUseful(VD))
m_Useful = true;

Check warning on line 148 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L147-L148

Added lines #L147 - L148 were not covered by tests

if (m_Useful && m_Marking)
copyVarToCurBlock(VD);

Check warning on line 151 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L150-L151

Added lines #L150 - L151 were not covered by tests

return true;

Check warning on line 153 in lib/Differentiator/UsefulAnalyzer.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/UsefulAnalyzer.cpp#L153

Added line #L153 was not covered by tests
}

} // namespace clad
Loading
Loading