[llvm] r303825 - [coroutines] Relocate instructions that maybe spilled after coro.begin
Gor Nishanov via llvm-commits
llvm-commits at lists.llvm.org
Wed May 24 17:46:20 PDT 2017
Author: gornishanov
Date: Wed May 24 19:46:20 2017
New Revision: 303825
URL: http://llvm.org/viewvc/llvm-project?rev=303825&view=rev
Log:
[coroutines] Relocate instructions that maybe spilled after coro.begin
Summary:
Frontend generates store instructions after allocas, for example:
```
define i8* @f(i64 %this) "coroutine.presplit"="1" personality i32 0 {
entry:
%this.addr = alloca i64
store i64 %this, i64* %this.addr
..
%hdl = call i8* @llvm.coro.begin(token %id, i8* %alloc)
```
Such instructions may require spilling into coro.frame, but, coro-frame address is only available after coro.begin and thus needs to be moved after coro.begin.
The only instructions that should not be moved are the arguments of coro.begin and all of their operands.
Reviewers: GorNishanov, majnemer
Reviewed By: GorNishanov
Subscribers: llvm-commits, EricWF
Differential Revision: https://reviews.llvm.org/D33527
Modified:
llvm/trunk/lib/Transforms/Coroutines/CoroSplit.cpp
llvm/trunk/test/Transforms/Coroutines/coro-frame.ll
Modified: llvm/trunk/lib/Transforms/Coroutines/CoroSplit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Coroutines/CoroSplit.cpp?rev=303825&r1=303824&r2=303825&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Coroutines/CoroSplit.cpp (original)
+++ llvm/trunk/lib/Transforms/Coroutines/CoroSplit.cpp Wed May 24 19:46:20 2017
@@ -509,12 +509,87 @@ static void simplifySuspendPoints(coro::
S.resize(N);
}
+static SmallPtrSet<BasicBlock *, 4> getCoroBeginPredBlocks(CoroBeginInst *CB) {
+ // Collect all blocks that we need to look for instructions to relocate.
+ SmallPtrSet<BasicBlock *, 4> RelocBlocks;
+ SmallVector<BasicBlock *, 4> Work;
+ Work.push_back(CB->getParent());
+
+ do {
+ BasicBlock *Current = Work.pop_back_val();
+ for (BasicBlock *BB : predecessors(Current))
+ if (RelocBlocks.count(BB) == 0) {
+ RelocBlocks.insert(BB);
+ Work.push_back(BB);
+ }
+ } while (!Work.empty());
+ return RelocBlocks;
+}
+
+static SmallPtrSet<Instruction *, 8>
+getNotRelocatableInstructions(CoroBeginInst *CoroBegin,
+ SmallPtrSetImpl<BasicBlock *> &RelocBlocks) {
+ SmallPtrSet<Instruction *, 8> DoNotRelocate;
+ // Collect all instructions that we should not relocate
+ SmallVector<Instruction *, 8> Work;
+
+ // Start with CoroBegin and terminators of all preceding blocks.
+ Work.push_back(CoroBegin);
+ BasicBlock *CoroBeginBB = CoroBegin->getParent();
+ for (BasicBlock *BB : RelocBlocks)
+ if (BB != CoroBeginBB)
+ Work.push_back(BB->getTerminator());
+
+ // For every instruction in the Work list, place its operands in DoNotRelocate
+ // set.
+ do {
+ Instruction *Current = Work.pop_back_val();
+ DoNotRelocate.insert(Current);
+ for (Value *U : Current->operands()) {
+ auto *I = dyn_cast<Instruction>(U);
+ if (!I)
+ continue;
+ if (isa<AllocaInst>(U))
+ continue;
+ if (DoNotRelocate.count(I) == 0) {
+ Work.push_back(I);
+ DoNotRelocate.insert(I);
+ }
+ }
+ } while (!Work.empty());
+ return DoNotRelocate;
+}
+
+static void relocateInstructionBefore(CoroBeginInst *CoroBegin, Function &F) {
+ // Analyze which non-alloca instructions are needed for allocation and
+ // relocate the rest to after coro.begin. We need to do it, since some of the
+ // targets of those instructions may be placed into coroutine frame memory
+ // for which becomes available after coro.begin intrinsic.
+
+ auto BlockSet = getCoroBeginPredBlocks(CoroBegin);
+ auto DoNotRelocateSet = getNotRelocatableInstructions(CoroBegin, BlockSet);
+
+ Instruction *InsertPt = CoroBegin->getNextNode();
+ BasicBlock &BB = F.getEntryBlock(); // TODO: Look at other blocks as well.
+ for (auto B = BB.begin(), E = BB.end(); B != E;) {
+ Instruction &I = *B++;
+ if (isa<AllocaInst>(&I))
+ continue;
+ if (&I == CoroBegin)
+ break;
+ if (DoNotRelocateSet.count(&I))
+ continue;
+ I.moveBefore(InsertPt);
+ }
+}
+
static void splitCoroutine(Function &F, CallGraph &CG, CallGraphSCC &SCC) {
coro::Shape Shape(F);
if (!Shape.CoroBegin)
return;
simplifySuspendPoints(Shape);
+ relocateInstructionBefore(Shape.CoroBegin, F);
buildCoroutineFrame(F, Shape);
replaceFrameSize(Shape);
Modified: llvm/trunk/test/Transforms/Coroutines/coro-frame.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Coroutines/coro-frame.ll?rev=303825&r1=303824&r2=303825&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/Coroutines/coro-frame.ll (original)
+++ llvm/trunk/test/Transforms/Coroutines/coro-frame.ll Wed May 24 19:46:20 2017
@@ -1,8 +1,11 @@
; Check that we can handle spills of the result of the invoke instruction
; RUN: opt < %s -coro-split -S | FileCheck %s
-define i8* @f() "coroutine.presplit"="1" personality i32 0 {
+define i8* @f(i64 %this) "coroutine.presplit"="1" personality i32 0 {
entry:
+ %this.addr = alloca i64
+ store i64 %this, i64* %this.addr
+ %this1 = load i64, i64* %this.addr
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%size = call i32 @llvm.coro.size.i32()
%alloc = call i8* @malloc(i32 %size)
@@ -15,6 +18,7 @@ cont:
i8 1, label %cleanup]
resume:
call double @print(double %r)
+ call void @print2(i64 %this1)
br label %cleanup
cleanup:
@@ -30,12 +34,12 @@ pad:
}
; See if the float was added to the frame
-; CHECK-LABEL: %f.Frame = type { void (%f.Frame*)*, void (%f.Frame*)*, i1, i1, double }
+; CHECK-LABEL: %f.Frame = type { void (%f.Frame*)*, void (%f.Frame*)*, i1, i1, i64, double }
; See if the float was spilled into the frame
; CHECK-LABEL: @f(
; CHECK: %r = call double @print(
-; CHECK: %r.spill.addr = getelementptr inbounds %f.Frame, %f.Frame* %FramePtr, i32 0, i32 4
+; CHECK: %r.spill.addr = getelementptr inbounds %f.Frame, %f.Frame* %FramePtr, i32 0, i32 5
; CHECK: store double %r, double* %r.spill.addr
; CHECK: ret i8* %hdl
@@ -58,4 +62,5 @@ declare i1 @llvm.coro.end(i8*, i1)
declare noalias i8* @malloc(i32)
declare double @print(double)
+declare void @print2(i64)
declare void @free(i8*)
More information about the llvm-commits
mailing list