Skip to content

Commit 3de551c

Browse files
author
ovdiiuv
committed
Rework isInjectiveE not to use ASTMatchers
1 parent 0f3a496 commit 3de551c

1 file changed

Lines changed: 138 additions & 41 deletions

File tree

lib/Differentiator/ReverseModeVisitor.cpp

Lines changed: 138 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -136,51 +136,148 @@ Expr* ReverseModeVisitor::getStdInitListSizeExpr(const Expr* E) {
136136
return CladTapeResult{*this, PushExpr, PopExpr, TapeRef};
137137
}
138138

139-
static bool isInjectiveE(const clang::Expr* E, clang::ASTContext& ctx) {
140-
StatementMatcher matcher =
141-
binaryOperator(
142-
hasOperatorName("+"),
143-
hasLHS(expr(
144-
has(callExpr(hasDescendant(memberExpr(
145-
hasObjectExpression(opaqueValueExpr(hasSourceExpression(
146-
declRefExpr(to(varDecl(hasName("threadIdx"))))))))))),
147-
unless(binaryOperator()))),
148-
hasRHS(binaryOperator(
149-
hasOperatorName("*"),
150-
has(expr(
151-
has(callExpr(hasDescendant(memberExpr(hasObjectExpression(
152-
opaqueValueExpr(hasSourceExpression(declRefExpr(
153-
to(varDecl(hasName("blockIdx"))))))))))),
154-
unless(binaryOperator()))),
155-
has(expr(
156-
has(callExpr(hasDescendant(memberExpr(hasObjectExpression(
157-
opaqueValueExpr(hasSourceExpression(declRefExpr(
158-
to(varDecl(hasName("blockDim"))))))))))),
159-
unless(binaryOperator()))))))
160-
.bind("targetVar");
161-
162-
class InjectivePatternMatchCallback : public MatchFinder::MatchCallback {
163-
const clang::Expr* targetExpr;
139+
static bool isInjectiveE(const clang::Expr* E) {
140+
class InjectiveCheckerExpr
141+
: public clang::RecursiveASTVisitor<InjectiveCheckerExpr> {
142+
struct IdxNode {
143+
struct ExprOrBinOp {
144+
const clang::DeclRefExpr* m_E = nullptr;
145+
clang::BinaryOperatorKind m_Opcode;
146+
enum class Kind { Expr, Opcode } m_Kind;
147+
148+
ExprOrBinOp(const clang::DeclRefExpr* E)
149+
: m_E(E), m_Kind(Kind::Expr) {}
150+
ExprOrBinOp(clang::BinaryOperatorKind op)
151+
: m_Opcode(op), m_Kind(Kind::Opcode) {}
152+
153+
bool isExpr() const { return m_Kind == Kind::Expr; }
154+
bool isOpcode() const { return m_Kind == Kind::Opcode; }
155+
};
156+
157+
ExprOrBinOp Node;
158+
std::unique_ptr<IdxNode> left;
159+
std::unique_ptr<IdxNode> right;
160+
161+
IdxNode(ExprOrBinOp N) : Node(N) {}
162+
};
163+
std::unique_ptr<IdxNode> m_Root;
164+
IdxNode* m_ParentNode;
165+
166+
enum class side { left, right } m_Side;
164167

165168
public:
166-
InjectivePatternMatchCallback(const clang::Expr* E) : targetExpr(E) {}
167-
bool matched = false;
168-
virtual void run(const MatchFinder::MatchResult& Result) override {
169-
if (const auto* expr =
170-
Result.Nodes.getNodeAs<clang::BinaryOperator>("targetVar")) {
171-
if (targetExpr == expr)
172-
matched = true;
169+
InjectiveCheckerExpr() = default;
170+
171+
bool comparePatternToTree(const IdxNode* current,
172+
const std::vector<std::string>& patternIdx,
173+
size_t i = 1, bool* shouldInvert = nullptr) {
174+
if (!shouldInvert)
175+
shouldInvert = new bool(false);
176+
177+
if (!current && (i >= patternIdx.size() || patternIdx[i].empty()))
178+
return true;
179+
180+
if (!current || i >= patternIdx.size() || patternIdx[i].empty())
181+
return false;
182+
183+
std::string expected;
184+
if (*shouldInvert)
185+
if (i % 2 == 0)
186+
expected = patternIdx[i + 1];
187+
else
188+
expected = patternIdx[i - 1];
189+
else
190+
expected = patternIdx[i];
191+
192+
if (current->Node.isOpcode()) {
193+
std::string actualOp =
194+
clang::BinaryOperator::getOpcodeStr(current->Node.m_Opcode).str();
195+
if (actualOp != expected) {
196+
if (i % 2 == 0 && actualOp == patternIdx[i + 1])
197+
*shouldInvert = true;
198+
else if (i % 2 == 1 && actualOp == patternIdx[i - 1])
199+
*shouldInvert = true;
200+
else
201+
return false;
202+
}
203+
} else if (current->Node.isExpr()) {
204+
if (!current->Node.m_E)
205+
return false;
206+
std::string actualName =
207+
current->Node.m_E->getNameInfo().getAsString();
208+
if (actualName != expected) {
209+
if (i % 2 == 0 && actualName == patternIdx[i + 1])
210+
*shouldInvert = true;
211+
else if (i % 2 == 1 && actualName == patternIdx[i - 1])
212+
*shouldInvert = true;
213+
else
214+
return false;
215+
}
173216
}
217+
218+
bool* invert = new bool(false);
219+
return comparePatternToTree(current->left.get(), patternIdx, 2 * i,
220+
invert) &&
221+
comparePatternToTree(current->right.get(), patternIdx, 2 * i + 1,
222+
invert);
174223
}
175-
bool hasMatched() const { return matched; }
176-
};
177224

178-
MatchFinder Finder;
179-
InjectivePatternMatchCallback Callback(E);
180-
Finder.addMatcher(matcher, &Callback);
181-
Finder.matchAST(ctx);
225+
bool isInjectiveIdx(const clang::Expr* E) {
226+
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
227+
TraverseStmt(const_cast<clang::Expr*>(E));
228+
std::vector<std::string> pattern = {"", "+", "threadIdx", "*",
229+
"", "", "blockIdx", "blockDim"};
230+
return comparePatternToTree(m_Root.get(), pattern);
231+
}
182232

183-
return Callback.hasMatched();
233+
bool TraverseBinaryOperator(clang::BinaryOperator* BinOp) {
234+
const auto opCode = BinOp->getOpcode();
235+
if (opCode == BO_Add || opCode == BO_Mul) {
236+
std::unique_ptr<IdxNode> curr = std::make_unique<IdxNode>(opCode);
237+
IdxNode* currPtr;
238+
239+
if (!m_Root) {
240+
m_Root = std::move(curr);
241+
currPtr = m_Root.get();
242+
} else {
243+
currPtr = curr.get();
244+
245+
if (m_Side == side::left)
246+
m_ParentNode->left = std::move(curr);
247+
248+
if (m_Side == side::right)
249+
m_ParentNode->right = std::move(curr);
250+
}
251+
252+
Expr* L = BinOp->getLHS();
253+
Expr* R = BinOp->getRHS();
254+
255+
m_ParentNode = currPtr;
256+
m_Side = side::left;
257+
TraverseStmt(L);
258+
m_ParentNode = currPtr;
259+
260+
m_Side = side::right;
261+
TraverseStmt(R);
262+
}
263+
return true;
264+
}
265+
266+
bool TraverseDeclRefExpr(clang::DeclRefExpr* DRE) {
267+
std::unique_ptr<IdxNode> curr = std::make_unique<IdxNode>(DRE);
268+
269+
if (m_ParentNode) {
270+
if (m_Side == side::left)
271+
m_ParentNode->left = std::move(curr);
272+
273+
if (m_Side == side::right)
274+
m_ParentNode->right = std::move(curr);
275+
}
276+
return true;
277+
}
278+
279+
} checker;
280+
return checker.isInjectiveIdx(E);
184281
}
185282

186283
static bool isInjective(const clang::Expr* E, clang::ASTContext& ctx) {
@@ -218,15 +315,15 @@ Expr* ReverseModeVisitor::getStdInitListSizeExpr(const Expr* E) {
218315
if (isConstL && !isConstR)
219316
return TraverseStmt(R);
220317

221-
return isInjectiveE(BinOp, m_Context);
318+
return isInjectiveE(BinOp);
222319
}
223320
return false;
224321
}
225322

226323
bool TraverseDeclRefExpr(clang::DeclRefExpr* DRE) {
227324
if (auto* VD = dyn_cast<VarDecl>(DRE->getDecl())) {
228325
if (auto* init = VD->getInit())
229-
return isInjectiveE(init->IgnoreImpCasts(), m_Context);
326+
return isInjectiveE(init->IgnoreImpCasts());
230327
}
231328
return false;
232329
}

0 commit comments

Comments
 (0)