extern bool PollyTrackFailures;
extern bool PollyDelinearize;
+/// @brief A function attribute which will cause Polly to skip the function
+extern llvm::StringRef PollySkipFnAttr;
+
//===----------------------------------------------------------------------===//
/// @brief Pass to detect the maximal static control parts (Scops) of a
/// function.
// Remember a list of errors for every region.
mutable RejectLogsContainer RejectLogs;
- // Remember the invalid functions producted by backends;
- typedef std::set<const Function *> FunctionSet;
- FunctionSet InvalidFunctions;
-
// Delinearize all non affine memory accesses and return false when there
// exists a non affine memory access that cannot be delinearized. Return true
// when all array accesses are affine after delinearization.
/// @return True if the loop is valid in the region.
bool isValidLoop(Loop *L, DetectionContext &Context) const;
- /// @brief Check if a function is an OpenMP subfunction.
- ///
- /// An OpenMP subfunction is not valid for Scop detection.
- ///
- /// @param F The function to check.
+ /// @brief Check if the function @p F is marked as invalid.
///
- /// @return True if the function is not an OpenMP subfunction.
+ /// @note An OpenMP subfunction will be marked as invalid.
bool isValidFunction(llvm::Function &F);
/// @brief Print the locations of all detected scops.
/// the function.
///
/// @param F The function to mark as invalid.
- void markFunctionAsInvalid(const Function *F) { InvalidFunctions.insert(F); }
+ void markFunctionAsInvalid(Function *F) const;
/// @brief Verify if all valid Regions in this Function are still valid
/// after some transformations.
bool polly::PollyTrackFailures = false;
bool polly::PollyDelinearize = false;
+StringRef polly::PollySkipFnAttr = "polly.skip.fn";
//===----------------------------------------------------------------------===//
// Statistics.
return true;
}
+void ScopDetection::markFunctionAsInvalid(Function *F) const {
+ F->addFnAttr(PollySkipFnAttr);
+}
+
bool ScopDetection::isValidFunction(llvm::Function &F) {
- return !InvalidFunctions.count(&F);
+ return !F.hasFnAttribute(PollySkipFnAttr);
}
void ScopDetection::printLocations(llvm::Function &F) {
Function *FN = Function::Create(FT, Function::InternalLinkage,
F->getName() + ".omp_subfn", M);
// Do not run any polly pass on the new function.
- P->getAnalysis<polly::ScopDetection>().markFunctionAsInvalid(FN);
+ FN->addFnAttr(PollySkipFnAttr);
Function::arg_iterator AI = FN->arg_begin();
AI->setName("omp.userContext");
-; RUN: opt %loadPolly %defaultOpts -polly-codegen -enable-polly-openmp -analyze < %s 2>&1 | not FileCheck %s
+; RUN: opt %loadPolly %defaultOpts -polly-codegen -enable-polly-openmp -analyze < %s 2>&1 | FileCheck %s
;#define N 500000
;float A[N];
}
-; CHECK: Checking region: omp.setup
+; CHECK-NOT: Checking region: omp.setup
; CHECK: call void @loop_openmp.omp_subfn(i8* %omp_data)
; CHECK: call void @GOMP_parallel_end()
+; Verify the new subfunction is annotated such that SCoP detection will skip it.
+; CHECK: @loop_openmp.omp_subfn({{.*}}) [[ATTR:#[0-9]+]]
+; CHECK: attributes [[ATTR]] = {{{[^\}]*}}polly.skip.fn{{[^\}]*}}}
+
--- /dev/null
+; RUN: opt %loadPolly -polly-detect -analyze < %s | FileCheck %s
+;
+; Verify polly skips this function
+;
+; CHECK-NOT: Valid Region for Scop
+;
+; void polly_skip_me(int *A, int N) {
+; for (int i = 0; i < N; i++)
+; A[i] = A[i] * A[i] + A[i];
+; }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @polly_skip_me(i32* %A, i32 %N) #0 {
+entry:
+ br label %entry.split
+
+entry.split: ; preds = %entry
+ %cmp1 = icmp sgt i32 %N, 0
+ br i1 %cmp1, label %for.body.preheader, label %for.end
+
+for.body.preheader: ; preds = %entry.split
+ br label %for.body
+
+for.body: ; preds = %for.body.preheader, %for.body
+ %i.02 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]
+ %arrayidx = getelementptr inbounds i32* %A, i32 %i.02
+ %tmp = load i32* %arrayidx, align 4
+ %mul = mul nsw i32 %tmp, %tmp
+ %add = add nsw i32 %mul, %tmp
+ %arrayidx3 = getelementptr inbounds i32* %A, i32 %i.02
+ store i32 %add, i32* %arrayidx3, align 4
+ %inc = add nsw i32 %i.02, 1
+ %cmp = icmp slt i32 %inc, %N
+ br i1 %cmp, label %for.body, label %for.end.loopexit
+
+for.end.loopexit: ; preds = %for.body
+ br label %for.end
+
+for.end: ; preds = %for.end.loopexit, %entry.split
+ ret void
+}
+
+attributes #0 = { "polly.skip.fn" }