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 visitInsertElementInst(InsertElementInst &
I) {
188 void visitInsertValueInst(InsertValueInst &
I) {
193 void visitStoreInst(StoreInst &SI) {
198 if (
SI.getValueOperand() !=
U->get())
211 auto IsSimpleStoreThenLoad = [&]() {
219 SmallVector<Instruction *, 4> StoreAliases = {AI};
220 while (!StoreAliases.
empty()) {
222 for (User *U :
I->users()) {
233 if (S->getPointerOperand() ==
I)
250 if (!IsSimpleStoreThenLoad())
255 void visitMemIntrinsic(MemIntrinsic &
MI) { handleMayWrite(
MI); }
257 void visitBitCastInst(BitCastInst &BC) {
262 void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
267 void visitGetElementPtrInst(GetElementPtrInst &GEPI) {
273 void visitIntrinsicInst(IntrinsicInst &
II) {
274 switch (
II.getIntrinsicID()) {
277 case Intrinsic::lifetime_start:
278 LifetimeStarts.insert(&
II);
279 LifetimeStartBBs.push_back(
II.getParent());
281 case Intrinsic::lifetime_end:
282 LifetimeEndBBs.insert(
II.getParent());
287 void visitCallBase(CallBase &CB) {
288 for (
unsigned Op = 0, OpCount = CB.
arg_size();
Op < OpCount; ++
Op)
294 bool getShouldLiveOnFrame()
const {
295 if (!ShouldLiveOnFrame)
296 ShouldLiveOnFrame = computeShouldLiveOnFrame();
297 return *ShouldLiveOnFrame;
300 bool getMayWriteBeforeCoroBegin()
const {
return MayWriteBeforeCoroBegin; }
302 DenseMap<Instruction *, std::optional<APInt>> getAliasesCopy()
const {
303 assert(getShouldLiveOnFrame() &&
"This method should only be called if the "
304 "alloca needs to live on the frame.");
305 for (
const auto &
P : AliasOffetMap)
308 "created before CoroBegin.");
309 return AliasOffetMap;
313 const DominatorTree &DT;
314 const coro::Shape &CoroShape;
315 const SuspendCrossingInfo &Checker;
319 DenseMap<Instruction *, std::optional<APInt>> AliasOffetMap{};
320 SmallPtrSet<Instruction *, 4> Users{};
321 SmallPtrSet<IntrinsicInst *, 2> LifetimeStarts{};
323 SmallPtrSet<BasicBlock *, 2> LifetimeEndBBs{};
324 SmallPtrSet<const BasicBlock *, 2> CoroSuspendBBs{};
325 bool MayWriteBeforeCoroBegin{
false};
326 bool ShouldUseLifetimeStartInfo{
true};
328 mutable std::optional<bool> ShouldLiveOnFrame{};
330 bool computeShouldLiveOnFrame()
const {
335 if (ShouldUseLifetimeStartInfo && !LifetimeStarts.empty()) {
338 if (LifetimeEndBBs.empty())
346 &LifetimeEndBBs, &DT))
353 if (PI.isEscaped()) {
354 for (
auto *
A : LifetimeStarts) {
355 for (
auto *
B : LifetimeStarts) {
356 if (Checker.hasPathOrLoopCrossingSuspendPoint(
A->getParent(),
377 for (
auto *U1 : Users)
378 for (
auto *U2 : Users)
379 if (Checker.isDefinitionAcrossSuspend(*U1, U2))
385 void handleMayWrite(
const Instruction &
I) {
386 if (!DT.dominates(CoroShape.CoroBegin, &
I))
387 MayWriteBeforeCoroBegin =
true;
390 bool usedAfterCoroBegin(Instruction &
I) {
391 for (
auto &U :
I.uses())
392 if (DT.dominates(CoroShape.CoroBegin, U))
397 void handleAlias(Instruction &
I) {
401 if (DT.dominates(CoroShape.CoroBegin, &
I) || !usedAfterCoroBegin(
I))
404 if (!IsOffsetKnown) {
405 AliasOffetMap[&
I].reset();
408 if (!Inserted && Itr->second && *Itr->second !=
Offset) {
432 if (AI->
hasMetadata(LLVMContext::MD_coro_outside_frame))
438 bool ShouldUseLifetimeStartInfo =
442 ShouldUseLifetimeStartInfo};
443 Visitor.visitPtr(*AI);
444 if (!Visitor.getShouldLiveOnFrame())
447 Visitor.getMayWriteBeforeCoroBegin());
454 for (
User *U :
A.users())
503 for (
User *U :
I.users())
506 if (
I.getType()->isTokenTy())
508 "token definition is separated from the use by a suspend point");
520 for (
auto &Iter : Spills) {
521 auto *V = Iter.first;
527 Spills[V].push_back(DVR->Marker->MarkedInstr);
540 auto collectUsers = [&](
Value *Def) {
541 for (
User *U : Def->users()) {
543 if (Inst->getParent() != CoroBegin->
getParent() ||
550 for (
auto &
I : Spills)
551 collectUsers(
I.first);
552 for (
auto &
I : Allocas)
553 collectUsers(
I.Alloca);
556 while (!Worklist.
empty()) {
558 for (
User *U : Def->users()) {
590 Arg->getParent()->removeParamAttr(Arg->getArgNo(), Attribute::Captures);
594 InsertPt = CSI->getParent()->getSingleSuccessor()->getFirstNonPHIIt();
604 auto *NewBB =
SplitEdge(
II->getParent(),
II->getNormalDest());
605 InsertPt = NewBB->getTerminator()->getIterator();
614 assert(!
I->isTerminator() &&
"unexpected terminator");
617 InsertPt =
I->getNextNode()->getIterator();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Prepare AGPR Alloc
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.
void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> 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="", bool Before=false)
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 if the block is well formed or null if the block is not well forme...
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()
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 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)
LLVM_ABI bool isManyPotentiallyReachableFromMany(SmallVectorImpl< BasicBlock * > &Worklist, const SmallPtrSetImpl< const BasicBlock * > &StopSet, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr)
Determine whether there is a potentially a path from at least one block in 'Worklist' to at least one...
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.