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. @@ -385,6 +387,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" @@ -1000,10 +1001,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"); @@ -1033,7 +1063,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)) @@ -1041,12 +1071,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"); @@ -1101,7 +1133,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(); @@ -1179,6 +1212,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. @@ -1211,6 +1245,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); Index: test/ScopDetect/profitable_source_annotation.ll =================================================================== --- /dev/null +++ test/ScopDetect/profitable_source_annotation.ll @@ -0,0 +1,42 @@ +; RUN: opt %loadPolly -polly-detect -polly-process-unprofitable=false -analyze < %s | FileCheck %s +; +; CHECK: Valid +; +; int __polly_profitable; +; void f(int *A) { +; __builtin_assume(__polly_profitable == 1); +; for (int i = 0; i < 100; i++) +; A[i] = i; +; } +; +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +@__polly_profitable = common global i32 0, align 4 + +define void @f(i32* %A) { +entry: + %tmp = load i32, i32* @__polly_profitable, align 4 + %cmp = icmp eq i32 %tmp, 1 + call void @llvm.assume(i1 %cmp) + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ] + %exitcond = icmp ne i64 %indvars.iv, 100 + br i1 %exitcond, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv + %tmp1 = trunc i64 %indvars.iv to i32 + store i32 %tmp1, i32* %arrayidx, align 4 + br label %for.inc + +for.inc: ; preds = %for.body + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} + +declare void @llvm.assume(i1) #1