Skip to content

Commit eb04942

Browse files
Vladislavkaniandr
authored andcommitted
[TSAR, Transform, LoopSwap] Add simple dependency check. Add nostrict clause to skip this check
1 parent 21ba3a0 commit eb04942

File tree

2 files changed

+64
-16
lines changed

2 files changed

+64
-16
lines changed

include/tsar/Support/DiagnosticKinds.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,4 @@ def warn_loopswap_not_canonical: Warning<"expected canonical loop">;
194194
def warn_loopswap_not_perfect: Warning<"expected perfect loop">;
195195
def warn_loopswap_id_not_found: Warning<"induction not found">;
196196
def warn_loopswap_not_forstmt: Warning<"expected for loop">;
197+
def err_loopswap_dependency: Error<"loop contains dependence. use 'nostrict' clause to skip this check">;

lib/Transform/Clang/LoopSwap.cpp

Lines changed: 63 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ using namespace std;
3333

3434
#undef DEBUG_TYPE
3535
#define DEBUG_TYPE "clang-swap"
36+
#define DEBUG_PREFIX "[LoopSwap]: "
3637

3738
char ClangLoopSwapPass::ID = 0;
3839

@@ -96,6 +97,9 @@ void ClangLoopSwapPass::getAnalysisUsage(AnalysisUsage &AU) const {
9697
ModulePass *llvm::createClangLoopSwapPass() { return new ClangLoopSwapPass(); }
9798

9899
namespace {
100+
inline void dbgPrintln(const char * Msg) {
101+
LLVM_DEBUG(dbgs() << DEBUG_PREFIX << Msg << "\n");
102+
}
99103
class SwapClauseVisitor : public RecursiveASTVisitor<SwapClauseVisitor> {
100104
public:
101105
bool VisitStringLiteral(clang::StringLiteral *SL) {
@@ -119,7 +123,8 @@ class ClangLoopSwapVisitor : public RecursiveASTVisitor<ClangLoopSwapVisitor> {
119123
mContext(TfmCtx->getContext()), mSrcMgr(mRewriter.getSourceMgr()),
120124
mLangOpts(mRewriter.getLangOpts()), mPass(Pass), mModule(M),
121125
mStatus(SEARCH_PRAGMA), mGO(NULL), mDIAT(NULL), mDIDepInfo(NULL),
122-
mMemMatcher(NULL), mPerfectLoopInfo(NULL), mCurrentLoops(NULL) {}
126+
mMemMatcher(NULL), mPerfectLoopInfo(NULL), mCurrentLoops(NULL),
127+
mIsStrict(false) {}
123128
const CanonicalLoopInfo *getLoopInfo(ForStmt *FS) {
124129
if (!FS)
125130
return NULL;
@@ -137,14 +142,16 @@ class ClangLoopSwapVisitor : public RecursiveASTVisitor<ClangLoopSwapVisitor> {
137142
auto LI = getLoopInfo(FS);
138143
bool IsCanonical;
139144
bool IsPerfect;
145+
clang::ValueDecl *VD = NULL;
140146
if (LI) {
141147
IsCanonical = LI->isCanonical();
142148
IsPerfect = mPerfectLoopInfo->count(LI->getLoop());
143149
// to get Value name it is necessary to match IR Value* to AST
144150
// ValueDecl*, it is possible that on Linux 'Value->getName()' doesn't
145151
// works
146-
mInductions.push_back(std::pair<clang::ValueDecl *, clang::ForStmt *>(
147-
mMemMatcher->find<IR>(LI->getInduction())->get<AST>(), FS));
152+
VD = mMemMatcher->find<IR>(LI->getInduction())->get<AST>();
153+
mInductions.push_back(
154+
std::pair<clang::ValueDecl *, clang::ForStmt *>(VD, FS));
148155
} else {
149156
// if it's not canonical loop, gathering induction is difficult, there
150157
// may be no induction at all; so just set a NULL stub
@@ -161,6 +168,30 @@ class ClangLoopSwapVisitor : public RecursiveASTVisitor<ClangLoopSwapVisitor> {
161168
mLoopsKinds.push_back(NOT_CANONICAL);
162169
else
163170
mLoopsKinds.push_back(NOT_CANONICAL_AND_PERFECT);
171+
// check only if canonical and perfect, otherwise it's not necessary or
172+
// there is no LoopInfo
173+
if (mIsStrict && IsCanonical && IsPerfect) {
174+
bool Dependency = false;
175+
auto *Loop = LI->getLoop()->getLoop();
176+
auto *LoopID = Loop->getLoopID();
177+
auto DepItr = mDIDepInfo->find(LoopID);
178+
auto &DIDepSet = DepItr->get<DIDependenceSet>();
179+
DenseSet<const DIAliasNode *> Coverage;
180+
accessCoverage<bcl::SimpleInserter>(DIDepSet, *mDIAT, Coverage,
181+
mGO->IgnoreRedundantMemory);
182+
if (!Coverage.empty()) {
183+
for (auto &DIAT : DIDepSet) {
184+
if (!Coverage.count(DIAT.getNode()))
185+
continue;
186+
if (DIAT.is_any<trait::Output, trait::Anti, trait::Flow>()) {
187+
Dependency = true;
188+
}
189+
}
190+
}
191+
if (Dependency) {
192+
mLoopsKinds[mLoopsKinds.size() - 1] = HAS_DEPENDENCY;
193+
}
194+
}
164195

165196
return RecursiveASTVisitor::TraverseForStmt(FS);
166197
} else {
@@ -184,9 +215,25 @@ class ClangLoopSwapVisitor : public RecursiveASTVisitor<ClangLoopSwapVisitor> {
184215
case Status::SEARCH_PRAGMA: {
185216
Pragma P(*S);
186217
llvm::SmallVector<clang::Stmt *, 1> Clauses;
187-
// if found expand clause
188-
bool Found = false;
189218
if (findClause(P, ClauseId::LoopSwap, Clauses)) {
219+
dbgPrintln("Pragma -> start");
220+
// collect info from clauses
221+
SwapClauseVisitor SCV;
222+
for (auto C : Clauses)
223+
SCV.TraverseStmt(C);
224+
auto &Literals = SCV.getLiterals();
225+
for (auto L : Literals) {
226+
mSwaps.push_back(L);
227+
}
228+
// also check for nostrict clause
229+
mIsStrict = true;
230+
auto Csize = Clauses.size();
231+
findClause(P, ClauseId::NoStrict, Clauses);
232+
if (Csize != Clauses.size()) {
233+
mIsStrict = false;
234+
dbgPrintln("Found nostrict clause");
235+
}
236+
// remove clauses
190237
llvm::SmallVector<clang::CharSourceRange, 8> ToRemove;
191238
auto IsPossible =
192239
pragmaRangeToRemove(P, Clauses, mSrcMgr, mLangOpts, ToRemove);
@@ -206,13 +253,6 @@ class ClangLoopSwapVisitor : public RecursiveASTVisitor<ClangLoopSwapVisitor> {
206253
RemoveEmptyLine.RemoveLineIfEmpty = false;
207254
for (auto SR : ToRemove)
208255
mRewriter.RemoveText(SR, RemoveEmptyLine);
209-
SwapClauseVisitor SCV;
210-
for (auto C : Clauses)
211-
SCV.TraverseStmt(C);
212-
auto &Literals = SCV.getLiterals();
213-
for (auto L : Literals) {
214-
mSwaps.push_back(L);
215-
}
216256
Clauses.clear();
217257
mStatus = Status::TRAVERSE_STMT;
218258
return true;
@@ -309,6 +349,10 @@ class ClangLoopSwapVisitor : public RecursiveASTVisitor<ClangLoopSwapVisitor> {
309349
IsPossible = false;
310350
toDiag(mSrcMgr.getDiagnostics(), mInductions[i].second->getBeginLoc(),
311351
diag::warn_loopswap_not_perfect);
352+
} else if (mLoopsKinds[i] == HAS_DEPENDENCY) {
353+
IsPossible = false;
354+
toDiag(mSrcMgr.getDiagnostics(), mInductions[i].second->getBeginLoc(),
355+
diag::err_loopswap_dependency);
312356
}
313357
}
314358
if (!IsPossible) {
@@ -343,6 +387,7 @@ class ClangLoopSwapVisitor : public RecursiveASTVisitor<ClangLoopSwapVisitor> {
343387
}
344388
}
345389

390+
dbgPrintln("Pragma -> done");
346391
resetVisitor();
347392
return res;
348393
}
@@ -361,6 +406,7 @@ class ClangLoopSwapVisitor : public RecursiveASTVisitor<ClangLoopSwapVisitor> {
361406
mSwaps.clear();
362407
mInductions.clear();
363408
mLoopsKinds.clear();
409+
mIsStrict = false;
364410
}
365411

366412
private:
@@ -398,12 +444,13 @@ class ClangLoopSwapVisitor : public RecursiveASTVisitor<ClangLoopSwapVisitor> {
398444
const tsar::GlobalOptions *mGO;
399445
tsar::MemoryMatchInfo::MemoryMatcher *mMemMatcher;
400446
tsar::PerfectLoopInfo *mPerfectLoopInfo;
401-
447+
bool mIsStrict;
402448
enum LoopKind {
403449
CANONICAL_AND_PERFECT,
404450
NOT_PERFECT,
405451
NOT_CANONICAL,
406-
NOT_CANONICAL_AND_PERFECT
452+
NOT_CANONICAL_AND_PERFECT,
453+
HAS_DEPENDENCY
407454
};
408455
llvm::SmallVector<LoopKind, 2> mLoopsKinds;
409456
llvm::SmallVector<std::pair<clang::ValueDecl *, clang::ForStmt *>, 2>
@@ -415,7 +462,7 @@ class ClangLoopSwapVisitor : public RecursiveASTVisitor<ClangLoopSwapVisitor> {
415462
} // namespace
416463

417464
bool ClangLoopSwapPass::runOnModule(llvm::Module &M) {
418-
errs() << "Start loop swap pass\n";
465+
dbgPrintln( "Start Loop Swap pass");
419466
auto TfmCtx = getAnalysis<TransformationEnginePass>().getContext(M);
420467
if (!TfmCtx || !TfmCtx->hasInstance()) {
421468
M.getContext().emitError("can not transform sources"
@@ -446,6 +493,6 @@ bool ClangLoopSwapPass::runOnModule(llvm::Module &M) {
446493
auto &GIP = getAnalysis<ClangGlobalInfoPass>();
447494
ClangLoopSwapVisitor vis(TfmCtx, GIP.getRawInfo(), *this, M);
448495
vis.TraverseDecl(TfmCtx->getContext().getTranslationUnitDecl());
449-
errs() << "Finish loop swap pass\n";
496+
dbgPrintln("Finish Loop Swap pass");
450497
return false;
451498
}

0 commit comments

Comments
 (0)