Index: polly/trunk/include/polly/CodeGen/IslAst.h =================================================================== --- polly/trunk/include/polly/CodeGen/IslAst.h +++ polly/trunk/include/polly/CodeGen/IslAst.h @@ -45,7 +45,7 @@ class IslAst { public: - static IslAst *create(Scop *Scop, const Dependences &D); + static IslAst create(Scop &Scop, const Dependences &D); ~IslAst(); /// Print a source code representation of the program. @@ -62,20 +62,25 @@ /// @param Build The isl_build object to use to build the condition. /// /// @returns An ast expression that describes the necessary run-time check. - static isl_ast_expr *buildRunCondition(Scop *S, + static isl_ast_expr *buildRunCondition(Scop &S, __isl_keep isl_ast_build *Build); + IslAst(const IslAst &) = delete; + IslAst &operator=(const IslAst &) = delete; + IslAst(IslAst &&); + IslAst &operator=(IslAst &&) = delete; + private: - Scop *S; + Scop &S; isl_ast_node *Root; isl_ast_expr *RunCondition; std::shared_ptr Ctx; - IslAst(Scop *Scop); + IslAst(Scop &Scop); void init(const Dependences &D); }; -class IslAstInfo : public ScopPass { +class IslAstInfo { public: using MemoryAccessSet = SmallPtrSet; @@ -113,27 +118,14 @@ }; private: - Scop *S; - IslAst *Ast; + Scop &S; + IslAst Ast; public: - static char ID; - IslAstInfo() : ScopPass(ID), S(nullptr), Ast(nullptr) {} - - /// Build the AST for the given SCoP @p S. - bool runOnScop(Scop &S) override; - - /// Register all analyses and transformation required. - void getAnalysisUsage(AnalysisUsage &AU) const override; - - /// Release the internal memory. - void releaseMemory() override; - - /// Print a source code representation of the program. - void printScop(llvm::raw_ostream &OS, Scop &S) const override; + IslAstInfo(Scop &S, const Dependences &D) : S(S), Ast(IslAst::create(S, D)) {} /// Return a copy of the AST root node. - __isl_give isl_ast_node *getAst() const; + __isl_give isl_ast_node *getAst(); /// Get the run condition. /// @@ -141,12 +133,13 @@ /// assumptions that have been taken hold. If the run condition evaluates to /// zero/false some assumptions do not hold and the original code needs to /// be executed. - __isl_give isl_ast_expr *getRunCondition() const; + __isl_give isl_ast_expr *getRunCondition(); + + void print(raw_ostream &O); /// @name Extract information attached to an isl ast (for) node. /// ///{ - /// Get the complete payload attached to @p Node. static IslAstUserPayload *getNodePayload(__isl_keep isl_ast_node *Node); @@ -183,10 +176,47 @@ ///} }; + +struct IslAstAnalysis : public AnalysisInfoMixin { + static AnalysisKey Key; + using Result = IslAstInfo; + IslAstInfo run(Scop &S, ScopAnalysisManager &SAM, + ScopStandardAnalysisResults &SAR); +}; + +class IslAstInfoWrapperPass : public ScopPass { + std::unique_ptr Ast; + +public: + static char ID; + IslAstInfoWrapperPass() : ScopPass(ID) {} + + IslAstInfo &getAI() { return *Ast; } + const IslAstInfo &getAI() const { return *Ast; } + + /// Build the AST for the given SCoP @p S. + bool runOnScop(Scop &S) override; + + /// Register all analyses and transformation required. + void getAnalysisUsage(AnalysisUsage &AU) const override; + + /// Release the internal memory. + void releaseMemory() override; + + /// Print a source code representation of the program. + void printScop(llvm::raw_ostream &OS, Scop &S) const override; +}; + +struct IslAstPrinterPass : public PassInfoMixin { + IslAstPrinterPass(raw_ostream &O) : Stream(O) {} + PreservedAnalyses run(Scop &S, ScopAnalysisManager &SAM, + ScopStandardAnalysisResults &, SPMUpdater &U); + raw_ostream &Stream; +}; } // namespace polly namespace llvm { class PassRegistry; -void initializeIslAstInfoPass(llvm::PassRegistry &); +void initializeIslAstInfoWrapperPassPass(llvm::PassRegistry &); } // namespace llvm #endif /* POLLY_ISL_AST_H */ Index: polly/trunk/include/polly/LinkAllPasses.h =================================================================== --- polly/trunk/include/polly/LinkAllPasses.h +++ polly/trunk/include/polly/LinkAllPasses.h @@ -46,7 +46,7 @@ llvm::Pass *createScopDetectionWrapperPassPass(); llvm::Pass *createScopInfoRegionPassPass(); llvm::Pass *createScopInfoWrapperPassPass(); -llvm::Pass *createIslAstInfoPass(); +llvm::Pass *createIslAstInfoWrapperPassPass(); llvm::Pass *createCodeGenerationPass(); #ifdef GPU_CODEGEN llvm::Pass *createPPCGCodeGenerationPass(GPUArch Arch = GPUArch::NVPTX64, @@ -82,7 +82,7 @@ polly::createScopInfoRegionPassPass(); polly::createPollyCanonicalizePass(); polly::createPolyhedralInfoPass(); - polly::createIslAstInfoPass(); + polly::createIslAstInfoWrapperPassPass(); polly::createCodeGenerationPass(); #ifdef GPU_CODEGEN polly::createPPCGCodeGenerationPass(); @@ -103,7 +103,7 @@ void initializeDeadCodeElimPass(llvm::PassRegistry &); void initializeJSONExporterPass(llvm::PassRegistry &); void initializeJSONImporterPass(llvm::PassRegistry &); -void initializeIslAstInfoPass(llvm::PassRegistry &); +void initializeIslAstInfoWrapperPassPass(llvm::PassRegistry &); void initializeCodeGenerationPass(llvm::PassRegistry &); #ifdef GPU_CODEGEN void initializePPCGCodeGenerationPass(llvm::PassRegistry &); Index: polly/trunk/lib/CodeGen/CodeGeneration.cpp =================================================================== --- polly/trunk/lib/CodeGen/CodeGeneration.cpp +++ polly/trunk/lib/CodeGen/CodeGeneration.cpp @@ -80,7 +80,7 @@ "SCoP ==\n"; S.print(errs()); errs() << "\n== The isl AST ==\n"; - AI->printScop(errs(), S); + AI->print(errs()); errs() << "\n== The invalid function ==\n"; F.print(errs()); }); @@ -167,7 +167,7 @@ /// Generate LLVM-IR for the SCoP @p S. bool runOnScop(Scop &S) override { - AI = &getAnalysis(); + AI = &getAnalysis().getAI(); // Check if we created an isl_ast root node, otherwise exit. isl_ast_node *AstRoot = AI->getAst(); @@ -273,7 +273,7 @@ /// Register all analyses and transformation required. void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); - AU.addRequired(); + AU.addRequired(); AU.addRequired(); AU.addRequired(); AU.addRequired(); @@ -287,7 +287,7 @@ AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); - AU.addPreserved(); + AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); Index: polly/trunk/lib/CodeGen/IslAst.cpp =================================================================== --- polly/trunk/lib/CodeGen/IslAst.cpp +++ polly/trunk/lib/CodeGen/IslAst.cpp @@ -332,18 +332,18 @@ } __isl_give isl_ast_expr * -IslAst::buildRunCondition(Scop *S, __isl_keep isl_ast_build *Build) { +IslAst::buildRunCondition(Scop &S, __isl_keep isl_ast_build *Build) { isl_ast_expr *RunCondition; // The conditions that need to be checked at run-time for this scop are // available as an isl_set in the runtime check context from which we can // directly derive a run-time condition. - auto *PosCond = isl_ast_build_expr_from_set(Build, S->getAssumedContext()); - if (S->hasTrivialInvalidContext()) { + auto *PosCond = isl_ast_build_expr_from_set(Build, S.getAssumedContext()); + if (S.hasTrivialInvalidContext()) { RunCondition = PosCond; } else { auto *ZeroV = isl_val_zero(isl_ast_build_get_ctx(Build)); - auto *NegCond = isl_ast_build_expr_from_set(Build, S->getInvalidContext()); + auto *NegCond = isl_ast_build_expr_from_set(Build, S.getInvalidContext()); auto *NotNegCond = isl_ast_expr_eq(isl_ast_expr_from_val(ZeroV), NegCond); RunCondition = isl_ast_expr_and(PosCond, NotNegCond); } @@ -352,7 +352,7 @@ // group which consists of read only and non read only (read write) accesses. // This operation is by construction quadratic in the read-write pointers and // linear in the read only pointers in each alias group. - for (const Scop::MinMaxVectorPairTy &MinMaxAccessPair : S->getAliasGroups()) { + for (const Scop::MinMaxVectorPairTy &MinMaxAccessPair : S.getAliasGroups()) { auto &MinMaxReadWrite = MinMaxAccessPair.first; auto &MinMaxReadOnly = MinMaxAccessPair.second; auto RWAccEnd = MinMaxReadWrite.end(); @@ -378,23 +378,23 @@ /// In order to improve the cost model we could either keep track of /// performed optimizations (e.g., tiling) or compute properties on the /// original as well as optimized SCoP (e.g., #stride-one-accesses). -static bool benefitsFromPolly(Scop *Scop, bool PerformParallelTest) { +static bool benefitsFromPolly(Scop &Scop, bool PerformParallelTest) { if (PollyProcessUnprofitable) return true; // Check if nothing interesting happened. - if (!PerformParallelTest && !Scop->isOptimized() && - Scop->getAliasGroups().empty()) + if (!PerformParallelTest && !Scop.isOptimized() && + Scop.getAliasGroups().empty()) return false; // The default assumption is that Polly improves the code. return true; } -IslAst::IslAst(Scop *Scop) +IslAst::IslAst(Scop &Scop) : S(Scop), Root(nullptr), RunCondition(nullptr), - Ctx(Scop->getSharedIslCtx()) {} + Ctx(Scop.getSharedIslCtx()) {} void IslAst::init(const Dependences &D) { bool PerformParallelTest = PollyParallel || DetectParallel || @@ -403,25 +403,25 @@ // We can not perform the dependence analysis and, consequently, // the parallel code generation in case the schedule tree contains // extension nodes. - auto *ScheduleTree = S->getScheduleTree(); + auto *ScheduleTree = S.getScheduleTree(); PerformParallelTest = - PerformParallelTest && !S->containsExtensionNode(ScheduleTree); + PerformParallelTest && !S.containsExtensionNode(ScheduleTree); isl_schedule_free(ScheduleTree); // Skip AST and code generation if there was no benefit achieved. if (!benefitsFromPolly(S, PerformParallelTest)) return; - isl_ctx *Ctx = S->getIslCtx(); + isl_ctx *Ctx = S.getIslCtx(); isl_options_set_ast_build_atomic_upper_bound(Ctx, true); isl_options_set_ast_build_detect_min_max(Ctx, true); isl_ast_build *Build; AstBuildUserInfo BuildInfo; if (UseContext) - Build = isl_ast_build_from_context(S->getContext()); + Build = isl_ast_build_from_context(S.getContext()); else - Build = isl_ast_build_from_context(isl_set_universe(S->getParamSpace())); + Build = isl_ast_build_from_context(isl_set_universe(S.getParamSpace())); Build = isl_ast_build_set_at_each_domain(Build, AtEachDomain, nullptr); @@ -443,17 +443,23 @@ RunCondition = buildRunCondition(S, Build); - Root = isl_ast_build_node_from_schedule(Build, S->getScheduleTree()); + Root = isl_ast_build_node_from_schedule(Build, S.getScheduleTree()); isl_ast_build_free(Build); } -IslAst *IslAst::create(Scop *Scop, const Dependences &D) { - auto Ast = new IslAst(Scop); - Ast->init(D); +IslAst IslAst::create(Scop &Scop, const Dependences &D) { + IslAst Ast{Scop}; + Ast.init(D); return Ast; } +IslAst::IslAst(IslAst &&O) + : S(O.S), Root(O.Root), RunCondition(O.RunCondition), Ctx(O.Ctx) { + O.Root = nullptr; + O.RunCondition = nullptr; +} + IslAst::~IslAst() { isl_ast_node_free(Root); isl_ast_expr_free(RunCondition); @@ -464,31 +470,9 @@ return isl_ast_expr_copy(RunCondition); } -void IslAstInfo::releaseMemory() { - if (Ast) { - delete Ast; - Ast = nullptr; - } -} - -bool IslAstInfo::runOnScop(Scop &Scop) { - if (Ast) - delete Ast; - - S = &Scop; - - const Dependences &D = - getAnalysis().getDependences(Dependences::AL_Statement); - - Ast = IslAst::create(&Scop, D); - - DEBUG(printScop(dbgs(), Scop)); - return false; -} - -__isl_give isl_ast_node *IslAstInfo::getAst() const { return Ast->getAst(); } -__isl_give isl_ast_expr *IslAstInfo::getRunCondition() const { - return Ast->getRunCondition(); +__isl_give isl_ast_node *IslAstInfo::getAst() { return Ast.getAst(); } +__isl_give isl_ast_expr *IslAstInfo::getRunCondition() { + return Ast.getRunCondition(); } IslAstUserPayload *IslAstInfo::getNodePayload(__isl_keep isl_ast_node *Node) { @@ -569,9 +553,15 @@ return Payload ? Payload->Build : nullptr; } -void IslAstInfo::printScop(raw_ostream &OS, Scop &S) const { +IslAstInfo IslAstAnalysis::run(Scop &S, ScopAnalysisManager &SAM, + ScopStandardAnalysisResults &SAR) { + return {S, SAM.getResult(S, SAR).getDependences( + Dependences::AL_Statement)}; +} + +void IslAstInfo::print(raw_ostream &OS) { isl_ast_print_options *Options; - isl_ast_node *RootNode = getAst(); + isl_ast_node *RootNode = Ast.getAst(); Function &F = S.getFunction(); OS << ":: isl ast :: " << F.getName() << " :: " << S.getNameStr() << "\n"; @@ -586,7 +576,7 @@ return; } - isl_ast_expr *RunCondition = getRunCondition(); + isl_ast_expr *RunCondition = Ast.getRunCondition(); char *RtCStr, *AstStr; Options = isl_ast_print_options_alloc(S.getIslCtx()); @@ -621,21 +611,49 @@ isl_printer_free(P); } -void IslAstInfo::getAnalysisUsage(AnalysisUsage &AU) const { +AnalysisKey IslAstAnalysis::Key; +PreservedAnalyses IslAstPrinterPass::run(Scop &S, ScopAnalysisManager &SAM, + ScopStandardAnalysisResults &SAR, + SPMUpdater &U) { + + auto &Ast = SAM.getResult(S, SAR); + Ast.print(Stream); + return PreservedAnalyses::all(); +} + +void IslAstInfoWrapperPass::releaseMemory() { Ast.reset(); } + +bool IslAstInfoWrapperPass::runOnScop(Scop &Scop) { + const Dependences &D = + getAnalysis().getDependences(Dependences::AL_Statement); + + Ast.reset(new IslAstInfo(Scop, D)); + + DEBUG(printScop(dbgs(), Scop)); + return false; +} +void IslAstInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { // Get the Common analysis usage of ScopPasses. ScopPass::getAnalysisUsage(AU); AU.addRequired(); AU.addRequired(); } -char IslAstInfo::ID = 0; +void IslAstInfoWrapperPass::printScop(raw_ostream &OS, Scop &S) const { + if (Ast) + Ast->print(OS); +} -Pass *polly::createIslAstInfoPass() { return new IslAstInfo(); } +char IslAstInfoWrapperPass::ID = 0; + +Pass *polly::createIslAstInfoWrapperPassPass() { + return new IslAstInfoWrapperPass(); +} -INITIALIZE_PASS_BEGIN(IslAstInfo, "polly-ast", +INITIALIZE_PASS_BEGIN(IslAstInfoWrapperPass, "polly-ast", "Polly - Generate an AST of the SCoP (isl)", false, false); INITIALIZE_PASS_DEPENDENCY(ScopInfoRegionPass); INITIALIZE_PASS_DEPENDENCY(DependenceInfo); -INITIALIZE_PASS_END(IslAstInfo, "polly-ast", +INITIALIZE_PASS_END(IslAstInfoWrapperPass, "polly-ast", "Polly - Generate an AST from the SCoP (isl)", false, false) Index: polly/trunk/lib/CodeGen/PPCGCodeGeneration.cpp =================================================================== --- polly/trunk/lib/CodeGen/PPCGCodeGeneration.cpp +++ polly/trunk/lib/CodeGen/PPCGCodeGeneration.cpp @@ -2645,7 +2645,7 @@ NodeBuilder.addParameters(S->getContext()); isl_ast_build *Build = isl_ast_build_alloc(S->getIslCtx()); - isl_ast_expr *Condition = IslAst::buildRunCondition(S, Build); + isl_ast_expr *Condition = IslAst::buildRunCondition(*S, Build); isl_ast_expr *SufficientCompute = createSufficientComputeCheck(*S, Build); Condition = isl_ast_expr_and(Condition, SufficientCompute); isl_ast_build_free(Build); Index: polly/trunk/lib/Support/RegisterPasses.cpp =================================================================== --- polly/trunk/lib/Support/RegisterPasses.cpp +++ polly/trunk/lib/Support/RegisterPasses.cpp @@ -230,7 +230,7 @@ initializeDependenceInfoWrapperPassPass(Registry); initializeJSONExporterPass(Registry); initializeJSONImporterPass(Registry); - initializeIslAstInfoPass(Registry); + initializeIslAstInfoWrapperPassPass(Registry); initializeIslScheduleOptimizerPass(Registry); initializePollyCanonicalizePass(Registry); initializePolyhedralInfoPass(Registry); @@ -333,7 +333,7 @@ } else { switch (CodeGeneration) { case CODEGEN_AST: - PM.add(polly::createIslAstInfoPass()); + PM.add(polly::createIslAstInfoWrapperPassPass()); break; case CODEGEN_FULL: PM.add(polly::createCodeGenerationPass());