Index: include/polly/ScopDetection.h =================================================================== --- include/polly/ScopDetection.h +++ include/polly/ScopDetection.h @@ -60,6 +60,7 @@ using namespace llvm; namespace llvm { +class AssumptionCache; class RegionInfo; class Region; class LoopInfo; @@ -197,6 +198,7 @@ LoopInfo *LI; RegionInfo *RI; AliasAnalysis *AA; + AssumptionCache *AC; //@} /// @brief Map to remember detection contexts for valid regions. @@ -378,6 +380,16 @@ /// @brief Print the locations of all detected scops. void printLocations(llvm::Function &F); + /// @brief Get the users profitable annotation for the given region if any. + /// + /// Profitable annotations can be placend in the source via: + /// __builtin_assume(__polly_profitable == X) + /// where X has to be the constant 0 (=unprofitable) or 1 (=profitable) and + /// __polly_profitable a global variable. + /// + /// @returns >0/<0 if annotatations suggest profitable/non-profitable, or 0. + int getProfitableAnnotation(const Region &R) const; + /// @brief Track diagnostics for invalid scops. /// /// @param Context The context of scop detection. Index: lib/Analysis/ScopDetection.cpp =================================================================== --- lib/Analysis/ScopDetection.cpp +++ lib/Analysis/ScopDetection.cpp @@ -53,6 +53,7 @@ #include "polly/Support/ScopLocation.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/RegionIterator.h" @@ -877,13 +878,6 @@ return LastValidRegion.release(); } -static bool regionWithoutLoops(Region &R, LoopInfo *LI) { - for (const BasicBlock *BB : R.blocks()) - if (R.contains(LI->getLoopFor(BB))) - return false; - - return true; -} unsigned ScopDetection::removeCachedResultsRecursively(const Region &R) { unsigned Count = 0; @@ -907,13 +901,7 @@ std::make_pair(&R, DetectionContext(R, *AA, false /*verifying*/))); DetectionContext &Context = It.first->second; - bool RegionIsValid = false; - if (!PollyProcessUnprofitable && regionWithoutLoops(R, LI)) { - removeCachedResults(R); - invalid(Context, /*Assert=*/true, &R); - } else - RegionIsValid = isValidRegion(Context); - + bool RegionIsValid = isValidRegion(Context); bool HasErrors = !RegionIsValid || Context.Log.size() > 0; if (PollyTrackFailures && HasErrors) @@ -994,10 +982,39 @@ return true; } +int ScopDetection::getProfitableAnnotation(const Region &R) const { + unsigned One = 0, Zero = 0; + for (auto &Assumption : AC->assumptions()) { + auto *CI = dyn_cast_or_null(Assumption); + if (!CI || CI->getNumArgOperands() != 1) + continue; + if (!DT->dominates(CI->getParent(), R.getEntry())) + continue; + auto *ICmp = dyn_cast(CI->getArgOperand(0)); + if (!ICmp || !ICmp->isEquality()) + continue; + auto *L = dyn_cast(ICmp->getOperand(0)); + auto *C = dyn_cast(ICmp->getOperand(1)); + if (!L || !C || !(C->isZero() || C->isOne())) + continue; + auto *P = dyn_cast(L->getPointerOperand()); + if (!P || !P->getName().equals("__polly_profitable")) + continue; + One += C->isOne(); + Zero += C->isZero(); + } + return One - Zero; +} + bool ScopDetection::isValidRegion(DetectionContext &Context) const { Region &CurRegion = Context.CurRegion; DEBUG(dbgs() << "Checking region: " << CurRegion.getNameStr() << "\n\t"); + int ProfitableAnnotation = getProfitableAnnotation(CurRegion); + if (ProfitableAnnotation < 0) { + DEBUG(dbgs() << "Annotated unprofitable\n"); + return false; + } if (CurRegion.isTopLevelRegion()) { DEBUG(dbgs() << "Top level region is invalid\n"); @@ -1027,7 +1044,7 @@ return invalid(Context, /*Assert=*/true, CurRegion.getEntry()); int NumLoops = countBeneficialLoops(&CurRegion); - if (!PollyProcessUnprofitable && NumLoops < 2) + if (!PollyProcessUnprofitable && ProfitableAnnotation == 0 && NumLoops < 2) invalid(Context, /*Assert=*/true, &CurRegion); if (!allBlocksValid(Context)) @@ -1035,12 +1052,14 @@ // We can probably not do a lot on scops that only write or only read // data. - if (!PollyProcessUnprofitable && (!Context.hasStores || !Context.hasLoads)) + if (!PollyProcessUnprofitable && ProfitableAnnotation == 0 && + (!Context.hasStores || !Context.hasLoads)) invalid(Context, /*Assert=*/true, &CurRegion); // Check if there are sufficent non-overapproximated loops. int NumAffineLoops = NumLoops - Context.BoxedLoopsSet.size(); - if (!PollyProcessUnprofitable && NumAffineLoops < 2) + if (!PollyProcessUnprofitable && ProfitableAnnotation == 0 && + NumAffineLoops < 2) invalid(Context, /*Assert=*/true, &CurRegion); DEBUG(dbgs() << "OK\n"); @@ -1095,7 +1114,8 @@ bool ScopDetection::runOnFunction(llvm::Function &F) { LI = &getAnalysis().getLoopInfo(); RI = &getAnalysis().getRegionInfo(); - if (!PollyProcessUnprofitable && LI->empty()) + AC = &getAnalysis().getAssumptionCache(F); + if (!PollyProcessUnprofitable && LI->empty() && AC->assumptions().empty()) return false; AA = &getAnalysis().getAAResults(); @@ -1176,6 +1196,7 @@ void ScopDetection::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); + AU.addRequired(); AU.addRequired(); AU.addRequired(); // We also need AA and RegionInfo when we are verifying analysis. @@ -1208,6 +1229,7 @@ "Polly - Detect static control parts (SCoPs)", false, false); INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass); +INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker); INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass); INITIALIZE_PASS_DEPENDENCY(RegionInfoPass); INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass);