Skip to content

Commit 708c242

Browse files
committed
[TSAR, Tfm, Reversal, Loop] Add new checks and update diagnostics.
1 parent 190e8b9 commit 708c242

File tree

2 files changed

+66
-23
lines changed

2 files changed

+66
-23
lines changed

include/tsar/Support/DiagnosticKinds.td

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,18 @@ def warn_interchange_not_for_loop: Warning<"unable to interchange not for-loop">
195195
def warn_interchange_dependency: Warning<"unable to interchange loop with data dependencies (use the 'nostrict' clause to force transformation)">;
196196
def warn_interchange_no_analysis: Warning<"absence of analysis results prevents loop interchange (use the 'nostrict' clause to force transformation">;
197197

198-
def err_reverse_not_forstmt : Error<"for loop expected">;
199-
def err_reverse_not_canonical : Error<"expected canonical loop form">;
200-
def warn_reverse_cant_match: Error<"can't match this to loop">;
201-
def err_reverse_no_analysis: Error<"No analysis for loop; use 'nostrict' clause to skip this">;
202-
def err_reverse_dependency: Error<"there is dependence in loop">;
198+
def warn_reverse_not_for_loop: Warning<"unable to reverse not for-loop">;
199+
def warn_disable_loop_reversal: Warning<"disable loop reversal">;
200+
def warn_reverse_induction_mismatch: Warning<"unable to find a reversible loop with the '%0' induction variable">;
201+
def warn_reverse_number_mismatch: Warning<"unable to find %0 reversible loop in the nest">;
202+
def warn_reverse_not_canonical: Warning<"unable to reverse loop being not in a canonical loop form">;
203+
def warn_reverse_multiple_exits: Warning<"unable to reverse loop having multiple exits (use the 'nostrict' clause to force transformation)">;
204+
def warn_reverse_unsafe_cfg: Warning<"unable to reverse loop with unsafe control flow (use the 'nostrict' clause to force transformation)">;
205+
def warn_reverse_no_analysis: Warning<"absence of analysis results prevents loop reversal (use the 'nostrict' clause to force transformation">;
206+
def warn_reverse_dependency: Warning<"unable to reverse loop with data dependencies (use the 'nostrict' clause to force transformation)">;
207+
def warn_reverse_increment_complex: Warning<"complex increment expression prevents loop reversal">;
208+
def warn_reverse_condition_complex: Warning<"complex conditional expression prevents loop reversal">;
209+
def warn_reverse_initialization_complex: Warning<"complex initialization expression prevents loop reversal">;
203210

204211
// Fortran-specific diagnostics.
205212
def warn_fortran_no_execution_part: Warning<"unable to locate execution-part statmenets">;

lib/Transform/Clang/LoopReversal.cpp

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "tsar/Frontend/Clang/Pragma.h"
4242
#include "tsar/Frontend/Clang/TransformationContext.h"
4343
#include "tsar/Transform/Clang/Passes.h"
44+
#include "tsar/Transform/IR/InterprocAttr.h"
4445
#include "tsar/Support/MetadataUtils.h"
4546
#include "tsar/Support/Clang/Diagnostic.h"
4647
#include "tsar/Support/GlobalOptions.h"
@@ -110,6 +111,7 @@ void ClangLoopReverse::getAnalysisUsage(AnalysisUsage &AU) const {
110111
AU.addRequired<ClangPerfectLoopPass>();
111112
AU.addRequired<DIEstimateMemoryPass>();
112113
AU.addRequired<GlobalOptionsImmutableWrapper>();
114+
AU.addRequired<LoopAttributesDeductionPass>();
113115
AU.addRequired<MemoryMatcherImmutableWrapper>();
114116
AU.addRequired<TransformationEnginePass>();
115117
AU.setPreservesAll();
@@ -128,6 +130,7 @@ INITIALIZE_PASS_DEPENDENCY(ClangPerfectLoopPass)
128130
INITIALIZE_PASS_DEPENDENCY(DIEstimateMemoryPass)
129131
INITIALIZE_PASS_DEPENDENCY(DIDependencyAnalysisPass)
130132
INITIALIZE_PASS_DEPENDENCY(GlobalOptionsImmutableWrapper)
133+
INITIALIZE_PASS_DEPENDENCY(LoopAttributesDeductionPass)
131134
INITIALIZE_PASS_DEPENDENCY(MemoryMatcherImmutableWrapper)
132135
INITIALIZE_PASS_DEPENDENCY(TransformationEnginePass)
133136
INITIALIZE_PASS_IN_GROUP_END(ClangLoopReverse, "clang-loop-reverse",
@@ -201,7 +204,8 @@ class ClangLoopReverseVisitor
201204
P.getAnalysis<ClangPerfectLoopPass>().getPerfectLoopInfo()),
202205
mCanonicalLoopInfo(
203206
P.getAnalysis<CanonicalLoopPass>().getCanonicalLoopInfo()),
204-
mDIMInfo(P.getAnalysis<DIEstimateMemoryPass>().getAliasTree(), P, F) {}
207+
mDIMInfo(P.getAnalysis<DIEstimateMemoryPass>().getAliasTree(), P, F),
208+
mLoopAttr(P.getAnalysis<LoopAttributesDeductionPass>()) {}
205209

206210
bool TraverseForStmt(clang::ForStmt *FS) {
207211
if (mStatus != TRAVERSE_LOOPS)
@@ -222,7 +226,7 @@ class ClangLoopReverseVisitor
222226
return RecursiveASTVisitor::TraverseDecl(D);
223227
if (mStatus == TRAVERSE_STMT) {
224228
toDiag(mSrcMgr.getDiagnostics(), D->getLocation(),
225-
tsar::diag::err_reverse_not_forstmt);
229+
tsar::diag::warn_reverse_not_for_loop);
226230
resetVisitor();
227231
}
228232
return RecursiveASTVisitor::TraverseDecl(D);
@@ -295,7 +299,7 @@ class ClangLoopReverseVisitor
295299
assert(mStatus == TRAVERSE_STMT && "Invalid visitor status!");
296300
if (!isa<clang::ForStmt>(S)) {
297301
toDiag(mSrcMgr.getDiagnostics(), S->getBeginLoc(),
298-
tsar::diag::err_reverse_not_forstmt);
302+
tsar::diag::warn_reverse_not_for_loop);
299303
resetVisitor();
300304
return RecursiveASTVisitor::TraverseStmt(S);
301305
}
@@ -323,7 +327,8 @@ class ClangLoopReverseVisitor
323327
})};
324328
if (LoopItr == mLoops.end()) {
325329
toDiag(mSrcMgr.getDiagnostics(), Literal->getBeginLoc(),
326-
tsar::diag::warn_reverse_cant_match);
330+
tsar::diag::warn_reverse_induction_mismatch)
331+
<< Literal->getString();
327332
} else {
328333
ToTransform.resize(std::distance(mLoops.begin(), LoopItr), false);
329334
ToTransform.push_back(true);
@@ -340,21 +345,37 @@ class ClangLoopReverseVisitor
340345
<< "\n");
341346
} else {
342347
toDiag(mSrcMgr.getDiagnostics(), Literal->getBeginLoc(),
343-
tsar::diag::warn_reverse_cant_match);
348+
tsar::diag::warn_reverse_number_mismatch)
349+
<< static_cast<unsigned>(LoopIdx);
344350
}
345351
}
346352
for (auto Num : ToTransform.set_bits()) {
347353
auto *CanonicalInfo{std::get<const CanonicalLoopInfo *>(mLoops[Num])};
348354
assert(CanonicalInfo && "CanonicalLoopInfo must not be null!");
349355
if (!CanonicalInfo->isCanonical()) {
350356
toDiag(mSrcMgr.getDiagnostics(), S->getBeginLoc(),
351-
tsar::diag::err_reverse_not_canonical);
357+
tsar::diag::warn_reverse_not_canonical);
352358
continue;
353359
}
360+
auto *L{CanonicalInfo->getLoop()->getLoop()};
354361
Optional<APSInt> Start, Step, End;
355-
if (mIsStrict &&
356-
!checkDependencies(Num, *CanonicalInfo, Start, Step, End))
357-
continue;
362+
if (mIsStrict) {
363+
if (!L->getExitingBlock()) {
364+
toDiag(mSrcMgr.getDiagnostics(), S->getBeginLoc(),
365+
tsar::diag::warn_reverse_multiple_exits);
366+
continue;
367+
}
368+
if (!mLoopAttr.hasAttr(*L, AttrKind::AlwaysReturn) ||
369+
!mLoopAttr.hasAttr(*L, AttrKind::NoIO) ||
370+
!mLoopAttr.hasAttr(*L, Attribute::NoUnwind) ||
371+
mLoopAttr.hasAttr(*L, Attribute::ReturnsTwice)) {
372+
toDiag(mSrcMgr.getDiagnostics(), S->getBeginLoc(),
373+
tsar::diag::warn_reverse_unsafe_cfg);
374+
continue;
375+
}
376+
if (!checkDependencies(Num, *CanonicalInfo, Start, Step, End))
377+
continue;
378+
}
358379
transformLoop(*CanonicalInfo, *std::get<clang::VarDecl *>(mLoops[Num]),
359380
Start, Step, End);
360381
}
@@ -369,14 +390,14 @@ class ClangLoopReverseVisitor
369390
if (!mDIMInfo.isValid()) {
370391
toDiag(mSrcMgr.getDiagnostics(),
371392
CanonicalInfo.getASTLoop()->getBeginLoc(),
372-
tsar::diag::err_reverse_no_analysis);
393+
tsar::diag::warn_reverse_no_analysis);
373394
return false;
374395
}
375396
auto *DIDepSet{mDIMInfo.findFromClient(*Loop)};
376397
if (!DIDepSet) {
377398
toDiag(mSrcMgr.getDiagnostics(),
378399
CanonicalInfo.getASTLoop()->getBeginLoc(),
379-
tsar::diag::err_reverse_no_analysis);
400+
tsar::diag::warn_reverse_no_analysis);
380401
return false;
381402
}
382403
DenseSet<const DIAliasNode *> Coverage;
@@ -408,7 +429,7 @@ class ClangLoopReverseVisitor
408429
}
409430
toDiag(mSrcMgr.getDiagnostics(),
410431
CanonicalInfo.getASTLoop()->getBeginLoc(),
411-
tsar::diag::err_reverse_dependency);
432+
tsar::diag::warn_reverse_dependency);
412433
return false;
413434
}
414435
}
@@ -536,21 +557,35 @@ class ClangLoopReverseVisitor
536557
const Optional<APSInt> &Step, const Optional<APSInt> &End) {
537558
IncrementInfo IE{
538559
parseIncrement(*CanonicalInfo.getASTLoop()->getInc(), Induction)};
539-
if (!IE)
560+
if (!IE) {
561+
toDiag(mSrcMgr.getDiagnostics(),
562+
CanonicalInfo.getASTLoop()->getBeginLoc(),
563+
tsar::diag::warn_reverse_increment_complex);
540564
return false;
565+
}
541566
ConditionInfo CE{
542567
parseCondition(*CanonicalInfo.getASTLoop()->getCond(), Induction)};
543-
if (!CE)
568+
if (!CE) {
569+
toDiag(mSrcMgr.getDiagnostics(),
570+
CanonicalInfo.getASTLoop()->getBeginLoc(),
571+
tsar::diag::warn_reverse_condition_complex);
544572
return false;
573+
}
545574
clang::SourceRange InitRange;
546575
if (auto *BO{dyn_cast<clang::BinaryOperator>(
547-
CanonicalInfo.getASTLoop()->getInit())})
576+
CanonicalInfo.getASTLoop()->getInit())};
577+
BO && BO->getOpcode() == clang::BinaryOperator::Opcode::BO_Assign &&
578+
isInductionRef(BO->getLHS(), &Induction)) {
548579
InitRange = BO->getRHS()->getSourceRange();
549-
else if (auto *DS{dyn_cast<clang::DeclStmt>(
550-
CanonicalInfo.getASTLoop()->getInit())})
580+
} else if (auto *DS{dyn_cast<clang::DeclStmt>(
581+
CanonicalInfo.getASTLoop()->getInit())}) {
551582
InitRange = DS->child_begin()->getSourceRange();
552-
else
583+
} else {
584+
toDiag(mSrcMgr.getDiagnostics(),
585+
CanonicalInfo.getASTLoop()->getBeginLoc(),
586+
tsar::diag::warn_reverse_initialization_complex);
553587
return false;
588+
}
554589
auto InitStr{mRewriter.getRewrittenText(InitRange)};
555590
if (Start)
556591
InitStr = Start->toString(10);
@@ -608,6 +643,7 @@ class ClangLoopReverseVisitor
608643
PerfectLoopInfo &mPerfectLoopInfo;
609644
const CanonicalLoopSet &mCanonicalLoopInfo;
610645
DIMemoryClientServerInfo mDIMInfo;
646+
LoopAttributesDeductionPass &mLoopAttr;
611647
bool mIsStrict{true};
612648
enum Status {
613649
SEARCH_PRAGMA,

0 commit comments

Comments
 (0)