diff options
author | Gor Nishanov <GorNishanov@gmail.com> | 2016-09-09 05:39:00 +0000 |
---|---|---|
committer | Gor Nishanov <GorNishanov@gmail.com> | 2016-09-09 05:39:00 +0000 |
commit | faf36c2e0b0dd074727e6b40078d87ed02eed117 (patch) | |
tree | 11b69fdacc51f4f0a348a4ead0247d4f20d34b34 /llvm/lib/Transforms | |
parent | 5f04d819a55a6a9f37216cf13bf5b939d5a48086 (diff) | |
download | bcm5719-llvm-faf36c2e0b0dd074727e6b40078d87ed02eed117.tar.gz bcm5719-llvm-faf36c2e0b0dd074727e6b40078d87ed02eed117.zip |
[Coroutines] Part13: Handle single edge PHINodes across suspends
Summary:
If one of the uses of the value is a single edge PHINode, handle it.
Original:
%val = something
<suspend>
%p = PHINode [%val]
After Spill + Part13:
%val = something
%slot = gep val.spill.slot
store %val, %slot
<suspend>
%p = load %slot
Plus tiny fixes/changes:
* use correct index for coro.free in CoroCleanup
* fixup id parameter in coro.free to allow authoring coroutine in plain C with __builtins
Reviewers: majnemer
Subscribers: mehdi_amini, llvm-commits
Differential Revision: https://reviews.llvm.org/D24242
llvm-svn: 281020
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/Coroutines/CoroCleanup.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Transforms/Coroutines/CoroEarly.cpp | 19 | ||||
-rw-r--r-- | llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 11 |
3 files changed, 28 insertions, 4 deletions
diff --git a/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp b/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp index cd6dbfc1d12..6f11efa0847 100644 --- a/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp @@ -49,7 +49,7 @@ bool Lowerer::lowerRemainingCoroIntrinsics(Function &F) { II->replaceAllUsesWith(II->getArgOperand(1)); break; case Intrinsic::coro_free: - II->replaceAllUsesWith(II->getArgOperand(0)); + II->replaceAllUsesWith(II->getArgOperand(1)); break; case Intrinsic::coro_alloc: II->replaceAllUsesWith(ConstantInt::getTrue(Context)); diff --git a/llvm/lib/Transforms/Coroutines/CoroEarly.cpp b/llvm/lib/Transforms/Coroutines/CoroEarly.cpp index f6dfea72b4a..e8bb0ca99d8 100644 --- a/llvm/lib/Transforms/Coroutines/CoroEarly.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroEarly.cpp @@ -115,12 +115,17 @@ static void setCannotDuplicate(CoroIdInst *CoroId) { bool Lowerer::lowerEarlyIntrinsics(Function &F) { bool Changed = false; + CoroIdInst *CoroId = nullptr; + SmallVector<CoroFreeInst *, 4> CoroFrees; for (auto IB = inst_begin(F), IE = inst_end(F); IB != IE;) { Instruction &I = *IB++; if (auto CS = CallSite(&I)) { switch (CS.getIntrinsicID()) { default: continue; + case Intrinsic::coro_free: + CoroFrees.push_back(cast<CoroFreeInst>(&I)); + break; case Intrinsic::coro_suspend: // Make sure that final suspend point is not duplicated as CoroSplit // pass expects that there is at most one final suspend point. @@ -141,6 +146,7 @@ bool Lowerer::lowerEarlyIntrinsics(Function &F) { F.addFnAttr(CORO_PRESPLIT_ATTR, UNPREPARED_FOR_SPLIT); setCannotDuplicate(CII); CII->setCoroutineSelf(); + CoroId = cast<CoroIdInst>(&I); } } break; @@ -160,6 +166,12 @@ bool Lowerer::lowerEarlyIntrinsics(Function &F) { Changed = true; } } + // Make sure that all CoroFree reference the coro.id intrinsic. + // Token type is not exposed through coroutine C/C++ builtins to plain C, so + // we allow specifying none and fixing it up here. + if (CoroId) + for (CoroFreeInst *CF : CoroFrees) + CF->setArgOperand(0, CoroId); return Changed; } @@ -178,9 +190,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.begin", "llvm.coro.end", - "llvm.coro.resume", "llvm.coro.destroy", - "llvm.coro.done", "llvm.coro.suspend"})) + 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"})) L = llvm::make_unique<Lowerer>(M); return false; } diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp index 34878aaff62..f6e0499a501 100644 --- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -438,6 +438,17 @@ static Instruction *insertSpills(SpillInfo &Spills, coro::Shape &Shape) { CurrentReload = CreateReload(&*CurrentBlock->getFirstInsertionPt()); } + // If we have a single edge PHINode, remove it and replace it with a reload + // from the coroutine frame. (We already took care of multi edge PHINodes + // by rewriting them in the rewritePHIs function). + if (auto *PN = dyn_cast<PHINode>(E.user())) { + assert(PN->getNumIncomingValues() == 1 && "unexpected number of incoming " + "values in the PHINode"); + PN->replaceAllUsesWith(CurrentReload); + PN->eraseFromParent(); + continue; + } + // Replace all uses of CurrentValue in the current instruction with reload. E.user()->replaceUsesOfWith(CurrentValue, CurrentReload); } |