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.
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>;
5960using DIAliasTraitVector = std::vector<const DIAliasTrait *>;
6061using 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
6365class LoopVisitor : public RecursiveASTVisitor <LoopVisitor> {
6466private:
@@ -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 () << " \t Pragma " << 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\t Begin:" << Begin.printToString (mSrcMgr )
178- << " \n " );
179- LLVM_DEBUG (dbgs () << " \t\t End:" << 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 () << " \t Pragma " << 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\t Begin:" << Range.getBegin ().printToString (mSrcMgr )
171+ << " \n " ;
172+ dbgs () << " \t\t End:" << 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
188181private:
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
203194class ClangLoopSwapping : public FunctionPass , private bcl ::Uncopyable {
@@ -213,12 +204,11 @@ class ClangLoopSwapping : public FunctionPass, private bcl::Uncopyable {
213204private:
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
305295bool 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
327315bool 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
357344void 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