summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Coroutines
diff options
context:
space:
mode:
authorGor Nishanov <GorNishanov@gmail.com>2016-09-05 23:45:45 +0000
committerGor Nishanov <GorNishanov@gmail.com>2016-09-05 23:45:45 +0000
commitccabaca2737b54dea1e5020f76b16991733de45e (patch)
tree3b9f4f0ad9689c7687e5a1167a97418069769323 /llvm/lib/Transforms/Coroutines
parenteea2ef7862e0be7368a74b142d5d87f700b02a8d (diff)
downloadbcm5719-llvm-ccabaca2737b54dea1e5020f76b16991733de45e.tar.gz
bcm5719-llvm-ccabaca2737b54dea1e5020f76b16991733de45e.zip
[Coroutines] Part12: Handle alloca address-taken
Summary: Move early uses of spilled variables after CoroBegin. For example, if a parameter had address taken, we may end up with the code like: define @f(i32 %n) { %n.addr = alloca i32 store %n, %n.addr ... call @coro.begin This patch fixes the problem by moving uses of spilled variables after CoroBegin. Reviewers: majnemer Subscribers: mehdi_amini, llvm-commits Differential Revision: https://reviews.llvm.org/D24234 llvm-svn: 280678
Diffstat (limited to 'llvm/lib/Transforms/Coroutines')
-rw-r--r--llvm/lib/Transforms/Coroutines/CoroFrame.cpp47
1 files changed, 46 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
index accffb12ad9..34878aaff62 100644
--- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
@@ -560,6 +560,51 @@ static void rewriteMaterializableInstructions(IRBuilder<> &IRB,
}
}
+// Move early uses of spilled variable after CoroBegin.
+// For example, if a parameter had address taken, we may end up with the code
+// like:
+// define @f(i32 %n) {
+// %n.addr = alloca i32
+// store %n, %n.addr
+// ...
+// call @coro.begin
+// we need to move the store after coro.begin
+static void moveSpillUsesAfterCoroBegin(Function &F, SpillInfo const &Spills,
+ CoroBeginInst *CoroBegin) {
+ DominatorTree DT(F);
+ SmallVector<Instruction *, 8> NeedsMoving;
+
+ Value *CurrentValue = nullptr;
+
+ for (auto const &E : Spills) {
+ if (CurrentValue == E.def())
+ continue;
+
+ CurrentValue = E.def();
+
+ for (User *U : CurrentValue->users()) {
+ Instruction *I = cast<Instruction>(U);
+ if (!DT.dominates(CoroBegin, I)) {
+ // TODO: Make this more robust. Currently if we run into a situation
+ // where simple instruction move won't work we panic and
+ // report_fatal_error.
+ for (User *UI : I->users()) {
+ if (!DT.dominates(CoroBegin, cast<Instruction>(UI)))
+ report_fatal_error("cannot move instruction since its users are not"
+ " dominated by CoroBegin");
+ }
+
+ DEBUG(dbgs() << "will move: " << *I << "\n");
+ NeedsMoving.push_back(I);
+ }
+ }
+ }
+
+ Instruction *InsertPt = CoroBegin->getNextNode();
+ for (Instruction *I : NeedsMoving)
+ I->moveBefore(InsertPt);
+}
+
// Splits the block at a particular instruction unless it is the first
// instruction in the block with a single predecessor.
static BasicBlock *splitBlockIfNotFirst(Instruction *I, const Twine &Name) {
@@ -656,7 +701,7 @@ void coro::buildCoroutineFrame(Function &F, Shape &Shape) {
}
std::sort(Spills.begin(), Spills.end());
DEBUG(dump("Spills", Spills));
-
+ moveSpillUsesAfterCoroBegin(F, Spills, Shape.CoroBegin);
Shape.FrameTy = buildFrameType(F, Shape, Spills);
Shape.FramePtr = insertSpills(Spills, Shape);
}
OpenPOWER on IntegriCloud