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

Adding support for range-based for loops in the reverse mode #980

Merged
merged 2 commits into from
Aug 1, 2024

Conversation

ovdiiuv
Copy link
Collaborator

@ovdiiuv ovdiiuv commented Jul 11, 2024

Adding basic support for the range-based for loops, does not yet support break and continue statements inside.

Fixes: #723

Copy link
Contributor

@github-actions github-actions bot left a 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 =
Copy link
Contributor

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]

Suggested change
DeclRefExpr* RangeExpr =
auto* RangeExpr =


DeclRefExpr* RangeExpr =
cast<DeclRefExpr>(cast<BinaryOperator>(VisitRange.getStmt())->getLHS());
DeclRefExpr* BeginExpr =
Copy link
Contributor

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]

Suggested change
DeclRefExpr* BeginExpr =
auto* BeginExpr =

BuildOp(BO_Assign, BeginExpr, BuildOp(UO_Deref, RangeExpr));
addToCurrentBlock(AssignRange);
addToCurrentBlock(AssignBegin);
auto* EndDecl = cast<VarDecl>(FRS->getEndStmt()->getSingleDecl());
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 *EndDecl' can be declared as 'const auto *EndDecl' [readability-qualified-auto]

Suggested change
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()),
Copy link
Contributor

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)));
Copy link
Contributor

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)));
                      ^

Copy link

codecov bot commented Jul 11, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 94.10%. Comparing base (e9c47b7) to head (e3f5a07).

Additional details and impacted files

Impacted file tree graph

@@            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     
Files Coverage Δ
include/clad/Differentiator/ReverseModeVisitor.h 97.97% <ø> (ø)
lib/Differentiator/ReverseModeVisitor.cpp 97.50% <100.00%> (+0.09%) ⬆️

... and 2 files with indirect coverage changes

Files Coverage Δ
include/clad/Differentiator/ReverseModeVisitor.h 97.97% <ø> (ø)
lib/Differentiator/ReverseModeVisitor.cpp 97.50% <100.00%> (+0.09%) ⬆️

... and 2 files with indirect coverage changes

// 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;
Copy link
Collaborator

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...

Copy link
Collaborator Author

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.

Copy link
Collaborator

@parth-07 parth-07 Jul 20, 2024

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?

Copy link
Collaborator Author

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.

Copy link
Owner

Choose a reason for hiding this comment

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

@parth-07, @ovdiiuv has opened an issue to track that comment so that we can move forward: #1004

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()),
Copy link
Owner

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();
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
const auto* Item = FRS->getLoopVariable();
VarDecl* Item = FRS->getLoopVariable();

Copy link
Collaborator Author

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

Copy link
Owner

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.

Copy link
Owner

@vgvassilev vgvassilev left a 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 =
Copy link
Owner

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())
Copy link
Owner

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();
Copy link
Owner

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());
Copy link
Owner

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.

Copy link
Owner

Choose a reason for hiding this comment

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

ping.

lib/Differentiator/ReverseModeVisitor.cpp Show resolved Hide resolved
auto* AssignEnd = BuildDeclStmt(BuildGlobalVarDecl(
CloneType(EndDecl->getType()), EndDecl->getNameAsString(),
BuildOp(BO_Add, BuildOp(UO_Deref, RangeExpr),
cast<BinaryOperator>(EndDecl->getInit())->getRHS()),
Copy link
Owner

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(
Copy link
Owner

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()),
Copy link
Owner

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);
Copy link
Owner

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.

@ovdiiuv ovdiiuv force-pushed the revrb branch 2 times, most recently from 6ac19d4 to a30c75c Compare July 26, 2024 12:19
Copy link
Contributor

@github-actions github-actions bot left a 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

lib/Differentiator/ReverseModeVisitor.cpp Outdated Show resolved Hide resolved
Stmt* bodyClone = Clone(FRS->getBody());
CompoundStmt* body = utils::PrependAndCreateCompoundStmt(
m_Sema.getASTContext(), bodyClone,
BuildDeclStmt(const_cast<VarDecl*>(LoopVD)));
Copy link
Contributor

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)));
                      ^

Copy link
Owner

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,
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
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);
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
BodyDiff.getStmt(), FRS->getForLoc(), noLoc, noLoc);
BodyDiff.getStmt(), FRS->getForLoc(), FRS->getBeginLoc(), FRS->getEndLoc());

We also need to add comments for the nullptrs on the line above.

Reverse = endBlock(direction::reverse);
Reverse = new (m_Context)
ForStmt(m_Context, nullptr, CounterCondition, nullptr, CounterDecrement,
Reverse, FRS->getForLoc(), noLoc, noLoc);
Copy link
Owner

Choose a reason for hiding this comment

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

Likewise.

test/Gradient/Loops.C Show resolved Hide resolved
@ovdiiuv ovdiiuv force-pushed the revrb branch 2 times, most recently from afd91ee to 04673ac Compare July 26, 2024 13:29
lib/Differentiator/ReverseModeVisitor.cpp Outdated Show resolved Hide resolved
lib/Differentiator/ReverseModeVisitor.cpp Outdated Show resolved Hide resolved
auto* BeginExpr =
cast<DeclRefExpr>(cast<BinaryOperator>(VisitBegin.getStmt())->getLHS());

auto* RangeInit = Clone(FRS->getRangeInit());
Copy link
Owner

Choose a reason for hiding this comment

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

ping.

lib/Differentiator/ReverseModeVisitor.cpp Outdated Show resolved Hide resolved
lib/Differentiator/ReverseModeVisitor.cpp Outdated Show resolved Hide resolved
Stmt* bodyClone = Clone(FRS->getBody());
CompoundStmt* body = utils::PrependAndCreateCompoundStmt(
m_Sema.getASTContext(), bodyClone,
BuildDeclStmt(const_cast<VarDecl*>(LoopVD)));
Copy link
Owner

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.

lib/Differentiator/ReverseModeVisitor.cpp Outdated Show resolved Hide resolved
@ovdiiuv ovdiiuv force-pushed the revrb branch 2 times, most recently from f05d9c1 to ef4f9a8 Compare July 26, 2024 14:58
Copy link
Contributor

@github-actions github-actions bot left a 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));
Copy link
Contributor

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));
                                     ^

@ovdiiuv ovdiiuv force-pushed the revrb branch 2 times, most recently from 10e92c7 to f3695a7 Compare July 31, 2024 16:34
@ovdiiuv ovdiiuv force-pushed the revrb branch 3 times, most recently from d652fc3 to 9dcec29 Compare July 31, 2024 16:50
Copy link
Contributor

clang-tidy review says "All clean, LGTM! 👍"

Copy link
Contributor

clang-tidy review says "All clean, LGTM! 👍"

Copy link
Contributor

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));
Copy link
Owner

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?

Copy link
Contributor

clang-tidy review says "All clean, LGTM! 👍"

@ovdiiuv ovdiiuv force-pushed the revrb branch 2 times, most recently from de4093e to 4889eac Compare July 31, 2024 19:20
Copy link
Contributor

clang-tidy review says "All clean, LGTM! 👍"

1 similar comment
Copy link
Contributor

clang-tidy review says "All clean, LGTM! 👍"

Copy link
Contributor

github-actions bot commented Aug 1, 2024

clang-tidy review says "All clean, LGTM! 👍"

Copy link
Owner

@vgvassilev vgvassilev left a comment

Choose a reason for hiding this comment

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

LGTM!

@vgvassilev vgvassilev merged commit 7d1e26c into vgvassilev:master Aug 1, 2024
89 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for range-based for loops.
3 participants