Skip to content

Commit f6e3de2

Browse files
committed
[TSAR, Transform] Change data structures and handle more cases.
1 parent db422be commit f6e3de2

File tree

2 files changed

+95
-113
lines changed

2 files changed

+95
-113
lines changed

include/tsar/Support/DiagnosticKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,6 @@ def warn_loop_swapping_diff_reduction: Warning<"unable to swap loops due to the
184184
def warn_loop_swapping_true_anti_dependence: Warning<"unable to swap loops due to the true or anti dependence">;
185185
def warn_loop_swapping_missing_loop: Warning<"not enough loops for swapping">;
186186
def warn_loop_swapping_redundant_loop: Warning<"too many loops for swapping, ignore redundant">;
187+
def error_loop_swapping_lost_loop: Error<"cannot match ForStmt with its IR">;
188+
def error_loop_swapping_expect_compound: Error<"expected compound statement after pragma">;
189+
def warn_loop_swapping_no_loop_id: Warning<"cannot find loop ID to perform swapping">;

lib/Transform/Clang/LoopSwapping.cpp

100644100755
Lines changed: 92 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
//===- LoopSwapping.cpp - Source-level Renaming of Local Objects - *- C++ -*===//
1+
//===- LoopSwapping.cpp - Loop Swapping (Clang) -----------------*- C++ -*-===//
22
//
33
// Traits Static Analyzer (SAPFOR)
44
//
5-
// Copyright 2018 DVM System Group
5+
// Copyright 2020 DVM System Group
66
//
77
// Licensed under the Apache License, Version 2.0 (the "License");
88
// you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
2222
//
2323
//===----------------------------------------------------------------------===//
2424

25+
#include "tsar/ADT/SpanningTreeRelation.h"
2526
#include "tsar/Analysis/AnalysisServer.h"
2627
#include "tsar/Analysis/Clang/LoopMatcher.h"
2728
#include "tsar/Analysis/Clang/NoMacroAssert.h"
@@ -58,7 +59,8 @@ using ClangLoopSwappingProvider =
5859
FunctionPassAAProvider<DIEstimateMemoryPass, DIDependencyAnalysisPass>;
5960
using DIAliasTraitVector = std::vector<const DIAliasTrait *>;
6061
using LoopRangeInfo = std::pair<Loop *, SourceRange>;
61-
using LoopRangeVector = SmallVector<LoopRangeInfo, 2>;
62+
using LoopRangeList = SmallVector<LoopRangeInfo, 2>;
63+
using PragmaInfoList = SmallVector<std::pair<Stmt *, LoopRangeList>, 2>;
6264

6365
class LoopVisitor : public RecursiveASTVisitor<LoopVisitor> {
6466
private:
@@ -100,29 +102,29 @@ class LoopVisitor : public RecursiveASTVisitor<LoopVisitor> {
100102
/// TODO ([email protected]): it seems that RemoveLineIfEmpty is
101103
/// set to true then removing (in RewriterBuffer) works incorrect.
102104
RemoveEmptyLine.RemoveLineIfEmpty = false;
103-
for (auto SR : ToRemove)
104-
mRewriter.RemoveText(SR, RemoveEmptyLine);
105+
/*for (auto SR : ToRemove)
106+
mRewriter.RemoveText(SR, RemoveEmptyLine);*/
105107
mCurrentLevel++;
106-
if (mCurrentLevel + 1 > int(mPragmaLevels.size())) {
107-
mPragmaLevels.resize(mCurrentLevel + 1);
108-
}
109-
mPragmaLevels[mCurrentLevel].push_back(S);
108+
mPragmaLoopsInfo.resize(mPragmaLoopsInfo.size() + 1);
109+
mPragmaLoopsInfo.back().first = S;
110110
mState = TraverseState::PRAGMA;
111111
}
112112
return true;
113113
}
114-
auto Res = RecursiveASTVisitor::TraverseStmt(S);
115-
return Res;
114+
if (mState == TraverseState::PRAGMA && !dyn_cast<CompoundStmt>(S)) {
115+
S->dump();
116+
toDiag(mSrcMgr.getDiagnostics(), mClauses.front()->getBeginLoc(),
117+
diag::error_loop_swapping_expect_compound);
118+
return false;
119+
}
120+
return RecursiveASTVisitor::TraverseStmt(S);
116121
}
117122

118123
bool TraverseCompoundStmt(CompoundStmt *S) {
119124
if (mState == TraverseState::PRAGMA) {
120125
mState = TraverseState::OUTERFOR;
121-
mLoopStack.push(LoopRangeVector());
122126
auto Res = RecursiveASTVisitor::TraverseCompoundStmt(S);
123-
mState = TraverseState::PRAGMA;
124-
mPragmaLoopsInfo[mPragmaLevels[mCurrentLevel].back()] = mLoopStack.top();
125-
mLoopStack.pop();
127+
mState = TraverseState::NONE;
126128
mCurrentLevel--;
127129
return Res;
128130
}
@@ -133,9 +135,11 @@ class LoopVisitor : public RecursiveASTVisitor<LoopVisitor> {
133135
if (mState == TraverseState::OUTERFOR) {
134136
auto Match = mLoopInfo.find<AST>(S);
135137
if (Match != mLoopInfo.end()) {
136-
Loop *MatchLoop = Match->get<IR>();
137-
SourceRange Range(S->getBeginLoc(), S->getEndLoc());
138-
mLoopStack.top().push_back(std::make_pair(MatchLoop, Range));
138+
mPragmaLoopsInfo.back().second.push_back(
139+
std::make_pair(Match->get<IR>(), S->getSourceRange()));
140+
} else {
141+
toDiag(mSrcMgr.getDiagnostics(), S->getBeginLoc(),
142+
diag::error_loop_swapping_lost_loop);
139143
}
140144
mState = TraverseState::INNERFOR;
141145
auto Res = RecursiveASTVisitor::TraverseForStmt(S);
@@ -145,45 +149,34 @@ class LoopVisitor : public RecursiveASTVisitor<LoopVisitor> {
145149
return RecursiveASTVisitor::TraverseForStmt(S);
146150
}
147151

148-
const DenseMap<Stmt *, LoopRangeVector> &getPragmaLoopsInfo() const {
152+
const PragmaInfoList &getPragmaLoopsInfo() const {
149153
return mPragmaLoopsInfo;
150154
}
151155

152-
const std::vector<SmallVector<Stmt *, 1>> &getPragmaLevels() const {
153-
return mPragmaLevels;
154-
}
155-
156-
size_t getMaxPragmaDepth() const {
157-
return mPragmaLevels.size();
156+
bool hasPragma() const {
157+
return !mPragmaLoopsInfo.empty();
158158
}
159159

160+
#ifdef LLVM_DEBUG
160161
void printLocations() const {
161-
for (size_t Level = 0; Level < mPragmaLevels.size(); Level++) {
162-
LLVM_DEBUG(dbgs() << "Level " << Level << " :\n");
163-
const auto &CurrentLevel = mPragmaLevels[Level];
164-
for (size_t PragmaN = 0; PragmaN < CurrentLevel.size(); PragmaN++) {
165-
const auto &Pragma = CurrentLevel[PragmaN];
166-
auto PragmaItr = mPragmaLoopsInfo.find(Pragma);
167-
assert(PragmaItr != mPragmaLoopsInfo.end() &&
168-
"Map should contain all pragmas (as keys) from level vectors.");
169-
const auto &Loops = PragmaItr->second;
170-
LLVM_DEBUG(dbgs() << "\tPragma " << PragmaN << " (" << Pragma <<"):\n");
171-
for (const auto &Info : Loops) {
172-
const auto LoopPtr = Info.first;
173-
const auto &Range = Info.second;
174-
SourceLocation Begin = Range.getBegin();
175-
SourceLocation End = Range.getEnd();
176-
LLVM_DEBUG(dbgs() << "\t\t[Range]\n");
177-
LLVM_DEBUG(dbgs() << "\t\tBegin:" << Begin.printToString(mSrcMgr)
178-
<< "\n");
179-
LLVM_DEBUG(dbgs() << "\t\tEnd:" << End.printToString(mSrcMgr) <<"\n");
180-
LLVM_DEBUG(dbgs() << "\t\t\n\t\t[Loop]\n");
181-
const auto &LoopText = mRewriter.getRewrittenText(Range);
182-
LLVM_DEBUG(dbgs() << "\t\t" << LoopText << "\n\n");
183-
}
162+
int N = 0;
163+
for (auto It = mPragmaLoopsInfo.begin(); It != mPragmaLoopsInfo.end();
164+
++It, ++N) {
165+
dbgs() << "\tPragma " << N << " (" << It->first <<"):\n";
166+
for (const auto &Info : It->second) {
167+
const auto LoopPtr = Info.first;
168+
const auto &Range = Info.second;
169+
dbgs() << "\t\t[Range]\n";
170+
dbgs() << "\t\tBegin:" << Range.getBegin().printToString(mSrcMgr)
171+
<< "\n";
172+
dbgs() << "\t\tEnd:" << Range.getEnd().printToString(mSrcMgr) <<"\n";
173+
dbgs() << "\t\t\n\t\t[Loop]\n";
174+
const auto &LoopText = mRewriter.getRewrittenText(Range);
175+
dbgs() << "\t\t" << LoopText << "\n\n";
184176
}
185177
}
186178
}
179+
#endif
187180

188181
private:
189182
Rewriter &mRewriter;
@@ -195,9 +188,7 @@ class LoopVisitor : public RecursiveASTVisitor<LoopVisitor> {
195188
SmallVector<Stmt *, 1> mClauses;
196189

197190
int mCurrentLevel;
198-
std::stack<LoopRangeVector> mLoopStack;
199-
std::vector<SmallVector<Stmt *, 1>> mPragmaLevels;
200-
DenseMap<Stmt *, LoopRangeVector> mPragmaLoopsInfo;
191+
PragmaInfoList mPragmaLoopsInfo;
201192
};
202193

203194
class ClangLoopSwapping : public FunctionPass, private bcl::Uncopyable {
@@ -213,12 +204,11 @@ class ClangLoopSwapping : public FunctionPass, private bcl::Uncopyable {
213204
private:
214205
void swapLoops(const LoopVisitor &Visitor);
215206
DIAliasTraitVector getLoopTraits(MDNode *LoopID) const;
216-
bool isSwappingAvailable(std::pair<Loop *, Loop *> &Loops) const;
207+
bool isSwappingAvailable(const LoopRangeList &LRL, const Stmt *Pragma) const;
217208
bool hasSameReductionKind(const DIAliasTraitVector &TV0,
218209
const DIAliasTraitVector &TV1) const;
219210
bool hasTrueOrAntiDependence(const DIAliasTraitVector &TV0,
220211
const DIAliasTraitVector &TV1) const;
221-
void removePragmas(const std::vector<SmallVector<Stmt *, 1>> &PragmaLevels);
222212

223213
Function *mFunction = nullptr;
224214
TransformationContext *mTfmCtx = nullptr;
@@ -304,17 +294,15 @@ bool ClangLoopSwapping::hasSameReductionKind(
304294

305295
bool ClangLoopSwapping::hasTrueOrAntiDependence(
306296
const DIAliasTraitVector &TV0, const DIAliasTraitVector &TV1) const {
297+
SpanningTreeRelation<DIAliasTree *> STR(mDIAT);
307298
for (auto &TS0: TV0) {
308-
auto *Node0 = TS0->getNode();
309-
MemoryDescriptor Dptr0 = *TS0;
310299
for (auto &TS1: TV1) {
311-
auto *Node1 = TS1->getNode();
312-
MemoryDescriptor Dptr1 = *TS1;
313-
if (Node0 == Node1) {
314-
if (Dptr0.is<trait::Readonly>() && !Dptr1.is<trait::Readonly>()) {
300+
if (!STR.isUnreachable(const_cast<DIAliasNode *>(TS0->getNode()),
301+
const_cast<DIAliasNode *>(TS1->getNode()))) {
302+
if (TS0->is<trait::Readonly>() && !TS1->is<trait::Readonly>()) {
315303
// anti dependence
316304
return true;
317-
} else if (Dptr1.is<trait::Readonly>() && !Dptr0.is<trait::Readonly>()){
305+
} else if (TS1->is<trait::Readonly>() && !TS0->is<trait::Readonly>()){
318306
// true dependence
319307
return true;
320308
}
@@ -325,29 +313,28 @@ bool ClangLoopSwapping::hasTrueOrAntiDependence(
325313
}
326314

327315
bool ClangLoopSwapping::isSwappingAvailable(
328-
std::pair<Loop *, Loop *> &Loops) const {
329-
auto HasLoopID = [this](MDNode*& LoopID, int LoopN) {
330-
if (!LoopID || !(LoopID = mGetLoopID(LoopID))) {
331-
LLVM_DEBUG(dbgs() << "[LOOP SWAPPING]: ignore loop without ID (loop " <<
332-
LoopN << ").\n");
333-
return false;
334-
}
335-
return true;
336-
};
337-
auto *LoopID0 = Loops.first->getLoopID();
338-
auto *LoopID1 = Loops.second->getLoopID();
339-
if (!HasLoopID(LoopID0, 0))
316+
const LoopRangeList &LRL, const Stmt *Pragma) const {
317+
auto *LoopID0 = mGetLoopID(LRL[0].first->getLoopID());
318+
auto *LoopID1 = mGetLoopID(LRL[1].first->getLoopID());
319+
if (!LoopID0) {
320+
toDiag(mSrcMgr->getDiagnostics(), LRL[0].second.getBegin(),
321+
diag::warn_loop_swapping_no_loop_id);
340322
return false;
341-
if (!HasLoopID(LoopID1, 1))
323+
}
324+
if (!LoopID1) {
325+
toDiag(mSrcMgr->getDiagnostics(), LRL[1].second.getBegin(),
326+
diag::warn_loop_swapping_no_loop_id);
342327
return false;
328+
}
343329
auto Traits0 = getLoopTraits(LoopID0);
344330
auto Traits1 = getLoopTraits(LoopID1);
345331
if (!hasSameReductionKind(Traits0, Traits1)) {
346-
toDiag(mSrcMgr->getDiagnostics(), diag::warn_loop_swapping_diff_reduction);
332+
toDiag(mSrcMgr->getDiagnostics(), Pragma->getBeginLoc(),
333+
diag::warn_loop_swapping_diff_reduction);
347334
return false;
348335
}
349336
if (hasTrueOrAntiDependence(Traits0, Traits1)) {
350-
toDiag(mSrcMgr->getDiagnostics(),
337+
toDiag(mSrcMgr->getDiagnostics(), Pragma->getBeginLoc(),
351338
diag::warn_loop_swapping_true_anti_dependence);
352339
return false;
353340
}
@@ -356,48 +343,38 @@ bool ClangLoopSwapping::isSwappingAvailable(
356343

357344
void ClangLoopSwapping::swapLoops(const LoopVisitor &Visitor) {
358345
Rewriter &Rewr = mTfmCtx->getRewriter();
359-
auto GetLoopEnd = [this, Rewr](const SourceRange &LoopRange)->SourceLocation {
346+
auto GetLoopEnd = [this, &Rewr](const SourceRange &LoopRange) {
360347
Token SemiTok;
361348
return (!getRawTokenAfter(LoopRange.getEnd(), *mSrcMgr,
362349
Rewr.getLangOpts(), SemiTok) && SemiTok.is(tok::semi)) ?
363350
SemiTok.getLocation() : LoopRange.getEnd();
364351
};
365-
auto &PragmaLevels = Visitor.getPragmaLevels();
366352
auto &PragmaLoopsInfo = Visitor.getPragmaLoopsInfo();
367-
for (auto it = PragmaLevels.rbegin(); it != PragmaLevels.rend(); it++) {
368-
for (auto &Pragma : *it) {
369-
auto PragmaItr = PragmaLoopsInfo.find(Pragma);
370-
assert(PragmaItr != PragmaLoopsInfo.end() &&
371-
"Map should contain all pragmas (as keys) from level vectors.");
372-
const auto &Loops = PragmaItr->second;
373-
if (Loops.size() < 2) {
374-
toDiag(mSrcMgr->getDiagnostics(),
375-
diag::warn_loop_swapping_missing_loop);
376-
continue;
377-
}
378-
if (Loops.size() > 2) {
379-
toDiag(mSrcMgr->getDiagnostics(),
380-
diag::warn_loop_swapping_redundant_loop);
381-
}
382-
auto Info0 = Loops[0];
383-
auto Info1 = Loops[1];
384-
auto Loop0 = Info0.first;
385-
auto Loop1 = Info1.first;
386-
auto LoopPair = std::make_pair(Loop0, Loop1);
387-
if (isSwappingAvailable(LoopPair)) {
388-
auto &Range0 = Info0.second;
389-
auto &Range1 = Info1.second;
390-
Range0.setEnd(GetLoopEnd(Range0));
391-
Range1.setEnd(GetLoopEnd(Range1));
392-
auto Range0End = Range0.getEnd();
393-
auto Range1Begin = Range1.getBegin();
394-
const auto &LoopText0 = Rewr.getRewrittenText(Range0);
395-
const auto &LoopText1 = Rewr.getRewrittenText(Range1);
396-
Rewr.RemoveText(Range0);
397-
Rewr.RemoveText(Range1);
398-
Rewr.InsertTextBefore(Range0End, LoopText1);
399-
Rewr.InsertTextAfter(Range1Begin, LoopText0);
400-
}
353+
for (auto It = PragmaLoopsInfo.begin(); It != PragmaLoopsInfo.end(); It++) {
354+
auto &Pragma = It->first;
355+
auto &Loops = It->second;
356+
if (Loops.size() < 2) {
357+
toDiag(mSrcMgr->getDiagnostics(), Pragma->getBeginLoc(),
358+
diag::warn_loop_swapping_missing_loop);
359+
continue;
360+
}
361+
if (Loops.size() > 2) {
362+
toDiag(mSrcMgr->getDiagnostics(), Pragma->getBeginLoc(),
363+
diag::warn_loop_swapping_redundant_loop);
364+
}
365+
if (isSwappingAvailable(Loops, Pragma)) {
366+
auto Range0 = Loops[0].second;
367+
auto Range1 = Loops[1].second;
368+
Range0.setEnd(GetLoopEnd(Range0));
369+
Range1.setEnd(GetLoopEnd(Range1));
370+
auto Range0End = Range0.getEnd();
371+
auto Range1Begin = Range1.getBegin();
372+
const auto &LoopText0 = Rewr.getRewrittenText(Range0);
373+
const auto &LoopText1 = Rewr.getRewrittenText(Range1);
374+
Rewr.RemoveText(Range0);
375+
Rewr.RemoveText(Range1);
376+
Rewr.InsertTextBefore(Range0End, LoopText1);
377+
Rewr.InsertTextAfter(Range1Begin, LoopText0);
401378
}
402379
}
403380
}
@@ -436,11 +413,13 @@ bool ClangLoopSwapping::runOnFunction(Function &F) {
436413
LoopVisitor Visitor(mTfmCtx->getRewriter(), mLoopInfo, *ImportInfo);
437414
mSrcMgr = &mTfmCtx->getRewriter().getSourceMgr();
438415
Visitor.TraverseDecl(FuncDecl);
439-
if (Visitor.getMaxPragmaDepth() == 0) {
416+
if (mSrcMgr->getDiagnostics().hasErrorOccurred())
417+
return false;
418+
if (!Visitor.hasPragma()) {
440419
LLVM_DEBUG(dbgs() << "[LOOP SWAPPING]: no pragma found.\n");
441420
return false;
442421
}
443-
Visitor.printLocations();
422+
LLVM_DEBUG(Visitor.printLocations());
444423
swapLoops(Visitor);
445424
return false;
446425
}

0 commit comments

Comments
 (0)