Skip to content

Commit fde70aa

Browse files
Vedant2005goyalvgvassilev
authored andcommitted
Add support for SourceLocExpr during differentiation to enable code containing assert and other source-location builtins.
1 parent 67937c2 commit fde70aa

7 files changed

Lines changed: 88 additions & 4 deletions

File tree

include/clad/Differentiator/BaseForwardModeVisitor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ class BaseForwardModeVisitor
9999
StmtDiff VisitWhileStmt(const clang::WhileStmt* WS);
100100
StmtDiff VisitDoStmt(const clang::DoStmt* DS);
101101
StmtDiff VisitContinueStmt(const clang::ContinueStmt* ContStmt);
102+
StmtDiff VisitSourceLocExpr(const clang::SourceLocExpr* E);
102103

103104
StmtDiff VisitSwitchStmt(const clang::SwitchStmt* SS);
104105
StmtDiff VisitBreakStmt(const clang::BreakStmt* BS);

include/clad/Differentiator/ReverseModeVisitor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,7 @@ namespace clad {
485485
StmtDiff VisitImplicitCastExpr(const clang::ImplicitCastExpr* ICE);
486486
StmtDiff VisitGNUNullExpr(const clang::GNUNullExpr* E);
487487
StmtDiff VisitPredefinedExpr(const clang::PredefinedExpr* E);
488+
StmtDiff VisitSourceLocExpr(const clang::SourceLocExpr* SLE);
488489

489490
#if CLANG_VERSION_MAJOR > 16
490491
StmtDiff VisitLambdaExpr(const clang::LambdaExpr* LE);

include/clad/Differentiator/StmtClone.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ namespace utils {
7979
DECLARE_CLONE_FN(CXXCatchStmt)
8080
DECLARE_CLONE_FN(CXXTryStmt)
8181
DECLARE_CLONE_FN(PredefinedExpr)
82+
DECLARE_CLONE_FN(SourceLocExpr)
8283
DECLARE_CLONE_FN(CharacterLiteral)
8384
DECLARE_CLONE_FN(FloatingLiteral)
8485
DECLARE_CLONE_FN(ImaginaryLiteral)

lib/Differentiator/BaseForwardModeVisitor.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,8 @@ StmtDiff BaseForwardModeVisitor::VisitConditionalOperator(
581581
.ActOnConditionalOp(noLoc, noLoc, cond, ifTrueDiff.getExpr(),
582582
ifFalseDiff.getExpr())
583583
.get();
584-
584+
if (condExpr->getType()->isVoidType())
585+
return StmtDiff(condExpr, nullptr);
585586
// cond is already used by the value conditional above; clone it for the
586587
// derivative conditional so the two do not share the stored condition.
587588
Expr* condExprDiff =
@@ -1262,7 +1263,7 @@ StmtDiff BaseForwardModeVisitor::VisitCallExpr(const CallExpr* CE) {
12621263
if (!isa<CXXOperatorCallExpr>(CE) && !isa<CXXMemberCallExpr>(CE) &&
12631264
!needsForwPass) {
12641265
bool allArgsHaveZeroDerivatives = true;
1265-
for (unsigned i = 0, e = CE->getNumArgs(); i < e; ++i) {
1266+
for (unsigned i = 0, e = diffArgs.size(); i < e; ++i) {
12661267
Expr* dArg = diffArgs[i];
12671268
// If argDiff.expr_dx is nullptr or is a constant 0, then the derivative
12681269
// of the function call is 0.
@@ -1321,7 +1322,7 @@ StmtDiff BaseForwardModeVisitor::VisitCallExpr(const CallExpr* CE) {
13211322
// If clad failed to derive it, try finding its derivative using
13221323
// numerical diff.
13231324
if (!callDiff) {
1324-
Multiplier = diffArgs[0];
1325+
Multiplier = diffArgs.empty() ? nullptr : diffArgs[0];
13251326
Expr* call =
13261327
m_Sema
13271328
.ActOnCallExpr(getCurrentScope(), Clone(CE->getCallee()), validLoc,
@@ -1533,7 +1534,7 @@ BaseForwardModeVisitor::VisitBinaryOperator(const BinaryOperator* BinOp) {
15331534
} else if (opCode == BO_Comma) {
15341535
// if expression is (E1, E2) then derivative is (E1', E1, E2')
15351536
// because E1 may change some variables that E2 depends on.
1536-
if (!isUnusedResult(Ldiff.getExpr_dx())) {
1537+
if (Ldiff.getExpr_dx() && !isUnusedResult(Ldiff.getExpr_dx())) {
15371538
opDiff = BuildOp(BO_Comma, BuildParens(Ldiff.getExpr_dx()),
15381539
BuildParens(Ldiff.getExpr()));
15391540
opDiff = BuildOp(BO_Comma, BuildParens(opDiff),
@@ -1874,6 +1875,13 @@ StmtDiff BaseForwardModeVisitor::VisitStringLiteral(const StringLiteral* SL) {
18741875
SL->getType(), utils::GetValidSLoc(m_Sema)));
18751876
}
18761877

1878+
StmtDiff
1879+
BaseForwardModeVisitor::VisitSourceLocExpr(const clang::SourceLocExpr* E) {
1880+
auto* Constant0 =
1881+
ConstantFolder::synthesizeLiteral(m_Context.IntTy, m_Context, /*val=*/0);
1882+
return StmtDiff(CloneNode(E), Constant0);
1883+
}
1884+
18771885
StmtDiff BaseForwardModeVisitor::VisitWhileStmt(const WhileStmt* WS) {
18781886
// Scope for the whole while loop.
18791887
ScopeRAII whileScope(*this, Scope::ContinueScope | Scope::BreakScope |

lib/Differentiator/ReverseModeVisitor.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2957,6 +2957,10 @@ Expr* ReverseModeVisitor::getStdInitListSizeExpr(const Expr* E) {
29572957
for (Stmt* S : revBlock)
29582958
addToCurrentBlock(S, direction::reverse);
29592959
return {cloneE, derivedE};
2960+
} else if (opCode == UnaryOperatorKind::UO_Extension) {
2961+
diff = Visit(E);
2962+
ResultRef = diff.getExpr_dx();
2963+
valueForRevPass = diff.getRevSweepAsExpr();
29602964
} else {
29612965
if (opCode != UO_LNot)
29622966
// We should only output warnings on visiting boolean conditions
@@ -3919,6 +3923,13 @@ Expr* ReverseModeVisitor::getStdInitListSizeExpr(const Expr* E) {
39193923
return StmtDiff(CloneNode(E), Constant0);
39203924
}
39213925

3926+
StmtDiff
3927+
ReverseModeVisitor::VisitSourceLocExpr(const clang::SourceLocExpr* E) {
3928+
auto* Constant0 = ConstantFolder::synthesizeLiteral(m_Context.IntTy,
3929+
m_Context, /*val=*/0);
3930+
return StmtDiff(CloneNode(E), Constant0);
3931+
}
3932+
39223933
StmtDiff ReverseModeVisitor::VisitCXXFunctionalCastExpr(
39233934
const clang::CXXFunctionalCastExpr* FCE) {
39243935
StmtDiff castExprDiff = Visit(FCE->getSubExpr(), dfdx());

lib/Differentiator/StmtClone.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,16 @@ Stmt* StmtClone::VisitPredefinedExpr(PredefinedExpr* Node) {
9292
clad_compat::ExprSetDeps(result, Node);
9393
return result;
9494
}
95+
#if CLANG_VERSION_MAJOR >= 15
96+
DEFINE_CLONE_EXPR(SourceLocExpr,
97+
(Ctx, Node->getIdentKind(), CloneType(Node->getType()),
98+
Node->getBeginLoc(), Node->getEndLoc(),
99+
Node->getParentContext()))
100+
#else
101+
DEFINE_CLONE_EXPR(SourceLocExpr,
102+
(Ctx, Node->getIdentKind(), Node->getBeginLoc(),
103+
Node->getEndLoc(), Node->getParentContext()))
104+
#endif
95105
DEFINE_CLONE_EXPR(CharacterLiteral,
96106
(Node->getValue(), Node->getKind(),
97107
CloneType(Node->getType()), Node->getLocation()))

test/Features/DiffAssert.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// RUN: %cladclang -std=c++17 -I%S/../../include %s -o %t
2+
// RUN: %t | %filecheck_exec %s
3+
4+
#include <cassert>
5+
#include "clad/Differentiator/Differentiator.h"
6+
7+
double func(double x){
8+
assert(x>0.0);
9+
return x*x*x;
10+
}
11+
double func1(double x) {
12+
const char* file = __builtin_FILE();
13+
int line = __builtin_LINE();
14+
return x*x*x;
15+
}
16+
17+
void temp() {}
18+
double temp_func(double x) {
19+
x > 0.0 ? temp() : temp();
20+
return x * x * x;
21+
}
22+
23+
int main(){
24+
auto d_func=clad::gradient(func);
25+
double dx=0;
26+
d_func.execute(3.0,&dx);
27+
printf("Diff result: %.2f\n", dx);
28+
//CHECK-EXEC: Diff result: 27.00
29+
30+
auto d_func_forw=clad::differentiate(func);
31+
auto res_forw=d_func_forw.execute(3.0);
32+
printf("Diff result: %.2f\n", res_forw);
33+
// CHECK-EXEC: Diff result: 27.00
34+
35+
auto d_func1=clad::gradient(func1);
36+
double dx1=0;
37+
d_func1.execute(3.0,&dx1);
38+
printf("Diff result: %.2f\n", dx1);
39+
//CHECK-EXEC: Diff result: 27.00
40+
41+
auto d_func1_forw = clad::differentiate(func1);
42+
auto res1_forw = d_func1_forw.execute(3.0);
43+
printf("Diff result: %.2f\n", res1_forw);
44+
//CHECK-EXEC: Diff result: 27.00
45+
46+
auto d_temp_func = clad::differentiate(temp_func);
47+
auto res_void = d_temp_func.execute(3.0);
48+
printf("Diff result: %.2f\n", res_void);
49+
//CHECK-EXEC: Diff result: 27.00
50+
51+
return 0;
52+
}

0 commit comments

Comments
 (0)