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)
128130INITIALIZE_PASS_DEPENDENCY(DIEstimateMemoryPass)
129131INITIALIZE_PASS_DEPENDENCY(DIDependencyAnalysisPass)
130132INITIALIZE_PASS_DEPENDENCY(GlobalOptionsImmutableWrapper)
133+ INITIALIZE_PASS_DEPENDENCY(LoopAttributesDeductionPass)
131134INITIALIZE_PASS_DEPENDENCY(MemoryMatcherImmutableWrapper)
132135INITIALIZE_PASS_DEPENDENCY(TransformationEnginePass)
133136INITIALIZE_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