37 if (!VisitedOrFreeBBs.
insert(From).second)
61 VisitedOrFreeBBs.
insert(FI->getParent());
78 U->replaceAllUsesWith(
Alloc);
81 Builder.SetInsertPoint(FI);
148 using Base = PtrUseVisitor<AllocaUseVisitor>;
149 AllocaUseVisitor(
const DataLayout &
DL,
const DominatorTree &DT,
150 const coro::Shape &CoroShape,
151 const SuspendCrossingInfo &Checker,
152 bool ShouldUseLifetimeStartInfo)
153 : PtrUseVisitor(
DL), DT(DT), CoroShape(CoroShape), Checker(Checker),
154 ShouldUseLifetimeStartInfo(ShouldUseLifetimeStartInfo) {
155 for (AnyCoroSuspendInst *SuspendInst : CoroShape.CoroSuspends)
156 CoroSuspendBBs.insert(SuspendInst->
getParent());
159 void visit(Instruction &
I) {
164 if (PI.isEscaped() &&
165 !DT.dominates(CoroShape.CoroBegin, PI.getEscapingInst())) {
166 MayWriteBeforeCoroBegin =
true;
173 void visitPHINode(PHINode &
I) {
178 void visitSelectInst(SelectInst &
I) {
183 void visitCatchPadInst(CatchPadInst &
I) {
186 ShouldLiveOnFrame =
false;
190 void visitInsertElementInst(InsertElementInst &
I) {
195 void visitInsertValueInst(InsertValueInst &
I) {
200 void visitStoreInst(StoreInst &SI) {
205 if (
SI.getValueOperand() !=
U->get())
218 auto IsSimpleStoreThenLoad = [&]() {
226 SmallVector<Instruction *, 4> StoreAliases = {AI};
227 while (!StoreAliases.
empty()) {
229 for (User *U :
I->users()) {
240 if (S->getPointerOperand() ==
I)
257 if (!IsSimpleStoreThenLoad())
262 void visitMemIntrinsic(MemIntrinsic &
MI) { handleMayWrite(
MI); }
264 void visitBitCastInst(BitCastInst &BC) {
269 void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
274 void visitGetElementPtrInst(GetElementPtrInst &GEPI) {
280 void visitIntrinsicInst(IntrinsicInst &
II) {
281 switch (
II.getIntrinsicID()) {
284 case Intrinsic::lifetime_start:
285 LifetimeStarts.insert(&
II);
286 LifetimeStartBBs.push_back(
II.getParent());
288 case Intrinsic::lifetime_end:
289 LifetimeEndBBs.insert(
II.getParent());
294 void visitCallBase(CallBase &CB) {
295 for (
unsigned Op = 0, OpCount = CB.
arg_size();
Op < OpCount; ++
Op)
301 bool getShouldLiveOnFrame()
const {
302 if (!ShouldLiveOnFrame)
303 ShouldLiveOnFrame = computeShouldLiveOnFrame();
304 return *ShouldLiveOnFrame;
307 bool getMayWriteBeforeCoroBegin()
const {
return MayWriteBeforeCoroBegin; }
309 DenseMap<Instruction *, std::optional<APInt>> getAliasesCopy()
const {
310 assert(getShouldLiveOnFrame() &&
"This method should only be called if the "
311 "alloca needs to live on the frame.");
312 for (
const auto &
P : AliasOffetMap)
315 "created before CoroBegin.");
316 return AliasOffetMap;
320 const DominatorTree &DT;
321 const coro::Shape &CoroShape;
322 const SuspendCrossingInfo &Checker;
326 DenseMap<Instruction *, std::optional<APInt>> AliasOffetMap{};
327 SmallPtrSet<Instruction *, 4> Users{};
328 SmallPtrSet<IntrinsicInst *, 2> LifetimeStarts{};
330 SmallPtrSet<BasicBlock *, 2> LifetimeEndBBs{};
331 SmallPtrSet<const BasicBlock *, 2> CoroSuspendBBs{};
332 bool MayWriteBeforeCoroBegin{
false};
333 bool ShouldUseLifetimeStartInfo{
true};
335 mutable std::optional<bool> ShouldLiveOnFrame{};
337 bool computeShouldLiveOnFrame()
const {
342 if (ShouldUseLifetimeStartInfo && !LifetimeStarts.empty()) {
345 if (LifetimeEndBBs.empty())
353 &LifetimeEndBBs, &DT))
360 if (PI.isEscaped()) {
361 for (
auto *
A : LifetimeStarts) {
362 for (
auto *
B : LifetimeStarts) {
363 if (Checker.hasPathOrLoopCrossingSuspendPoint(
A->getParent(),
384 for (
auto *U1 : Users)
385 for (
auto *U2 : Users)
386 if (Checker.isDefinitionAcrossSuspend(*U1, U2))
392 void handleMayWrite(
const Instruction &
I) {
393 if (!DT.dominates(CoroShape.CoroBegin, &
I))
394 MayWriteBeforeCoroBegin =
true;
397 bool usedAfterCoroBegin(Instruction &
I) {
398 for (
auto &U :
I.uses())
399 if (DT.dominates(CoroShape.CoroBegin, U))
404 void handleAlias(Instruction &
I) {
408 if (DT.dominates(CoroShape.CoroBegin, &
I) || !usedAfterCoroBegin(
I))
411 if (!IsOffsetKnown) {
412 AliasOffetMap[&
I].reset();
415 if (!Inserted && Itr->second && *Itr->second !=
Offset) {
439 if (AI->
hasMetadata(LLVMContext::MD_coro_outside_frame))
445 bool ShouldUseLifetimeStartInfo =
449 ShouldUseLifetimeStartInfo};
450 Visitor.visitPtr(*AI);
451 if (!Visitor.getShouldLiveOnFrame())
454 Visitor.getMayWriteBeforeCoroBegin());
461 for (
User *U :
A.users())
510 for (
User *U :
I.users())
513 if (
I.getType()->isTokenTy())
515 "token definition is separated from the use by a suspend point");
527 for (
auto &Iter : Spills) {
528 auto *V = Iter.first;
534 Spills[V].push_back(DVR->Marker->MarkedInstr);
547 auto collectUsers = [&](
Value *Def) {
548 for (
User *U : Def->users()) {
550 if (Inst->getParent() != CoroBegin->
getParent() ||
557 for (
auto &
I : Spills)
558 collectUsers(
I.first);
559 for (
auto &
I : Allocas)
560 collectUsers(
I.Alloca);
563 while (!Worklist.
empty()) {
565 for (
User *U : Def->users()) {
597 Arg->getParent()->removeParamAttr(Arg->getArgNo(), Attribute::Captures);
601 InsertPt = CSI->getParent()->getSingleSuccessor()->getFirstNonPHIIt();
611 auto *NewBB =
SplitEdge(
II->getParent(),
II->getNormalDest());
612 InsertPt = NewBB->getTerminator()->getIterator();
621 assert(!
I->isTerminator() &&
"unexpected terminator");
624 InsertPt =
I->getNextNode()->getIterator();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
uint64_t IntrinsicInst * II
This file provides a collection of visitors which walk the (instruction) uses of a pointer.
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)
static bool isSuspendReachableFrom(BasicBlock *From, VisitedBlocksSet &VisitedOrFreeBBs)
Does control flow starting at the given block ever reach a suspend instruction before reaching a bloc...
static Instruction * splitBeforeCatchSwitch(CatchSwitchInst *CatchSwitch)
static bool isLocalAlloca(CoroAllocaAllocInst *AI)
Is the given alloca "local", i.e.
static bool isNonSpilledIntrinsic(Instruction &I)
static Instruction * lowerNonLocalAlloca(CoroAllocaAllocInst *AI, const Shape &Shape, SmallVectorImpl< Instruction * > &DeadInsts)
Turn the given coro.alloca.alloc call into a dynamic allocation.
SmallPtrSet< BasicBlock *, 8 > VisitedBlocksSet
static void collectFrameAlloca(AllocaInst *AI, const coro::Shape &Shape, const SuspendCrossingInfo &Checker, SmallVectorImpl< AllocaInfo > &Allocas, const DominatorTree &DT)
an instruction to allocate memory on the stack
This class represents an incoming formal argument to a Function.
LLVM Basic Block Representation.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
bool doesNotCapture(unsigned OpNo) const
Determine whether this data operand is not captured.
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
Value * getParentPad() const
static CleanupPadInst * Create(Value *ParentPad, ArrayRef< Value * > Args={}, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
static CleanupReturnInst * Create(Value *CleanupPad, BasicBlock *UnwindBB=nullptr, InsertPosition InsertBefore=nullptr)
This represents the llvm.coro.alloca.alloc instruction.
This class represents the llvm.coro.begin or llvm.coro.begin.custom.abi instructions.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
void visit(Iterator Start, Iterator End)
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI void moveBefore(InstListType::iterator InsertPos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
A base class for visitors over the uses of a pointer value.
void visitGetElementPtrInst(GetElementPtrInst &GEPI)
void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC)
void visitBitCastInst(BitCastInst &BC)
void visitIntrinsicInst(IntrinsicInst &II)
iterator end()
Get an iterator to the end of the SetVector.
iterator begin()
Get an iterator to the beginning of the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool isDefinitionAcrossSuspend(BasicBlock *DefBB, User *U) const
LLVM Value Representation.
iterator_range< user_iterator > users()
SmallVector< UseToVisit, 8 > Worklist
The worklist of to-visit uses.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
SmallMapVector< Value *, SmallVector< Instruction *, 2 >, 8 > SpillInfo
@ Async
The "async continuation" lowering, where each suspend point creates a single continuation function.
@ RetconOnce
The "unique returned-continuation" lowering, where each suspend point creates a single continuation f...
@ Retcon
The "returned-continuation" lowering, where each suspend point creates a single continuation function...
BasicBlock::iterator getSpillInsertionPt(const coro::Shape &, Value *Def, const DominatorTree &DT)
bool isSuspendBlock(BasicBlock *BB)
void sinkSpillUsesAfterCoroBegin(const DominatorTree &DT, CoroBeginInst *CoroBegin, coro::SpillInfo &Spills, SmallVectorImpl< coro::AllocaInfo > &Allocas)
Async and Retcon{Once} conventions assume that all spill uses can be sunk after the coro....
void collectSpillsFromArgs(SpillInfo &Spills, Function &F, const SuspendCrossingInfo &Checker)
void collectSpillsFromDbgInfo(SpillInfo &Spills, Function &F, const SuspendCrossingInfo &Checker)
void collectSpillsAndAllocasFromInsts(SpillInfo &Spills, SmallVector< AllocaInfo, 8 > &Allocas, SmallVector< Instruction *, 4 > &DeadInstructions, SmallVector< CoroAllocaAllocInst *, 4 > &LocalAllocas, Function &F, const SuspendCrossingInfo &Checker, const DominatorTree &DT, const coro::Shape &Shape)
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI bool isManyPotentiallyReachableFromMany(SmallVectorImpl< BasicBlock * > &Worklist, const SmallPtrSetImpl< const BasicBlock * > &StopSet, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr, const CycleInfo *CI=nullptr)
Determine whether there is a potentially a path from at least one block in 'Worklist' to at least one...
LLVM_ABI void findDbgValues(Value *V, SmallVectorImpl< DbgVariableRecord * > &DbgVariableRecords)
Finds the dbg.values describing a value.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI BasicBlock * SplitEdge(BasicBlock *From, BasicBlock *To, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="")
Split the edge connecting the specified blocks, and return the newly created basic block between From...
AllocaInst * PromiseAlloca
SmallVector< AnyCoroSuspendInst *, 4 > CoroSuspends
LLVM_ABI Value * emitAlloc(IRBuilder<> &Builder, Value *Size, CallGraph *CG) const
Allocate memory according to the rules of the active lowering.
SwitchLoweringStorage SwitchLowering
CoroBeginInst * CoroBegin
BasicBlock::iterator getInsertPtAfterFramePtr() const
LLVM_ABI void emitDealloc(IRBuilder<> &Builder, Value *Ptr, CallGraph *CG) const
Deallocate memory according to the rules of the active lowering.