summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorGor Nishanov <GorNishanov@gmail.com>2018-04-02 16:55:12 +0000
committerGor Nishanov <GorNishanov@gmail.com>2018-04-02 16:55:12 +0000
commitb0316d96ae563c8e6473952d3213e833961c81ff (patch)
tree7ff5838f27df91f410829e9b6eb4a277950db45b /llvm/lib
parent49d802862d5edf762928cb2ee159614f31eb2364 (diff)
downloadbcm5719-llvm-b0316d96ae563c8e6473952d3213e833961c81ff.tar.gz
bcm5719-llvm-b0316d96ae563c8e6473952d3213e833961c81ff.zip
[coroutines] Add support for llvm.coro.noop intrinsics
Summary: A recent addition to Coroutines TS (https://wg21.link/p0913) adds a pre-defined coroutine noop_coroutine that does nothing. To implement this feature, we implemented an llvm.coro.noop intrinsic that returns a coroutine handle to a coroutine that does nothing when resumed or destroyed. Reviewers: EricWF, modocache, rnk, lewissbaker Reviewed By: modocache Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D45114 llvm-svn: 328986
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Transforms/Coroutines/CoroEarly.cpp48
-rw-r--r--llvm/lib/Transforms/Coroutines/Coroutines.cpp7
2 files changed, 48 insertions, 7 deletions
diff --git a/llvm/lib/Transforms/Coroutines/CoroEarly.cpp b/llvm/lib/Transforms/Coroutines/CoroEarly.cpp
index ba05896af15..ac47a06281a 100644
--- a/llvm/lib/Transforms/Coroutines/CoroEarly.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroEarly.cpp
@@ -27,10 +27,12 @@ namespace {
class Lowerer : public coro::LowererBase {
IRBuilder<> Builder;
PointerType *const AnyResumeFnPtrTy;
+ Constant *NoopCoro = nullptr;
void lowerResumeOrDestroy(CallSite CS, CoroSubFnInst::ResumeKind);
void lowerCoroPromise(CoroPromiseInst *Intrin);
void lowerCoroDone(IntrinsicInst *II);
+ void lowerCoroNoop(IntrinsicInst *II);
public:
Lowerer(Module &M)
@@ -103,6 +105,41 @@ void Lowerer::lowerCoroDone(IntrinsicInst *II) {
II->eraseFromParent();
}
+void Lowerer::lowerCoroNoop(IntrinsicInst *II) {
+ if (!NoopCoro) {
+ LLVMContext &C = Builder.getContext();
+ Module &M = *II->getModule();
+
+ // Create a noop.frame struct type.
+ StructType *FrameTy = StructType::create(C, "NoopCoro.Frame");
+ auto *FramePtrTy = FrameTy->getPointerTo();
+ auto *FnTy = FunctionType::get(Type::getVoidTy(C), FramePtrTy,
+ /*IsVarArgs=*/false);
+ auto *FnPtrTy = FnTy->getPointerTo();
+ FrameTy->setBody({FnPtrTy, FnPtrTy});
+
+ // Create a Noop function that does nothing.
+ Function *NoopFn =
+ Function::Create(FnTy, GlobalValue::LinkageTypes::PrivateLinkage,
+ "NoopCoro.ResumeDestroy", &M);
+ NoopFn->setCallingConv(CallingConv::Fast);
+ auto *Entry = BasicBlock::Create(C, "entry", NoopFn);
+ ReturnInst::Create(C, Entry);
+
+ // Create a constant struct for the frame.
+ Constant* Values[] = {NoopFn, NoopFn};
+ Constant* NoopCoroConst = ConstantStruct::get(FrameTy, Values);
+ NoopCoro = new GlobalVariable(M, NoopCoroConst->getType(), /*isConstant=*/true,
+ GlobalVariable::PrivateLinkage, NoopCoroConst,
+ "NoopCoro.Frame.Const");
+ }
+
+ Builder.SetInsertPoint(II);
+ auto *NoopCoroVoidPtr = Builder.CreateBitCast(NoopCoro, Int8Ptr);
+ II->replaceAllUsesWith(NoopCoroVoidPtr);
+ II->eraseFromParent();
+}
+
// Prior to CoroSplit, calls to coro.begin needs to be marked as NoDuplicate,
// as CoroSplit assumes there is exactly one coro.begin. After CoroSplit,
// NoDuplicate attribute will be removed from coro.begin otherwise, it will
@@ -138,6 +175,9 @@ bool Lowerer::lowerEarlyIntrinsics(Function &F) {
if (cast<CoroEndInst>(&I)->isFallthrough())
CS.setCannotDuplicate();
break;
+ case Intrinsic::coro_noop:
+ lowerCoroNoop(cast<IntrinsicInst>(&I));
+ break;
case Intrinsic::coro_id:
// Mark a function that comes out of the frontend that has a coro.id
// with a coroutine attribute.
@@ -192,10 +232,10 @@ struct CoroEarly : public FunctionPass {
// This pass has work to do only if we find intrinsics we are going to lower
// in the module.
bool doInitialization(Module &M) override {
- if (coro::declaresIntrinsics(M, {"llvm.coro.id", "llvm.coro.destroy",
- "llvm.coro.done", "llvm.coro.end",
- "llvm.coro.free", "llvm.coro.promise",
- "llvm.coro.resume", "llvm.coro.suspend"}))
+ if (coro::declaresIntrinsics(
+ M, {"llvm.coro.id", "llvm.coro.destroy", "llvm.coro.done",
+ "llvm.coro.end", "llvm.coro.noop", "llvm.coro.free",
+ "llvm.coro.promise", "llvm.coro.resume", "llvm.coro.suspend"}))
L = llvm::make_unique<Lowerer>(M);
return false;
}
diff --git a/llvm/lib/Transforms/Coroutines/Coroutines.cpp b/llvm/lib/Transforms/Coroutines/Coroutines.cpp
index fb09bd4ba44..7723cdfab54 100644
--- a/llvm/lib/Transforms/Coroutines/Coroutines.cpp
+++ b/llvm/lib/Transforms/Coroutines/Coroutines.cpp
@@ -125,9 +125,10 @@ static bool isCoroutineIntrinsicName(StringRef Name) {
static const char *const CoroIntrinsics[] = {
"llvm.coro.alloc", "llvm.coro.begin", "llvm.coro.destroy",
"llvm.coro.done", "llvm.coro.end", "llvm.coro.frame",
- "llvm.coro.free", "llvm.coro.id", "llvm.coro.param",
- "llvm.coro.promise", "llvm.coro.resume", "llvm.coro.save",
- "llvm.coro.size", "llvm.coro.subfn.addr", "llvm.coro.suspend",
+ "llvm.coro.free", "llvm.coro.id", "llvm.coro.noop",
+ "llvm.coro.param", "llvm.coro.promise", "llvm.coro.resume",
+ "llvm.coro.save", "llvm.coro.size", "llvm.coro.subfn.addr",
+ "llvm.coro.suspend",
};
return Intrinsic::lookupLLVMIntrinsicByName(CoroIntrinsics, Name) != -1;
}
OpenPOWER on IntegriCloud