LLVM 21.0.0git
SpillUtils.cpp
Go to the documentation of this file.
1//===- SpillUtils.cpp - Utilities for checking for spills ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "CoroInternal.h"
11#include "llvm/Analysis/CFG.h"
13#include "llvm/IR/CFG.h"
14#include "llvm/IR/DebugInfo.h"
15#include "llvm/IR/Dominators.h"
18
19namespace llvm {
20
21namespace coro {
22
23namespace {
24
25typedef SmallPtrSet<BasicBlock *, 8> VisitedBlocksSet;
26
27// Check for structural coroutine intrinsics that should not be spilled into
28// the coroutine frame.
29static bool isCoroutineStructureIntrinsic(Instruction &I) {
30 return isa<CoroIdInst>(&I) || isa<CoroSaveInst>(&I) ||
31 isa<CoroSuspendInst>(&I);
32}
33
34/// Does control flow starting at the given block ever reach a suspend
35/// instruction before reaching a block in VisitedOrFreeBBs?
36static bool isSuspendReachableFrom(BasicBlock *From,
37 VisitedBlocksSet &VisitedOrFreeBBs) {
38 // Eagerly try to add this block to the visited set. If it's already
39 // there, stop recursing; this path doesn't reach a suspend before
40 // either looping or reaching a freeing block.
41 if (!VisitedOrFreeBBs.insert(From).second)
42 return false;
43
44 // We assume that we'll already have split suspends into their own blocks.
46 return true;
47
48 // Recurse on the successors.
49 for (auto *Succ : successors(From)) {
50 if (isSuspendReachableFrom(Succ, VisitedOrFreeBBs))
51 return true;
52 }
53
54 return false;
55}
56
57/// Is the given alloca "local", i.e. bounded in lifetime to not cross a
58/// suspend point?
59static bool isLocalAlloca(CoroAllocaAllocInst *AI) {
60 // Seed the visited set with all the basic blocks containing a free
61 // so that we won't pass them up.
62 VisitedBlocksSet VisitedOrFreeBBs;
63 for (auto *User : AI->users()) {
64 if (auto FI = dyn_cast<CoroAllocaFreeInst>(User))
65 VisitedOrFreeBBs.insert(FI->getParent());
66 }
67
68 return !isSuspendReachableFrom(AI->getParent(), VisitedOrFreeBBs);
69}
70
71/// Turn the given coro.alloca.alloc call into a dynamic allocation.
72/// This happens during the all-instructions iteration, so it must not
73/// delete the call.
74static Instruction *
75lowerNonLocalAlloca(CoroAllocaAllocInst *AI, const coro::Shape &Shape,
76 SmallVectorImpl<Instruction *> &DeadInsts) {
77 IRBuilder<> Builder(AI);
78 auto Alloc = Shape.emitAlloc(Builder, AI->getSize(), nullptr);
79
80 for (User *U : AI->users()) {
81 if (isa<CoroAllocaGetInst>(U)) {
82 U->replaceAllUsesWith(Alloc);
83 } else {
84 auto FI = cast<CoroAllocaFreeInst>(U);
85 Builder.SetInsertPoint(FI);
86 Shape.emitDealloc(Builder, Alloc, nullptr);
87 }
88 DeadInsts.push_back(cast<Instruction>(U));
89 }
90
91 // Push this on last so that it gets deleted after all the others.
92 DeadInsts.push_back(AI);
93
94 // Return the new allocation value so that we can check for needed spills.
95 return cast<Instruction>(Alloc);
96}
97
98// We need to make room to insert a spill after initial PHIs, but before
99// catchswitch instruction. Placing it before violates the requirement that
100// catchswitch, like all other EHPads must be the first nonPHI in a block.
101//
102// Split away catchswitch into a separate block and insert in its place:
103//
104// cleanuppad <InsertPt> cleanupret.
105//
106// cleanupret instruction will act as an insert point for the spill.
107static Instruction *splitBeforeCatchSwitch(CatchSwitchInst *CatchSwitch) {
108 BasicBlock *CurrentBlock = CatchSwitch->getParent();
109 BasicBlock *NewBlock = CurrentBlock->splitBasicBlock(CatchSwitch);
110 CurrentBlock->getTerminator()->eraseFromParent();
111
112 auto *CleanupPad =
113 CleanupPadInst::Create(CatchSwitch->getParentPad(), {}, "", CurrentBlock);
114 auto *CleanupRet =
115 CleanupReturnInst::Create(CleanupPad, NewBlock, CurrentBlock);
116 return CleanupRet;
117}
118
119// We use a pointer use visitor to track how an alloca is being used.
120// The goal is to be able to answer the following three questions:
121// 1. Should this alloca be allocated on the frame instead.
122// 2. Could the content of the alloca be modified prior to CoroBegin, which
123// would require copying the data from the alloca to the frame after
124// CoroBegin.
125// 3. Are there any aliases created for this alloca prior to CoroBegin, but
126// used after CoroBegin. In that case, we will need to recreate the alias
127// after CoroBegin based off the frame.
128//
129// To answer question 1, we track two things:
130// A. List of all BasicBlocks that use this alloca or any of the aliases of
131// the alloca. In the end, we check if there exists any two basic blocks that
132// cross suspension points. If so, this alloca must be put on the frame.
133// B. Whether the alloca or any alias of the alloca is escaped at some point,
134// either by storing the address somewhere, or the address is used in a
135// function call that might capture. If it's ever escaped, this alloca must be
136// put on the frame conservatively.
137//
138// To answer quetion 2, we track through the variable MayWriteBeforeCoroBegin.
139// Whenever a potential write happens, either through a store instruction, a
140// function call or any of the memory intrinsics, we check whether this
141// instruction is prior to CoroBegin.
142//
143// To answer question 3, we track the offsets of all aliases created for the
144// alloca prior to CoroBegin but used after CoroBegin. std::optional is used to
145// be able to represent the case when the offset is unknown (e.g. when you have
146// a PHINode that takes in different offset values). We cannot handle unknown
147// offsets and will assert. This is the potential issue left out. An ideal
148// solution would likely require a significant redesign.
149
150namespace {
151struct AllocaUseVisitor : PtrUseVisitor<AllocaUseVisitor> {
152 using Base = PtrUseVisitor<AllocaUseVisitor>;
153 AllocaUseVisitor(const DataLayout &DL, const DominatorTree &DT,
154 const coro::Shape &CoroShape,
155 const SuspendCrossingInfo &Checker,
156 bool ShouldUseLifetimeStartInfo)
157 : PtrUseVisitor(DL), DT(DT), CoroShape(CoroShape), Checker(Checker),
158 ShouldUseLifetimeStartInfo(ShouldUseLifetimeStartInfo) {
159 for (AnyCoroSuspendInst *SuspendInst : CoroShape.CoroSuspends)
160 CoroSuspendBBs.insert(SuspendInst->getParent());
161 }
162
163 void visit(Instruction &I) {
164 Users.insert(&I);
165 Base::visit(I);
166 // If the pointer is escaped prior to CoroBegin, we have to assume it would
167 // be written into before CoroBegin as well.
168 if (PI.isEscaped() &&
169 !DT.dominates(CoroShape.CoroBegin, PI.getEscapingInst())) {
170 MayWriteBeforeCoroBegin = true;
171 }
172 }
173 // We need to provide this overload as PtrUseVisitor uses a pointer based
174 // visiting function.
175 void visit(Instruction *I) { return visit(*I); }
176
177 void visitPHINode(PHINode &I) {
178 enqueueUsers(I);
179 handleAlias(I);
180 }
181
182 void visitSelectInst(SelectInst &I) {
183 enqueueUsers(I);
184 handleAlias(I);
185 }
186
187 void visitStoreInst(StoreInst &SI) {
188 // Regardless whether the alias of the alloca is the value operand or the
189 // pointer operand, we need to assume the alloca is been written.
190 handleMayWrite(SI);
191
192 if (SI.getValueOperand() != U->get())
193 return;
194
195 // We are storing the pointer into a memory location, potentially escaping.
196 // As an optimization, we try to detect simple cases where it doesn't
197 // actually escape, for example:
198 // %ptr = alloca ..
199 // %addr = alloca ..
200 // store %ptr, %addr
201 // %x = load %addr
202 // ..
203 // If %addr is only used by loading from it, we could simply treat %x as
204 // another alias of %ptr, and not considering %ptr being escaped.
205 auto IsSimpleStoreThenLoad = [&]() {
206 auto *AI = dyn_cast<AllocaInst>(SI.getPointerOperand());
207 // If the memory location we are storing to is not an alloca, it
208 // could be an alias of some other memory locations, which is difficult
209 // to analyze.
210 if (!AI)
211 return false;
212 // StoreAliases contains aliases of the memory location stored into.
213 SmallVector<Instruction *, 4> StoreAliases = {AI};
214 while (!StoreAliases.empty()) {
215 Instruction *I = StoreAliases.pop_back_val();
216 for (User *U : I->users()) {
217 // If we are loading from the memory location, we are creating an
218 // alias of the original pointer.
219 if (auto *LI = dyn_cast<LoadInst>(U)) {
220 enqueueUsers(*LI);
221 handleAlias(*LI);
222 continue;
223 }
224 // If we are overriding the memory location, the pointer certainly
225 // won't escape.
226 if (auto *S = dyn_cast<StoreInst>(U))
227 if (S->getPointerOperand() == I)
228 continue;
229 if (isa<LifetimeIntrinsic>(U))
230 continue;
231 // BitCastInst creats aliases of the memory location being stored
232 // into.
233 if (auto *BI = dyn_cast<BitCastInst>(U)) {
234 StoreAliases.push_back(BI);
235 continue;
236 }
237 return false;
238 }
239 }
240
241 return true;
242 };
243
244 if (!IsSimpleStoreThenLoad())
245 PI.setEscaped(&SI);
246 }
247
248 // All mem intrinsics modify the data.
249 void visitMemIntrinsic(MemIntrinsic &MI) { handleMayWrite(MI); }
250
251 void visitBitCastInst(BitCastInst &BC) {
252 Base::visitBitCastInst(BC);
253 handleAlias(BC);
254 }
255
256 void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
257 Base::visitAddrSpaceCastInst(ASC);
258 handleAlias(ASC);
259 }
260
261 void visitGetElementPtrInst(GetElementPtrInst &GEPI) {
262 // The base visitor will adjust Offset accordingly.
263 Base::visitGetElementPtrInst(GEPI);
264 handleAlias(GEPI);
265 }
266
267 void visitIntrinsicInst(IntrinsicInst &II) {
268 // When we found the lifetime markers refers to a
269 // subrange of the original alloca, ignore the lifetime
270 // markers to avoid misleading the analysis.
271 if (!IsOffsetKnown || !Offset.isZero())
272 return Base::visitIntrinsicInst(II);
273 switch (II.getIntrinsicID()) {
274 default:
275 return Base::visitIntrinsicInst(II);
276 case Intrinsic::lifetime_start:
277 LifetimeStarts.insert(&II);
278 LifetimeStartBBs.push_back(II.getParent());
279 break;
280 case Intrinsic::lifetime_end:
281 LifetimeEndBBs.insert(II.getParent());
282 break;
283 }
284 }
285
286 void visitCallBase(CallBase &CB) {
287 for (unsigned Op = 0, OpCount = CB.arg_size(); Op < OpCount; ++Op)
288 if (U->get() == CB.getArgOperand(Op) && !CB.doesNotCapture(Op))
289 PI.setEscaped(&CB);
290 handleMayWrite(CB);
291 }
292
293 bool getShouldLiveOnFrame() const {
294 if (!ShouldLiveOnFrame)
295 ShouldLiveOnFrame = computeShouldLiveOnFrame();
296 return *ShouldLiveOnFrame;
297 }
298
299 bool getMayWriteBeforeCoroBegin() const { return MayWriteBeforeCoroBegin; }
300
301 DenseMap<Instruction *, std::optional<APInt>> getAliasesCopy() const {
302 assert(getShouldLiveOnFrame() && "This method should only be called if the "
303 "alloca needs to live on the frame.");
304 for (const auto &P : AliasOffetMap)
305 if (!P.second)
306 report_fatal_error("Unable to handle an alias with unknown offset "
307 "created before CoroBegin.");
308 return AliasOffetMap;
309 }
310
311private:
312 const DominatorTree &DT;
313 const coro::Shape &CoroShape;
314 const SuspendCrossingInfo &Checker;
315 // All alias to the original AllocaInst, created before CoroBegin and used
316 // after CoroBegin. Each entry contains the instruction and the offset in the
317 // original Alloca. They need to be recreated after CoroBegin off the frame.
318 DenseMap<Instruction *, std::optional<APInt>> AliasOffetMap{};
319 SmallPtrSet<Instruction *, 4> Users{};
320 SmallPtrSet<IntrinsicInst *, 2> LifetimeStarts{};
321 SmallVector<BasicBlock *> LifetimeStartBBs{};
322 SmallPtrSet<BasicBlock *, 2> LifetimeEndBBs{};
323 SmallPtrSet<const BasicBlock *, 2> CoroSuspendBBs{};
324 bool MayWriteBeforeCoroBegin{false};
325 bool ShouldUseLifetimeStartInfo{true};
326
327 mutable std::optional<bool> ShouldLiveOnFrame{};
328
329 bool computeShouldLiveOnFrame() const {
330 // If lifetime information is available, we check it first since it's
331 // more precise. We look at every pair of lifetime.start intrinsic and
332 // every basic block that uses the pointer to see if they cross suspension
333 // points. The uses cover both direct uses as well as indirect uses.
334 if (ShouldUseLifetimeStartInfo && !LifetimeStarts.empty()) {
335 // If there is no explicit lifetime.end, then assume the address can
336 // cross suspension points.
337 if (LifetimeEndBBs.empty())
338 return true;
339
340 // If there is a path from a lifetime.start to a suspend without a
341 // corresponding lifetime.end, then the alloca's lifetime persists
342 // beyond that suspension point and the alloca must go on the frame.
343 llvm::SmallVector<BasicBlock *> Worklist(LifetimeStartBBs);
344 if (isManyPotentiallyReachableFromMany(Worklist, CoroSuspendBBs,
345 &LifetimeEndBBs, &DT))
346 return true;
347
348 // Addresses are guaranteed to be identical after every lifetime.start so
349 // we cannot use the local stack if the address escaped and there is a
350 // suspend point between lifetime markers. This should also cover the
351 // case of a single lifetime.start intrinsic in a loop with suspend point.
352 if (PI.isEscaped()) {
353 for (auto *A : LifetimeStarts) {
354 for (auto *B : LifetimeStarts) {
355 if (Checker.hasPathOrLoopCrossingSuspendPoint(A->getParent(),
356 B->getParent()))
357 return true;
358 }
359 }
360 }
361 return false;
362 }
363 // FIXME: Ideally the isEscaped check should come at the beginning.
364 // However there are a few loose ends that need to be fixed first before
365 // we can do that. We need to make sure we are not over-conservative, so
366 // that the data accessed in-between await_suspend and symmetric transfer
367 // is always put on the stack, and also data accessed after coro.end is
368 // always put on the stack (esp the return object). To fix that, we need
369 // to:
370 // 1) Potentially treat sret as nocapture in calls
371 // 2) Special handle the return object and put it on the stack
372 // 3) Utilize lifetime.end intrinsic
373 if (PI.isEscaped())
374 return true;
375
376 for (auto *U1 : Users)
377 for (auto *U2 : Users)
378 if (Checker.isDefinitionAcrossSuspend(*U1, U2))
379 return true;
380
381 return false;
382 }
383
384 void handleMayWrite(const Instruction &I) {
385 if (!DT.dominates(CoroShape.CoroBegin, &I))
386 MayWriteBeforeCoroBegin = true;
387 }
388
389 bool usedAfterCoroBegin(Instruction &I) {
390 for (auto &U : I.uses())
391 if (DT.dominates(CoroShape.CoroBegin, U))
392 return true;
393 return false;
394 }
395
396 void handleAlias(Instruction &I) {
397 // We track all aliases created prior to CoroBegin but used after.
398 // These aliases may need to be recreated after CoroBegin if the alloca
399 // need to live on the frame.
400 if (DT.dominates(CoroShape.CoroBegin, &I) || !usedAfterCoroBegin(I))
401 return;
402
403 if (!IsOffsetKnown) {
404 AliasOffetMap[&I].reset();
405 } else {
406 auto [Itr, Inserted] = AliasOffetMap.try_emplace(&I, Offset);
407 if (!Inserted && Itr->second && *Itr->second != Offset) {
408 // If we have seen two different possible values for this alias, we set
409 // it to empty.
410 Itr->second.reset();
411 }
412 }
413 }
414};
415} // namespace
416
417static void collectFrameAlloca(AllocaInst *AI, const coro::Shape &Shape,
418 const SuspendCrossingInfo &Checker,
419 SmallVectorImpl<AllocaInfo> &Allocas,
420 const DominatorTree &DT) {
421 if (Shape.CoroSuspends.empty())
422 return;
423
424 // The PromiseAlloca will be specially handled since it needs to be in a
425 // fixed position in the frame.
426 if (AI == Shape.SwitchLowering.PromiseAlloca)
427 return;
428
429 // The __coro_gro alloca should outlive the promise, make sure we
430 // keep it outside the frame.
431 if (AI->hasMetadata(LLVMContext::MD_coro_outside_frame))
432 return;
433
434 // The code that uses lifetime.start intrinsic does not work for functions
435 // with loops without exit. Disable it on ABIs we know to generate such
436 // code.
437 bool ShouldUseLifetimeStartInfo =
438 (Shape.ABI != coro::ABI::Async && Shape.ABI != coro::ABI::Retcon &&
439 Shape.ABI != coro::ABI::RetconOnce);
440 AllocaUseVisitor Visitor{AI->getDataLayout(), DT, Shape, Checker,
441 ShouldUseLifetimeStartInfo};
442 Visitor.visitPtr(*AI);
443 if (!Visitor.getShouldLiveOnFrame())
444 return;
445 Allocas.emplace_back(AI, Visitor.getAliasesCopy(),
446 Visitor.getMayWriteBeforeCoroBegin());
447}
448
449} // namespace
450
452 const SuspendCrossingInfo &Checker) {
453 // Collect the spills for arguments and other not-materializable values.
454 for (Argument &A : F.args())
455 for (User *U : A.users())
456 if (Checker.isDefinitionAcrossSuspend(A, U))
457 Spills[&A].push_back(cast<Instruction>(U));
458}
459
461 SpillInfo &Spills, SmallVector<AllocaInfo, 8> &Allocas,
462 SmallVector<Instruction *, 4> &DeadInstructions,
464 const SuspendCrossingInfo &Checker, const DominatorTree &DT,
465 const coro::Shape &Shape) {
466
467 for (Instruction &I : instructions(F)) {
468 // Values returned from coroutine structure intrinsics should not be part
469 // of the Coroutine Frame.
470 if (isCoroutineStructureIntrinsic(I) || &I == Shape.CoroBegin)
471 continue;
472
473 // Handle alloca.alloc specially here.
474 if (auto AI = dyn_cast<CoroAllocaAllocInst>(&I)) {
475 // Check whether the alloca's lifetime is bounded by suspend points.
476 if (isLocalAlloca(AI)) {
477 LocalAllocas.push_back(AI);
478 continue;
479 }
480
481 // If not, do a quick rewrite of the alloca and then add spills of
482 // the rewritten value. The rewrite doesn't invalidate anything in
483 // Spills because the other alloca intrinsics have no other operands
484 // besides AI, and it doesn't invalidate the iteration because we delay
485 // erasing AI.
486 auto Alloc = lowerNonLocalAlloca(AI, Shape, DeadInstructions);
487
488 for (User *U : Alloc->users()) {
489 if (Checker.isDefinitionAcrossSuspend(*Alloc, U))
490 Spills[Alloc].push_back(cast<Instruction>(U));
491 }
492 continue;
493 }
494
495 // Ignore alloca.get; we process this as part of coro.alloca.alloc.
496 if (isa<CoroAllocaGetInst>(I))
497 continue;
498
499 if (auto *AI = dyn_cast<AllocaInst>(&I)) {
500 collectFrameAlloca(AI, Shape, Checker, Allocas, DT);
501 continue;
502 }
503
504 for (User *U : I.users())
505 if (Checker.isDefinitionAcrossSuspend(I, U)) {
506 // We cannot spill a token.
507 if (I.getType()->isTokenTy())
509 "token definition is separated from the use by a suspend point");
510 Spills[&I].push_back(cast<Instruction>(U));
511 }
512 }
513}
514
516 const SuspendCrossingInfo &Checker) {
517 // We don't want the layout of coroutine frame to be affected
518 // by debug information. So we only choose to salvage DbgValueInst for
519 // whose value is already in the frame.
520 // We would handle the dbg.values for allocas specially
521 for (auto &Iter : Spills) {
522 auto *V = Iter.first;
525 findDbgValues(DVIs, V, &DVRs);
526 for (DbgValueInst *DVI : DVIs)
527 if (Checker.isDefinitionAcrossSuspend(*V, DVI))
528 Spills[V].push_back(DVI);
529 // Add the instructions which carry debug info that is in the frame.
530 for (DbgVariableRecord *DVR : DVRs)
531 if (Checker.isDefinitionAcrossSuspend(*V, DVR->Marker->MarkedInstr))
532 Spills[V].push_back(DVR->Marker->MarkedInstr);
533 }
534}
535
536/// Async and Retcon{Once} conventions assume that all spill uses can be sunk
537/// after the coro.begin intrinsic.
539 CoroBeginInst *CoroBegin,
540 coro::SpillInfo &Spills,
544
545 // Collect all users that precede coro.begin.
546 auto collectUsers = [&](Value *Def) {
547 for (User *U : Def->users()) {
548 auto Inst = cast<Instruction>(U);
549 if (Inst->getParent() != CoroBegin->getParent() ||
550 Dom.dominates(CoroBegin, Inst))
551 continue;
552 if (ToMove.insert(Inst))
553 Worklist.push_back(Inst);
554 }
555 };
556 std::for_each(Spills.begin(), Spills.end(),
557 [&](auto &I) { collectUsers(I.first); });
558 std::for_each(Allocas.begin(), Allocas.end(),
559 [&](auto &I) { collectUsers(I.Alloca); });
560
561 // Recursively collect users before coro.begin.
562 while (!Worklist.empty()) {
563 auto *Def = Worklist.pop_back_val();
564 for (User *U : Def->users()) {
565 auto Inst = cast<Instruction>(U);
566 if (Dom.dominates(CoroBegin, Inst))
567 continue;
568 if (ToMove.insert(Inst))
569 Worklist.push_back(Inst);
570 }
571 }
572
573 // Sort by dominance.
574 SmallVector<Instruction *, 64> InsertionList(ToMove.begin(), ToMove.end());
575 llvm::sort(InsertionList, [&Dom](Instruction *A, Instruction *B) -> bool {
576 // If a dominates b it should precede (<) b.
577 return Dom.dominates(A, B);
578 });
579
580 Instruction *InsertPt = CoroBegin->getNextNode();
581 for (Instruction *Inst : InsertionList)
582 Inst->moveBefore(InsertPt->getIterator());
583}
584
586 const DominatorTree &DT) {
587 BasicBlock::iterator InsertPt;
588 if (auto *Arg = dyn_cast<Argument>(Def)) {
589 // For arguments, we will place the store instruction right after
590 // the coroutine frame pointer instruction, i.e. coro.begin.
591 InsertPt = Shape.getInsertPtAfterFramePtr();
592
593 // If we're spilling an Argument, make sure we clear 'captures'
594 // from the coroutine function.
595 Arg->getParent()->removeParamAttr(Arg->getArgNo(), Attribute::Captures);
596 } else if (auto *CSI = dyn_cast<AnyCoroSuspendInst>(Def)) {
597 // Don't spill immediately after a suspend; splitting assumes
598 // that the suspend will be followed by a branch.
599 InsertPt = CSI->getParent()->getSingleSuccessor()->getFirstNonPHIIt();
600 } else {
601 auto *I = cast<Instruction>(Def);
602 if (!DT.dominates(Shape.CoroBegin, I)) {
603 // If it is not dominated by CoroBegin, then spill should be
604 // inserted immediately after CoroFrame is computed.
605 InsertPt = Shape.getInsertPtAfterFramePtr();
606 } else if (auto *II = dyn_cast<InvokeInst>(I)) {
607 // If we are spilling the result of the invoke instruction, split
608 // the normal edge and insert the spill in the new block.
609 auto *NewBB = SplitEdge(II->getParent(), II->getNormalDest());
610 InsertPt = NewBB->getTerminator()->getIterator();
611 } else if (isa<PHINode>(I)) {
612 // Skip the PHINodes and EH pads instructions.
613 BasicBlock *DefBlock = I->getParent();
614 if (auto *CSI = dyn_cast<CatchSwitchInst>(DefBlock->getTerminator()))
615 InsertPt = splitBeforeCatchSwitch(CSI)->getIterator();
616 else
617 InsertPt = DefBlock->getFirstInsertionPt();
618 } else {
619 assert(!I->isTerminator() && "unexpected terminator");
620 // For all other values, the spill is placed immediately after
621 // the definition.
622 InsertPt = I->getNextNode()->getIterator();
623 }
624 }
625
626 return InsertPt;
627}
628
629} // End namespace coro.
630
631} // End namespace llvm.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
uint64_t Offset
Definition: ELF_riscv.cpp:478
IRTranslator LLVM IR MI
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
iv Induction Variable Users
Definition: IVUsers.cpp:48
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
uint64_t IntrinsicInst * II
#define P(N)
StandardInstrumentations SI(Mod->getContext(), Debug, VerifyEach)
This file provides a collection of visitors which walk the (instruction) uses of a pointer.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> op)
This class represents an incoming formal argument to a Function.
Definition: Argument.h:31
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
Definition: BasicBlock.cpp:437
InstListType::iterator iterator
Instruction iterators...
Definition: BasicBlock.h:177
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...
Definition: BasicBlock.h:240
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 class represents the llvm.coro.begin or llvm.coro.begin.custom.abi instructions.
Definition: CoroInstr.h:448
This represents the llvm.dbg.value instruction.
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.
Definition: Dominators.h:162
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Definition: Dominators.cpp:122
void moveBefore(Instruction *MovePos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
iterator end()
Definition: MapVector.h:71
iterator begin()
Definition: MapVector.h:69
iterator end()
Get an iterator to the end of the SetVector.
Definition: SetVector.h:113
iterator begin()
Get an iterator to the beginning of the SetVector.
Definition: SetVector.h:103
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:162
A SetVector that performs no allocations if smaller than a certain size.
Definition: SetVector.h:370
bool empty() const
Definition: SmallVector.h:81
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
LLVM Value Representation.
Definition: Value.h:74
const ParentTy * getParent() const
Definition: ilist_node.h:32
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition: ilist_node.h:353
@ BasicBlock
Various leaf nodes.
Definition: ISDOpcodes.h:71
@ 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)
Definition: SpillUtils.cpp:585
bool isSuspendBlock(BasicBlock *BB)
Definition: Coroutines.cpp:106
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....
Definition: SpillUtils.cpp:538
void collectSpillsFromArgs(SpillInfo &Spills, Function &F, const SuspendCrossingInfo &Checker)
Definition: SpillUtils.cpp:451
void collectSpillsFromDbgInfo(SpillInfo &Spills, Function &F, const SuspendCrossingInfo &Checker)
Definition: SpillUtils.cpp:515
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)
Definition: SpillUtils.cpp:460
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
auto successors(const MachineBasicBlock *BB)
void findDbgValues(SmallVectorImpl< DbgValueInst * > &DbgValues, Value *V, SmallVectorImpl< DbgVariableRecord * > *DbgVariableRecords=nullptr)
Finds the llvm.dbg.value intrinsics describing a value.
Definition: DebugInfo.cpp:155
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1664
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
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...
Definition: CFG.cpp:248
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...
A MapVector that performs no allocations if smaller than a certain size.
Definition: MapVector.h:254
CoroBeginInst * CoroBegin
Definition: CoroShape.h:53
BasicBlock::iterator getInsertPtAfterFramePtr() const
Definition: CoroShape.h:245