summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Coroutines
diff options
context:
space:
mode:
authorGor Nishanov <GorNishanov@gmail.com>2019-05-13 23:58:24 +0000
committerGor Nishanov <GorNishanov@gmail.com>2019-05-13 23:58:24 +0000
commitd64455cd431bce37d15acca4e2de2829180fe12c (patch)
tree3f53786cfee597906a8ef18796a3023c15e1b22c /llvm/lib/Transforms/Coroutines
parent921f132a0f609154fa3a2c419b0119f7bf32ba96 (diff)
downloadbcm5719-llvm-d64455cd431bce37d15acca4e2de2829180fe12c.tar.gz
bcm5719-llvm-d64455cd431bce37d15acca4e2de2829180fe12c.zip
[coroutines] Fix spills of static array allocas
Summary: CoroFrame was not considering static array allocas, and was only ever reserving a single element in the coroutine frame. This meant that stores to the non-zero'th element would corrupt later frame data. Store static array allocas as field arrays in the coroutine frame. Added test. Committed by Gor Nishanov on behalf of ben-clayton Reviewers: GorNishanov, modocache Reviewed By: GorNishanov Subscribers: Orlando, capn, EricWF, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D61372 llvm-svn: 360636
Diffstat (limited to 'llvm/lib/Transforms/Coroutines')
-rw-r--r--llvm/lib/Transforms/Coroutines/CoroFrame.cpp45
1 files changed, 39 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
index 24d685b7113..98f6ca24f97 100644
--- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
@@ -402,6 +402,7 @@ static StructType *buildFrameType(Function &F, coro::Shape &Shape,
if (CurrentDef == Shape.PromiseAlloca)
continue;
+ uint64_t Count = 1;
Type *Ty = nullptr;
if (auto *AI = dyn_cast<AllocaInst>(CurrentDef)) {
Ty = AI->getAllocatedType();
@@ -413,11 +414,18 @@ static StructType *buildFrameType(Function &F, coro::Shape &Shape,
Padder.addType(PaddingTy);
}
}
+ if (auto *CI = dyn_cast<ConstantInt>(AI->getArraySize()))
+ Count = CI->getValue().getZExtValue();
+ else
+ report_fatal_error("Coroutines cannot handle non static allocas yet");
} else {
Ty = CurrentDef->getType();
}
S.setFieldIndex(Types.size());
- Types.push_back(Ty);
+ if (Count == 1)
+ Types.push_back(Ty);
+ else
+ Types.push_back(ArrayType::get(Ty, Count));
Padder.addType(Ty);
}
FrameTy->setBody(Types);
@@ -470,6 +478,7 @@ static Instruction *splitBeforeCatchSwitch(CatchSwitchInst *CatchSwitch) {
//
static Instruction *insertSpills(SpillInfo &Spills, coro::Shape &Shape) {
auto *CB = Shape.CoroBegin;
+ LLVMContext &C = CB->getContext();
IRBuilder<> Builder(CB->getNextNode());
StructType *FrameTy = Shape.FrameTy;
PointerType *FramePtrTy = FrameTy->getPointerTo();
@@ -491,14 +500,38 @@ static Instruction *insertSpills(SpillInfo &Spills, coro::Shape &Shape) {
if (Shape.PromiseAlloca)
Allocas.emplace_back(Shape.PromiseAlloca, coro::Shape::PromiseField);
+ // Create a GEP with the given index into the coroutine frame for the original
+ // value Orig. Appends an extra 0 index for array-allocas, preserving the
+ // original type.
+ auto GetFramePointer = [&](uint32_t Index, Value *Orig) -> Value * {
+ SmallVector<Value *, 3> Indices = {
+ ConstantInt::get(Type::getInt32Ty(C), 0),
+ ConstantInt::get(Type::getInt32Ty(C), Index),
+ };
+
+ if (auto *AI = dyn_cast<AllocaInst>(Orig)) {
+ if (auto *CI = dyn_cast<ConstantInt>(AI->getArraySize())) {
+ auto Count = CI->getValue().getZExtValue();
+ if (Count > 1) {
+ Indices.push_back(ConstantInt::get(Type::getInt32Ty(C), 0));
+ }
+ } else {
+ report_fatal_error("Coroutines cannot handle non static allocas yet");
+ }
+ }
+
+ return Builder.CreateInBoundsGEP(FrameTy, FramePtr, Indices);
+ };
+
// Create a load instruction to reload the spilled value from the coroutine
// frame.
auto CreateReload = [&](Instruction *InsertBefore) {
assert(Index && "accessing unassigned field number");
Builder.SetInsertPoint(InsertBefore);
- auto *G = Builder.CreateConstInBoundsGEP2_32(FrameTy, FramePtr, 0, Index,
- CurrentValue->getName() +
- Twine(".reload.addr"));
+
+ auto *G = GetFramePointer(Index, CurrentValue);
+ G->setName(CurrentValue->getName() + Twine(".reload.addr"));
+
return isa<AllocaInst>(CurrentValue)
? G
: Builder.CreateLoad(FrameTy->getElementType(Index), G,
@@ -588,8 +621,8 @@ static Instruction *insertSpills(SpillInfo &Spills, coro::Shape &Shape) {
Builder.SetInsertPoint(&Shape.AllocaSpillBlock->front());
// If we found any allocas, replace all of their remaining uses with Geps.
for (auto &P : Allocas) {
- auto *G =
- Builder.CreateConstInBoundsGEP2_32(FrameTy, FramePtr, 0, P.second);
+ auto *G = GetFramePointer(P.second, P.first);
+
// We are not using ReplaceInstWithInst(P.first, cast<Instruction>(G)) here,
// as we are changing location of the instruction.
G->takeName(P.first);
OpenPOWER on IntegriCloud