diff options
| author | Gor Nishanov <GorNishanov@gmail.com> | 2019-05-13 23:58:24 +0000 |
|---|---|---|
| committer | Gor Nishanov <GorNishanov@gmail.com> | 2019-05-13 23:58:24 +0000 |
| commit | d64455cd431bce37d15acca4e2de2829180fe12c (patch) | |
| tree | 3f53786cfee597906a8ef18796a3023c15e1b22c /llvm/lib/Transforms/Coroutines | |
| parent | 921f132a0f609154fa3a2c419b0119f7bf32ba96 (diff) | |
| download | bcm5719-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.cpp | 45 |
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); |

