-
Notifications
You must be signed in to change notification settings - Fork 122
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
Adding support for range-based for loops in the reverse mode #980
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clang-tidy made some suggestions
cast<BinaryOperator>(VisitBegin.getStmt())->getLHS()) | ||
->getDecl()]; | ||
|
||
DeclRefExpr* RangeExpr = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: use auto when initializing with a template cast to avoid duplicating the type name [modernize-use-auto]
DeclRefExpr* RangeExpr = | |
auto* RangeExpr = |
|
||
DeclRefExpr* RangeExpr = | ||
cast<DeclRefExpr>(cast<BinaryOperator>(VisitRange.getStmt())->getLHS()); | ||
DeclRefExpr* BeginExpr = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: use auto when initializing with a template cast to avoid duplicating the type name [modernize-use-auto]
DeclRefExpr* BeginExpr = | |
auto* BeginExpr = |
BuildOp(BO_Assign, BeginExpr, BuildOp(UO_Deref, RangeExpr)); | ||
addToCurrentBlock(AssignRange); | ||
addToCurrentBlock(AssignBegin); | ||
auto* EndDecl = cast<VarDecl>(FRS->getEndStmt()->getSingleDecl()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: 'auto *EndDecl' can be declared as 'const auto *EndDecl' [readability-qualified-auto]
auto* EndDecl = cast<VarDecl>(FRS->getEndStmt()->getSingleDecl()); | |
const auto* EndDecl = cast<VarDecl>(FRS->getEndStmt()->getSingleDecl()); |
Expr* ForwardCond = BuildOp(BO_NE, BeginExpr, EndExpr); | ||
// Add item assignment statement to the body. | ||
auto* body = utils::PrependAndCreateCompoundStmt( | ||
m_Sema.getASTContext(), const_cast<Stmt*>(FRS->getBody()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: do not use const_cast [cppcoreguidelines-pro-type-const-cast]
m_Sema.getASTContext(), const_cast<Stmt*>(FRS->getBody()),
^
// Add item assignment statement to the body. | ||
auto* body = utils::PrependAndCreateCompoundStmt( | ||
m_Sema.getASTContext(), const_cast<Stmt*>(FRS->getBody()), | ||
BuildDeclStmt(const_cast<VarDecl*>(Item))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: do not use const_cast [cppcoreguidelines-pro-type-const-cast]
BuildDeclStmt(const_cast<VarDecl*>(Item)));
^
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #980 +/- ##
==========================================
+ Coverage 94.00% 94.10% +0.09%
==========================================
Files 55 55
Lines 8139 8225 +86
==========================================
+ Hits 7651 7740 +89
+ Misses 488 485 -3
... and 2 files with indirect coverage changes
|
99dc69b
to
1f612ed
Compare
test/Gradient/Loops.C
Outdated
// CHECK-NEXT: double r = 0; | ||
// CHECK-NEXT: double a[3] = {y, x * y, x * x + y}; | ||
// CHECK-NEXT: _t0 = {{0U|0UL}}; | ||
// CHECK-NEXT: _d___range1 = &_d_a; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use std::begin
and std::end
on C-style arrays? If so, then we should probably use these functions instead of explicitly taking the address of the array and using the array size. It will make the functionality reusable and consistent for more complicated types such as std::vector
, std::list
, and so on...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could, but the way it is done is more natural, since clad creates all those statements automatically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does clad creates statements such as &_d_a
automatically? You are synthesizing the statements by making Clang API calls whether you are creating &_d_a
or std::begin(_d_a)
, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that makes sense. Please correct me if I'm wrong, but that would require the support of the iterators in the reverse mode and clad doesn't support that yet. That's an issue I'm currently working on, but clad doesn't yet support custom pullbacks. If so, I suggest we return on that issue once custom pullbacks are supported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Expr* ForwardCond = BuildOp(BO_NE, BeginExpr, EndExpr); | ||
// Add item assignment statement to the body. | ||
auto* body = utils::PrependAndCreateCompoundStmt( | ||
m_Sema.getASTContext(), const_cast<Stmt*>(FRS->getBody()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn’t we clone the body here?
|
||
llvm::SaveAndRestore<bool> SaveIsInsideLoop(isInsideLoop); | ||
isInsideLoop = true; | ||
const auto* Item = FRS->getLoopVariable(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const auto* Item = FRS->getLoopVariable(); | |
VarDecl* Item = FRS->getLoopVariable(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that would compile, will try later
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I bet it will, we should also rename Item
to LoopVD
or something like that. VD
is a common acronym for things like that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this. Seems like it is heading in the right direction.
|
||
beginBlock(direction::reverse); | ||
// Create all declarations needed. | ||
auto* d_BeginDeclRef = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should spell out the type here. I think it is VarDecl.
// Create all declarations needed. | ||
auto* d_BeginDeclRef = | ||
m_Variables[cast<DeclRefExpr>( | ||
cast<BinaryOperator>(VisitBegin.getStmt())->getLHS()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should move VisitBegin.getStmt())->getLHS()
into a temporary variable since it is used more than once.
|
||
llvm::SaveAndRestore<bool> SaveIsInsideLoop(isInsideLoop); | ||
isInsideLoop = true; | ||
const auto* Item = FRS->getLoopVariable(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I bet it will, we should also rename Item
to LoopVD
or something like that. VD
is a common acronym for things like that.
auto* BeginExpr = | ||
cast<DeclRefExpr>(cast<BinaryOperator>(VisitBegin.getStmt())->getLHS()); | ||
|
||
auto* RangeInit = Clone(FRS->getRangeInit()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should describe in a comment, with code example, what are we trying to produce here with the next several blocks of code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ping.
auto* AssignEnd = BuildDeclStmt(BuildGlobalVarDecl( | ||
CloneType(EndDecl->getType()), EndDecl->getNameAsString(), | ||
BuildOp(BO_Add, BuildOp(UO_Deref, RangeExpr), | ||
cast<BinaryOperator>(EndDecl->getInit())->getRHS()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These things are better as temporary variables.
addToCurrentBlock(AssignRange); | ||
addToCurrentBlock(AssignBegin); | ||
const auto* EndDecl = cast<VarDecl>(FRS->getEndStmt()->getSingleDecl()); | ||
auto* AssignEnd = BuildDeclStmt(BuildGlobalVarDecl( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please spell out the type here.
Expr* ForwardCond = BuildOp(BO_NE, BeginExpr, EndExpr); | ||
// Add item assignment statement to the body. | ||
auto* body = utils::PrependAndCreateCompoundStmt( | ||
m_Sema.getASTContext(), Clone(FRS->getBody()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The clone operations are better of outside the calls. We need to spell out the type here, too.
Stmt* Forward = | ||
new (m_Context) ForStmt(m_Context, nullptr, ForwardCond, nullptr, | ||
BuildOp(BO_Comma, IncBegin, d_IncBegin), | ||
BodyDiff.getStmt(), noLoc, noLoc, noLoc); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a new policy: we try to pass the source locations of the original function instead of noLoc
.
6ac19d4
to
a30c75c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clang-tidy made some suggestions
Stmt* bodyClone = Clone(FRS->getBody()); | ||
CompoundStmt* body = utils::PrependAndCreateCompoundStmt( | ||
m_Sema.getASTContext(), bodyClone, | ||
BuildDeclStmt(const_cast<VarDecl*>(LoopVD))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: do not use const_cast [cppcoreguidelines-pro-type-const-cast]
BuildDeclStmt(const_cast<VarDecl*>(LoopVD)));
^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should clone that variable declaration, too.
m_Sema.getASTContext(), bodyClone, | ||
BuildDeclStmt(const_cast<VarDecl*>(LoopVD))); | ||
StmtDiff BodyDiff = | ||
DifferentiateLoopBody(body, loopCounter, nullptr, d_DecBegin, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DifferentiateLoopBody(body, loopCounter, nullptr, d_DecBegin, | |
DifferentiateLoopBody(body, loopCounter, /*condVarDifff=*/nullptr, d_DecBegin, |
Expr* Inc = BuildOp(BO_Comma, IncBegin, d_IncBegin); | ||
Stmt* Forward = new (m_Context) | ||
ForStmt(m_Context, nullptr, ForwardCond, nullptr, Inc, | ||
BodyDiff.getStmt(), FRS->getForLoc(), noLoc, noLoc); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BodyDiff.getStmt(), FRS->getForLoc(), noLoc, noLoc); | |
BodyDiff.getStmt(), FRS->getForLoc(), FRS->getBeginLoc(), FRS->getEndLoc()); |
We also need to add comments for the nullptr
s on the line above.
Reverse = endBlock(direction::reverse); | ||
Reverse = new (m_Context) | ||
ForStmt(m_Context, nullptr, CounterCondition, nullptr, CounterDecrement, | ||
Reverse, FRS->getForLoc(), noLoc, noLoc); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise.
afd91ee
to
04673ac
Compare
auto* BeginExpr = | ||
cast<DeclRefExpr>(cast<BinaryOperator>(VisitBegin.getStmt())->getLHS()); | ||
|
||
auto* RangeInit = Clone(FRS->getRangeInit()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ping.
Stmt* bodyClone = Clone(FRS->getBody()); | ||
CompoundStmt* body = utils::PrependAndCreateCompoundStmt( | ||
m_Sema.getASTContext(), bodyClone, | ||
BuildDeclStmt(const_cast<VarDecl*>(LoopVD))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should clone that variable declaration, too.
f05d9c1
to
ef4f9a8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clang-tidy made some suggestions
Expr* ForwardCond = BuildOp(BO_NE, BeginDeclRef, EndExpr); | ||
// Add item assignment statement to the body. | ||
Stmt* bodyClone = Clone(FRS->getBody()); | ||
Stmt* LoopVDStmt = BuildDeclStmt(const_cast<VarDecl*>(LoopVD)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: do not use const_cast [cppcoreguidelines-pro-type-const-cast]
Stmt* LoopVDStmt = BuildDeclStmt(const_cast<VarDecl*>(LoopVD));
^
10e92c7
to
f3695a7
Compare
d652fc3
to
9dcec29
Compare
clang-tidy review says "All clean, LGTM! 👍" |
clang-tidy review says "All clean, LGTM! 👍" |
clang-tidy review says "All clean, LGTM! 👍" |
if (!LoopVD->getType()->isReferenceType()) { | ||
Expr* d_LoopVD = BuildDeclRef(LoopVDDiff.getDecl_dx()); | ||
AdjLoopVDAddAssign = | ||
BuildOp(BO_Assign, d_LoopVD, BuildOp(UO_Deref, d_BeginDeclRef)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a test case to make codecov happy?
clang-tidy review says "All clean, LGTM! 👍" |
de4093e
to
4889eac
Compare
clang-tidy review says "All clean, LGTM! 👍" |
1 similar comment
clang-tidy review says "All clean, LGTM! 👍" |
clang-tidy review says "All clean, LGTM! 👍" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Adding basic support for the range-based for loops, does not yet support break and continue statements inside.
Fixes: #723