mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-04 01:11:44 +00:00
[coroutines] Part 3 of N: Adding Boilerplate for Coroutine Passes
This adds boilerplate code for all coroutine passes, the passes are no-ops for now. Also, a small test has been added to verify that passes execute in the expected order or not at all if coroutine support is disabled. Patch by Gor Nishanov! Differential Revision: https://reviews.llvm.org/D22847 llvm-svn: 277033
This commit is contained in:
parent
333fbe947a
commit
618a29cbe1
@ -1177,8 +1177,8 @@ earlier passes.
|
||||
Upstreaming sequence (rough plan)
|
||||
=================================
|
||||
#. Add documentation.
|
||||
#. Add coroutine intrinsics. <= we are here
|
||||
#. Add empty coroutine passes.
|
||||
#. Add coroutine intrinsics.
|
||||
#. Add empty coroutine passes. <= we are here
|
||||
#. Add coroutine devirtualization + tests.
|
||||
#. Add CGSCC restart trigger + tests.
|
||||
#. Add coroutine heap elision + tests.
|
||||
|
@ -46,6 +46,9 @@ void initializeInstrumentation(PassRegistry&);
|
||||
/// Initialize all passes linked into the Analysis library.
|
||||
void initializeAnalysis(PassRegistry&);
|
||||
|
||||
/// Initialize all passes linked into the Coroutines library.
|
||||
void initializeCoroutines(PassRegistry&);
|
||||
|
||||
/// Initialize all passes linked into the CodeGen library.
|
||||
void initializeCodeGen(PassRegistry&);
|
||||
|
||||
|
38
include/llvm/Transforms/Coroutines.h
Normal file
38
include/llvm/Transforms/Coroutines.h
Normal file
@ -0,0 +1,38 @@
|
||||
//===-- Coroutines.h - Coroutine Transformations ----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Declare accessor functions for coroutine lowering passes.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TRANSFORMS_COROUTINES_H
|
||||
#define LLVM_TRANSFORMS_COROUTINES_H
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Pass;
|
||||
class PassManagerBuilder;
|
||||
|
||||
/// Add all coroutine passes to appropriate extension points.
|
||||
void addCoroutinePassesToExtensionPoints(PassManagerBuilder &Builder);
|
||||
|
||||
/// Lower coroutine intrinsics that are not needed by later passes.
|
||||
Pass *createCoroEarlyPass();
|
||||
|
||||
/// Split up coroutines into multiple functions driving their state machines.
|
||||
Pass *createCoroSplitPass();
|
||||
|
||||
/// Analyze coroutines use sites, devirtualize resume/destroy calls and elide
|
||||
/// heap allocation for coroutine frame where possible.
|
||||
Pass *createCoroElidePass();
|
||||
|
||||
/// Lower all remaining coroutine intrinsics.
|
||||
Pass *createCoroCleanupPass();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -6,3 +6,4 @@ add_subdirectory(IPO)
|
||||
add_subdirectory(Vectorize)
|
||||
add_subdirectory(Hello)
|
||||
add_subdirectory(ObjCARC)
|
||||
add_subdirectory(Coroutines)
|
||||
|
8
lib/Transforms/Coroutines/CMakeLists.txt
Normal file
8
lib/Transforms/Coroutines/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
add_llvm_library(LLVMCoroutines
|
||||
Coroutines.cpp
|
||||
CoroCleanup.cpp
|
||||
CoroEarly.cpp
|
||||
CoroElide.cpp
|
||||
CoroSplit.cpp
|
||||
)
|
||||
|
42
lib/Transforms/Coroutines/CoroCleanup.cpp
Normal file
42
lib/Transforms/Coroutines/CoroCleanup.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
//===- CoroCleanup.cpp - Coroutine Cleanup Pass ---------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This pass lowers all remaining coroutine intrinsics.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CoroInternal.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "coro-cleanup"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Top Level Driver
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
struct CoroCleanup : FunctionPass {
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
|
||||
CoroCleanup() : FunctionPass(ID) {}
|
||||
|
||||
bool runOnFunction(Function &F) override { return false; }
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
char CoroCleanup::ID = 0;
|
||||
INITIALIZE_PASS(CoroCleanup, "coro-cleanup",
|
||||
"Lower all coroutine related intrinsics", false, false)
|
||||
|
||||
Pass *llvm::createCoroCleanupPass() { return new CoroCleanup(); }
|
43
lib/Transforms/Coroutines/CoroEarly.cpp
Normal file
43
lib/Transforms/Coroutines/CoroEarly.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
//===- CoroEarly.cpp - Coroutine Early Function Pass ----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This pass lowers coroutine intrinsics that hide the details of the exact
|
||||
// calling convention for coroutine resume and destroy functions and details of
|
||||
// the structure of the coroutine frame.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CoroInternal.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "coro-early"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Top Level Driver
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
struct CoroEarly : public FunctionPass {
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
CoroEarly() : FunctionPass(ID) {}
|
||||
|
||||
bool runOnFunction(Function &F) override { return false; }
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
char CoroEarly::ID = 0;
|
||||
INITIALIZE_PASS(CoroEarly, "coro-early", "Lower early coroutine intrinsics",
|
||||
false, false)
|
||||
|
||||
Pass *llvm::createCoroEarlyPass() { return new CoroEarly(); }
|
49
lib/Transforms/Coroutines/CoroElide.cpp
Normal file
49
lib/Transforms/Coroutines/CoroElide.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
//===- CoroElide.cpp - Coroutine Frame Allocation Elision Pass ------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This pass replaces dynamic allocation of coroutine frame with alloca and
|
||||
// replaces calls to llvm.coro.resume and llvm.coro.destroy with direct calls
|
||||
// to coroutine sub-functions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CoroInternal.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "coro-elide"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Top Level Driver
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
struct CoroElide : FunctionPass {
|
||||
static char ID;
|
||||
CoroElide() : FunctionPass(ID) {}
|
||||
bool runOnFunction(Function &F) override { return false; }
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
char CoroElide::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(
|
||||
CoroElide, "coro-elide",
|
||||
"Coroutine frame allocation elision and indirect calls replacement", false,
|
||||
false)
|
||||
INITIALIZE_PASS_END(
|
||||
CoroElide, "coro-elide",
|
||||
"Coroutine frame allocation elision and indirect calls replacement", false,
|
||||
false)
|
||||
|
||||
Pass *llvm::createCoroElidePass() { return new CoroElide(); }
|
28
lib/Transforms/Coroutines/CoroInternal.h
Normal file
28
lib/Transforms/Coroutines/CoroInternal.h
Normal file
@ -0,0 +1,28 @@
|
||||
//===- CoroInternal.h - Internal Coroutine interfaces ---------*- C++ -*---===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Common definitions/declarations used internally by coroutine lowering passes.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TRANSFORMS_COROUTINES_COROINTERNAL_H
|
||||
#define LLVM_LIB_TRANSFORMS_COROUTINES_COROINTERNAL_H
|
||||
|
||||
#include "llvm/Transforms/Coroutines.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class PassRegistry;
|
||||
|
||||
void initializeCoroEarlyPass(PassRegistry &);
|
||||
void initializeCoroSplitPass(PassRegistry &);
|
||||
void initializeCoroElidePass(PassRegistry &);
|
||||
void initializeCoroCleanupPass(PassRegistry &);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
45
lib/Transforms/Coroutines/CoroSplit.cpp
Normal file
45
lib/Transforms/Coroutines/CoroSplit.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
//===- CoroSplit.cpp - Converts a coroutine into a state machine ----------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This pass builds the coroutine frame and outlines resume and destroy parts
|
||||
// of the coroutine into separate functions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CoroInternal.h"
|
||||
#include "llvm/Analysis/CallGraphSCCPass.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "coro-split"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Top Level Driver
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
struct CoroSplit : public CallGraphSCCPass {
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
CoroSplit() : CallGraphSCCPass(ID) {}
|
||||
|
||||
bool runOnSCC(CallGraphSCC &SCC) override { return false; }
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesAll();
|
||||
CallGraphSCCPass::getAnalysisUsage(AU);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
char CoroSplit::ID = 0;
|
||||
INITIALIZE_PASS(
|
||||
CoroSplit, "coro-split",
|
||||
"Split coroutine into a set of functions driving its state machine", false,
|
||||
false)
|
||||
|
||||
Pass *llvm::createCoroSplitPass() { return new CoroSplit(); }
|
68
lib/Transforms/Coroutines/Coroutines.cpp
Normal file
68
lib/Transforms/Coroutines/Coroutines.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
//===-- Coroutines.cpp ----------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This file implements the common infrastructure for Coroutine Passes.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CoroInternal.h"
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
#include "llvm/IR/Verifier.h"
|
||||
#include "llvm/InitializePasses.h"
|
||||
#include "llvm/Transforms/IPO.h"
|
||||
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void llvm::initializeCoroutines(PassRegistry &Registry) {
|
||||
initializeCoroEarlyPass(Registry);
|
||||
initializeCoroSplitPass(Registry);
|
||||
initializeCoroElidePass(Registry);
|
||||
initializeCoroCleanupPass(Registry);
|
||||
}
|
||||
|
||||
static void addCoroutineOpt0Passes(const PassManagerBuilder &Builder,
|
||||
legacy::PassManagerBase &PM) {
|
||||
PM.add(createCoroSplitPass());
|
||||
PM.add(createCoroElidePass());
|
||||
|
||||
PM.add(createBarrierNoopPass());
|
||||
PM.add(createCoroCleanupPass());
|
||||
}
|
||||
|
||||
static void addCoroutineEarlyPasses(const PassManagerBuilder &Builder,
|
||||
legacy::PassManagerBase &PM) {
|
||||
PM.add(createCoroEarlyPass());
|
||||
}
|
||||
|
||||
static void addCoroutineScalarOptimizerPasses(const PassManagerBuilder &Builder,
|
||||
legacy::PassManagerBase &PM) {
|
||||
PM.add(createCoroElidePass());
|
||||
}
|
||||
|
||||
static void addCoroutineSCCPasses(const PassManagerBuilder &Builder,
|
||||
legacy::PassManagerBase &PM) {
|
||||
PM.add(createCoroSplitPass());
|
||||
}
|
||||
|
||||
static void addCoroutineOptimizerLastPasses(const PassManagerBuilder &Builder,
|
||||
legacy::PassManagerBase &PM) {
|
||||
PM.add(createCoroCleanupPass());
|
||||
}
|
||||
|
||||
void llvm::addCoroutinePassesToExtensionPoints(PassManagerBuilder &Builder) {
|
||||
Builder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
|
||||
addCoroutineEarlyPasses);
|
||||
Builder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
||||
addCoroutineOpt0Passes);
|
||||
Builder.addExtension(PassManagerBuilder::EP_CGSCCOptimizerLate,
|
||||
addCoroutineSCCPasses);
|
||||
Builder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate,
|
||||
addCoroutineScalarOptimizerPasses);
|
||||
Builder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
||||
addCoroutineOptimizerLastPasses);
|
||||
}
|
22
lib/Transforms/Coroutines/LLVMBuild.txt
Normal file
22
lib/Transforms/Coroutines/LLVMBuild.txt
Normal file
@ -0,0 +1,22 @@
|
||||
;===- ./lib/Transforms/Coroutines/LLVMBuild.txt ----------------*- Conf -*--===;
|
||||
;
|
||||
; The LLVM Compiler Infrastructure
|
||||
;
|
||||
; This file is distributed under the University of Illinois Open Source
|
||||
; License. See LICENSE.TXT for details.
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
;
|
||||
; This is an LLVMBuild description file for the components in this subdirectory.
|
||||
;
|
||||
; For more information on the LLVMBuild system, please see:
|
||||
;
|
||||
; http://llvm.org/docs/LLVMBuild.html
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[component_0]
|
||||
type = Library
|
||||
name = Coroutines
|
||||
parent = Transforms
|
||||
required_libraries = Analysis Core IPO Scalar Support TransformUtils
|
@ -16,7 +16,7 @@
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[common]
|
||||
subdirectories = IPO InstCombine Instrumentation Scalar Utils Vectorize ObjCARC
|
||||
subdirectories = Coroutines IPO InstCombine Instrumentation Scalar Utils Vectorize ObjCARC
|
||||
|
||||
[component_0]
|
||||
type = Group
|
||||
|
24
test/Transforms/Coroutines/smoketest.ll
Normal file
24
test/Transforms/Coroutines/smoketest.ll
Normal file
@ -0,0 +1,24 @@
|
||||
; Test that all coroutine passes run in the correct order at all optimization
|
||||
; levels and -disable-coroutines removes coroutine passes from the pipeline.
|
||||
;
|
||||
; RUN: opt < %s -disable-output -enable-coroutines -debug-pass=Arguments -O1 2>&1 | FileCheck %s
|
||||
; RUN: opt < %s -disable-output -enable-coroutines -debug-pass=Arguments -O2 2>&1 | FileCheck %s
|
||||
; RUN: opt < %s -disable-output -enable-coroutines -debug-pass=Arguments -O3 2>&1 | FileCheck %s
|
||||
; RUN: opt < %s -disable-output -enable-coroutines -debug-pass=Arguments \
|
||||
; RUN: -coro-early -coro-split -coro-elide -coro-cleanup 2>&1 | FileCheck %s
|
||||
; RUN: opt < %s -disable-output -debug-pass=Arguments 2>&1 \
|
||||
; RUN: | FileCheck %s -check-prefix=NOCORO
|
||||
|
||||
; CHECK: coro-early
|
||||
; CHECK: coro-split
|
||||
; CHECK: coro-elide
|
||||
; CHECK: coro-cleanup
|
||||
|
||||
; NOCORO-NOT: coro-early
|
||||
; NOCORO-NOT: coro-split
|
||||
; NOCORO-NOT: coro-elide
|
||||
; NOCORO-NOT: coro-cleanup
|
||||
|
||||
define void @foo() {
|
||||
ret void
|
||||
}
|
@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS
|
||||
BitWriter
|
||||
CodeGen
|
||||
Core
|
||||
Coroutines
|
||||
IPO
|
||||
IRReader
|
||||
InstCombine
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Support/ToolOutputFile.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Transforms/Coroutines.h"
|
||||
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
||||
#include "llvm/Transforms/Utils/Cloning.h"
|
||||
#include <algorithm>
|
||||
@ -215,6 +216,11 @@ static cl::opt<bool> DiscardValueNames(
|
||||
cl::desc("Discard names from Value (other than GlobalValue)."),
|
||||
cl::init(false), cl::Hidden);
|
||||
|
||||
static cl::opt<bool> Coroutines(
|
||||
"enable-coroutines",
|
||||
cl::desc("Enable coroutine passes."),
|
||||
cl::init(false), cl::Hidden);
|
||||
|
||||
static cl::opt<bool> PassRemarksWithHotness(
|
||||
"pass-remarks-with-hotness",
|
||||
cl::desc("With PGO, include profile count in optimization remarks"),
|
||||
@ -274,6 +280,9 @@ static void AddOptimizationPasses(legacy::PassManagerBase &MPM,
|
||||
TM->addEarlyAsPossiblePasses(PM);
|
||||
});
|
||||
|
||||
if (Coroutines)
|
||||
addCoroutinePassesToExtensionPoints(Builder);
|
||||
|
||||
Builder.populateFunctionPassManager(FPM);
|
||||
Builder.populateModulePassManager(MPM);
|
||||
}
|
||||
@ -348,6 +357,7 @@ int main(int argc, char **argv) {
|
||||
// Initialize passes
|
||||
PassRegistry &Registry = *PassRegistry::getPassRegistry();
|
||||
initializeCore(Registry);
|
||||
initializeCoroutines(Registry);
|
||||
initializeScalarOpts(Registry);
|
||||
initializeObjCARCOpts(Registry);
|
||||
initializeVectorization(Registry);
|
||||
|
Loading…
Reference in New Issue
Block a user