Skip to content

Commit 02ca346

Browse files
committedJun 30, 2017
Introduce a hybrid target to generate code for either the GPU or CPU
Summary: Introduce a "hybrid" `-polly-target` option to optimise code for either the GPU or CPU. When this target is selected, PPCGCodeGeneration will attempt first to optimise a Scop. If the Scop isn't modified, it is then sent to the passes that form the CPU pipeline, i.e. IslScheduleOptimizerPass, IslAstInfoWrapperPass and CodeGeneration. In case the Scop is modified, it is marked to be skipped by the subsequent CPU optimisation passes. Reviewers: grosser, Meinersbur, bollu Reviewed By: grosser Subscribers: kbarton, nemanjai, pollydev Tags: #polly Differential Revision: https://reviews.llvm.org/D34054 llvm-svn: 306863
1 parent 9f59da8 commit 02ca346

File tree

7 files changed

+43
-16
lines changed

7 files changed

+43
-16
lines changed
 

‎polly/include/polly/ScopInfo.h

+9
Original file line numberDiff line numberDiff line change
@@ -1633,6 +1633,9 @@ class Scop {
16331633
/// Number of copy statements.
16341634
unsigned CopyStmtsNum;
16351635

1636+
/// Flag to indicate if the Scop is to be skipped.
1637+
bool SkipScop;
1638+
16361639
typedef std::list<ScopStmt> StmtSet;
16371640
/// The statements in this Scop.
16381641
StmtSet Stmts;
@@ -2366,6 +2369,12 @@ class Scop {
23662369
/// Check if the SCoP has been optimized by the scheduler.
23672370
bool isOptimized() const { return IsOptimized; }
23682371

2372+
/// Mark the SCoP to be skipped by ScopPass passes.
2373+
void markAsToBeSkipped() { SkipScop = true; }
2374+
2375+
/// Check if the SCoP is to be skipped by ScopPass passes.
2376+
bool isToBeSkipped() const { return SkipScop; }
2377+
23692378
/// Get the name of the entry and exit blocks of this Scop.
23702379
///
23712380
/// These along with the function name can uniquely identify a Scop.

‎polly/lib/Analysis/ScopInfo.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -3497,8 +3497,8 @@ static Loop *getLoopSurroundingScop(Scop &S, LoopInfo &LI) {
34973497
Scop::Scop(Region &R, ScalarEvolution &ScalarEvolution, LoopInfo &LI,
34983498
ScopDetection::DetectionContext &DC)
34993499
: SE(&ScalarEvolution), R(R), name(R.getNameStr()), IsOptimized(false),
3500-
HasSingleExitEdge(R.getExitingBlock()), HasErrorBlock(false),
3501-
MaxLoopDepth(0), CopyStmtsNum(0), DC(DC),
3500+
SkipScop(false), HasSingleExitEdge(R.getExitingBlock()),
3501+
HasErrorBlock(false), MaxLoopDepth(0), CopyStmtsNum(0), DC(DC),
35023502
IslCtx(isl_ctx_alloc(), isl_ctx_free), Context(nullptr),
35033503
Affinator(this, LI), AssumedContext(nullptr), InvalidContext(nullptr),
35043504
Schedule(nullptr) {

‎polly/lib/CodeGen/CodeGeneration.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,10 @@ class CodeGeneration : public ScopPass {
278278

279279
/// Generate LLVM-IR for the SCoP @p S.
280280
bool runOnScop(Scop &S) override {
281+
// Skip SCoPs in case they're already code-generated by PPCGCodeGeneration.
282+
if (S.isToBeSkipped())
283+
return false;
284+
281285
AI = &getAnalysis<IslAstInfoWrapperPass>().getAI();
282286
LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
283287
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();

‎polly/lib/CodeGen/IslAst.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,11 @@ PreservedAnalyses IslAstPrinterPass::run(Scop &S, ScopAnalysisManager &SAM,
624624
void IslAstInfoWrapperPass::releaseMemory() { Ast.reset(); }
625625

626626
bool IslAstInfoWrapperPass::runOnScop(Scop &Scop) {
627+
628+
// Skip SCoPs in case they're already handled by PPCGCodeGeneration.
629+
if (Scop.isToBeSkipped())
630+
return false;
631+
627632
const Dependences &D =
628633
getAnalysis<DependenceInfo>().getDependences(Dependences::AL_Statement);
629634

‎polly/lib/CodeGen/PPCGCodeGeneration.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -2840,8 +2840,10 @@ class PPCGCodeGeneration : public ScopPass {
28402840
auto PPCGProg = createPPCGProg(PPCGScop);
28412841
auto PPCGGen = generateGPU(PPCGScop, PPCGProg);
28422842

2843-
if (PPCGGen->tree)
2843+
if (PPCGGen->tree) {
28442844
generateCode(isl_ast_node_copy(PPCGGen->tree), PPCGProg);
2845+
CurrentScop.markAsToBeSkipped();
2846+
}
28452847

28462848
freeOptions(PPCGScop);
28472849
freePPCGGen(PPCGGen);

‎polly/lib/Support/RegisterPasses.cpp

+16-13
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,15 @@ static cl::opt<CodeGenChoice> CodeGeneration(
9292
clEnumValN(CODEGEN_NONE, "none", "No code generation")),
9393
cl::Hidden, cl::init(CODEGEN_FULL), cl::ZeroOrMore, cl::cat(PollyCategory));
9494

95-
enum TargetChoice { TARGET_CPU, TARGET_GPU };
95+
enum TargetChoice { TARGET_CPU, TARGET_GPU, TARGET_HYBRID };
9696
static cl::opt<TargetChoice>
9797
Target("polly-target", cl::desc("The hardware to target"),
9898
cl::values(clEnumValN(TARGET_CPU, "cpu", "generate CPU code")
9999
#ifdef GPU_CODEGEN
100100
,
101-
clEnumValN(TARGET_GPU, "gpu", "generate GPU code")
101+
clEnumValN(TARGET_GPU, "gpu", "generate GPU code"),
102+
clEnumValN(TARGET_HYBRID, "hybrid",
103+
"generate GPU code (preferably) or CPU code")
102104
#endif
103105
),
104106
cl::init(TARGET_CPU), cl::ZeroOrMore, cl::cat(PollyCategory));
@@ -314,9 +316,12 @@ void registerPollyPasses(llvm::legacy::PassManagerBase &PM) {
314316
if (EnablePruneUnprofitable)
315317
PM.add(polly::createPruneUnprofitablePass());
316318

317-
if (Target == TARGET_GPU) {
318-
// GPU generation provides its own scheduling optimization strategy.
319-
} else {
319+
#ifdef GPU_CODEGEN
320+
if (Target == TARGET_HYBRID)
321+
PM.add(
322+
polly::createPPCGCodeGenerationPass(GPUArchChoice, GPURuntimeChoice));
323+
#endif
324+
if (Target == TARGET_CPU || Target == TARGET_HYBRID)
320325
switch (Optimizer) {
321326
case OPTIMIZER_NONE:
322327
break; /* Do nothing */
@@ -325,17 +330,11 @@ void registerPollyPasses(llvm::legacy::PassManagerBase &PM) {
325330
PM.add(polly::createIslScheduleOptimizerPass());
326331
break;
327332
}
328-
}
329333

330334
if (ExportJScop)
331335
PM.add(polly::createJSONExporterPass());
332336

333-
if (Target == TARGET_GPU) {
334-
#ifdef GPU_CODEGEN
335-
PM.add(
336-
polly::createPPCGCodeGenerationPass(GPUArchChoice, GPURuntimeChoice));
337-
#endif
338-
} else {
337+
if (Target == TARGET_CPU || Target == TARGET_HYBRID)
339338
switch (CodeGeneration) {
340339
case CODEGEN_AST:
341340
PM.add(polly::createIslAstInfoWrapperPassPass());
@@ -346,7 +345,11 @@ void registerPollyPasses(llvm::legacy::PassManagerBase &PM) {
346345
case CODEGEN_NONE:
347346
break;
348347
}
349-
}
348+
#ifdef GPU_CODEGEN
349+
else
350+
PM.add(
351+
polly::createPPCGCodeGenerationPass(GPUArchChoice, GPURuntimeChoice));
352+
#endif
350353

351354
// FIXME: This dummy ModulePass keeps some programs from miscompiling,
352355
// probably some not correctly preserved analyses. It acts as a barrier to

‎polly/lib/Transform/ScheduleOptimizer.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1443,6 +1443,10 @@ char IslScheduleOptimizer::ID = 0;
14431443

14441444
bool IslScheduleOptimizer::runOnScop(Scop &S) {
14451445

1446+
// Skip SCoPs in case they're already optimised by PPCGCodeGeneration
1447+
if (S.isToBeSkipped())
1448+
return false;
1449+
14461450
// Skip empty SCoPs but still allow code generation as it will delete the
14471451
// loops present but not needed.
14481452
if (S.getSize() == 0) {

0 commit comments

Comments
 (0)
Please sign in to comment.