diff options
| author | Tobias Grosser <tobias@grosser.es> | 2016-07-18 11:56:39 +0000 |
|---|---|---|
| committer | Tobias Grosser <tobias@grosser.es> | 2016-07-18 11:56:39 +0000 |
| commit | 38fc0aed08853fbad0aa55764dd01def682550b6 (patch) | |
| tree | 90c54f8b0a6f7c469d3180a8e39075431413c99c /polly/lib/CodeGen/PPCGCodeGeneration.cpp | |
| parent | 52bd8012bd0f440e21ddec0c1d6ed89605adbb3b (diff) | |
GPGPU: Create host control flow
Create LLVM-IR for all host-side control flow of a given GPU AST. We implement
this by introducing a new GPUNodeBuilder class derived from IslNodeBuilder. The
IslNodeBuilder will take care of generating all general-purpose ast nodes, but
we provide our own createUser implementation to handle the different GPU
specific user statements. For now, we just skip any user statement and only
generate a host-code sceleton, but in subsequent commits we will add handling of
normal ScopStmt's performing computations, kernel calls, as well as host-device
data transfers. We will also introduce run-time check generation and LICM in
subsequent commits.
llvm-svn: 275783
Diffstat (limited to 'polly/lib/CodeGen/PPCGCodeGeneration.cpp')
| -rw-r--r-- | polly/lib/CodeGen/PPCGCodeGeneration.cpp | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/polly/lib/CodeGen/PPCGCodeGeneration.cpp b/polly/lib/CodeGen/PPCGCodeGeneration.cpp index 72de3be94632..e28088e803fc 100644 --- a/polly/lib/CodeGen/PPCGCodeGeneration.cpp +++ b/polly/lib/CodeGen/PPCGCodeGeneration.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "polly/CodeGen/IslNodeBuilder.h" +#include "polly/CodeGen/Utils.h" #include "polly/DependenceInfo.h" #include "polly/LinkAllPasses.h" #include "polly/Options.h" @@ -68,6 +69,35 @@ static __isl_give isl_id_to_ast_expr *pollyBuildAstExprForStmt( return nullptr; } +/// Generate code for a GPU specific isl AST. +/// +/// The GPUNodeBuilder augments the general existing IslNodeBuilder, which +/// generates code for general-prupose AST nodes, with special functionality +/// for generating GPU specific user nodes. +/// +/// @see GPUNodeBuilder::createUser +class GPUNodeBuilder : public IslNodeBuilder { +public: + GPUNodeBuilder(PollyIRBuilder &Builder, ScopAnnotator &Annotator, Pass *P, + const DataLayout &DL, LoopInfo &LI, ScalarEvolution &SE, + DominatorTree &DT, Scop &S) + : IslNodeBuilder(Builder, Annotator, P, DL, LI, SE, DT, S) {} + +private: + /// Create code for user-defined AST nodes. + /// + /// These AST nodes can be of type: + /// + /// - ScopStmt: A computational statement (TODO) + /// - Kernel: A GPU kernel call (TODO) + /// - Data-Transfer: A GPU <-> CPU data-transfer (TODO) + /// + virtual void createUser(__isl_take isl_ast_node *User) { + isl_ast_node_free(User); + return; + } +}; + namespace { class PPCGCodeGeneration : public ScopPass { public: @@ -76,6 +106,12 @@ public: /// The scop that is currently processed. Scop *S; + LoopInfo *LI; + DominatorTree *DT; + ScalarEvolution *SE; + const DataLayout *DL; + RegionInfo *RI; + PPCGCodeGeneration() : ScopPass(ID) {} /// Construct compilation options for PPCG. @@ -650,12 +686,58 @@ public: PPCGScop->options = nullptr; } + /// Generate code for a given GPU AST described by @p Root. + /// + /// @param An isl_ast_node pointing to the root of the GPU AST. + void generateCode(__isl_take isl_ast_node *Root) { + ScopAnnotator Annotator; + Annotator.buildAliasScopes(*S); + + Region *R = &S->getRegion(); + + simplifyRegion(R, DT, LI, RI); + + BasicBlock *EnteringBB = R->getEnteringBlock(); + + PollyIRBuilder Builder = createPollyIRBuilder(EnteringBB, Annotator); + + GPUNodeBuilder NodeBuilder(Builder, Annotator, this, *DL, *LI, *SE, *DT, + *S); + + // Only build the run-time condition and parameters _after_ having + // introduced the conditional branch. This is important as the conditional + // branch will guard the original scop from new induction variables that + // the SCEVExpander may introduce while code generating the parameters and + // which may introduce scalar dependences that prevent us from correctly + // code generating this scop. + BasicBlock *StartBlock = + executeScopConditionally(*S, this, Builder.getTrue()); + + // TODO: Handle LICM + // TODO: Verify run-time checks + auto SplitBlock = StartBlock->getSinglePredecessor(); + Builder.SetInsertPoint(SplitBlock->getTerminator()); + NodeBuilder.addParameters(S->getContext()); + Builder.SetInsertPoint(&*StartBlock->begin()); + NodeBuilder.create(Root); + NodeBuilder.finalizeSCoP(*S); + } + bool runOnScop(Scop &CurrentScop) override { S = &CurrentScop; + LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); + DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); + SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); + DL = &S->getRegion().getEntry()->getParent()->getParent()->getDataLayout(); + RI = &getAnalysis<RegionInfoPass>().getRegionInfo(); auto PPCGScop = createPPCGScop(); auto PPCGProg = createPPCGProg(PPCGScop); auto PPCGGen = generateGPU(PPCGScop, PPCGProg); + + if (PPCGGen->tree) + generateCode(isl_ast_node_copy(PPCGGen->tree)); + freeOptions(PPCGScop); freePPCGGen(PPCGGen); gpu_prog_free(PPCGProg); |
