LLVM 24.0.0git
CoroSplit.cpp
Go to the documentation of this file.
1//===- CoroSplit.cpp - Converts a coroutine into a state machine ----------===//
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// This pass builds the coroutine frame and outlines resume and destroy parts
9// of the coroutine into separate functions.
10//
11// We present a coroutine to an LLVM as an ordinary function with suspension
12// points marked up with intrinsics. We let the optimizer party on the coroutine
13// as a single function for as long as possible. Shortly before the coroutine is
14// eligible to be inlined into its callers, we split up the coroutine into parts
15// corresponding to an initial, resume and destroy invocations of the coroutine,
16// add them to the current SCC and restart the IPO pipeline to optimize the
17// coroutine subfunctions we extracted before proceeding to the caller of the
18// coroutine.
19//===----------------------------------------------------------------------===//
20
22#include "CoroCloner.h"
23#include "CoroInternal.h"
24#include "llvm/ADT/DenseMap.h"
26#include "llvm/ADT/STLExtras.h"
30#include "llvm/ADT/StringRef.h"
31#include "llvm/ADT/Twine.h"
33#include "llvm/Analysis/CFG.h"
40#include "llvm/IR/Argument.h"
41#include "llvm/IR/Attributes.h"
42#include "llvm/IR/BasicBlock.h"
43#include "llvm/IR/CFG.h"
44#include "llvm/IR/CallingConv.h"
45#include "llvm/IR/Constants.h"
46#include "llvm/IR/DIBuilder.h"
47#include "llvm/IR/DataLayout.h"
48#include "llvm/IR/DebugInfo.h"
50#include "llvm/IR/Dominators.h"
51#include "llvm/IR/GlobalValue.h"
54#include "llvm/IR/InstrTypes.h"
55#include "llvm/IR/Instruction.h"
58#include "llvm/IR/LLVMContext.h"
59#include "llvm/IR/MDBuilder.h"
60#include "llvm/IR/Module.h"
62#include "llvm/IR/Type.h"
63#include "llvm/IR/Value.h"
64#include "llvm/IR/Verifier.h"
66#include "llvm/Support/Debug.h"
75#include <cassert>
76#include <cstddef>
77#include <cstdint>
78#include <initializer_list>
79#include <iterator>
80
81using namespace llvm;
82
83#define DEBUG_TYPE "coro-split"
84
85// FIXME:
86// Lower the intrinisc in CoroEarly phase if coroutine frame doesn't escape
87// and it is known that other transformations, for example, sanitizers
88// won't lead to incorrect code.
90 coro::Shape &Shape) {
91 auto Wrapper = CB->getWrapperFunction();
92 auto Awaiter = CB->getAwaiter();
93 auto FramePtr = CB->getFrame();
94
95 Builder.SetInsertPoint(CB);
96
97 CallBase *NewCall = nullptr;
98 // await_suspend has only 2 parameters, awaiter and handle.
99 // Copy parameter attributes from the intrinsic call, but remove the last,
100 // because the last parameter now becomes the function that is being called.
101 AttributeList NewAttributes =
102 CB->getAttributes().removeParamAttributes(CB->getContext(), 2);
103
104 if (auto Invoke = dyn_cast<InvokeInst>(CB)) {
105 auto WrapperInvoke =
106 Builder.CreateInvoke(Wrapper, Invoke->getNormalDest(),
107 Invoke->getUnwindDest(), {Awaiter, FramePtr});
108
109 WrapperInvoke->setCallingConv(Invoke->getCallingConv());
110 std::copy(Invoke->bundle_op_info_begin(), Invoke->bundle_op_info_end(),
111 WrapperInvoke->bundle_op_info_begin());
112 WrapperInvoke->setAttributes(NewAttributes);
113 WrapperInvoke->setDebugLoc(Invoke->getDebugLoc());
114 NewCall = WrapperInvoke;
115 } else if (auto Call = dyn_cast<CallInst>(CB)) {
116 auto WrapperCall = Builder.CreateCall(Wrapper, {Awaiter, FramePtr});
117
118 WrapperCall->setAttributes(NewAttributes);
119 WrapperCall->setDebugLoc(Call->getDebugLoc());
120 NewCall = WrapperCall;
121 } else {
122 llvm_unreachable("Unexpected coro_await_suspend invocation method");
123 }
124
125 if (CB->getCalledFunction()->getIntrinsicID() ==
126 Intrinsic::coro_await_suspend_handle) {
127 // Follow the lowered await_suspend call above with a lowered resume call
128 // to the returned coroutine.
129 if (auto *Invoke = dyn_cast<InvokeInst>(CB)) {
130 // If the await_suspend call is an invoke, we continue in the next block.
131 Builder.SetInsertPoint(Invoke->getNormalDest()->getFirstInsertionPt());
132 }
133
134 coro::LowererBase LB(*Wrapper->getParent());
135 auto *ResumeAddr = LB.makeSubFnCall(NewCall, CoroSubFnInst::ResumeIndex,
136 &*Builder.GetInsertPoint());
137
138 LLVMContext &Ctx = Builder.getContext();
140 Type::getVoidTy(Ctx), PointerType::getUnqual(Ctx), false);
141 auto *ResumeCall = Builder.CreateCall(ResumeTy, ResumeAddr, {NewCall});
142
143 // We can't insert the 'ret' instruction and adjust the cc until the
144 // function has been split, so remember this for later.
145 Shape.SymmetricTransfers.push_back(ResumeCall);
146
147 NewCall = ResumeCall;
148 }
149
150 CB->replaceAllUsesWith(NewCall);
151 CB->eraseFromParent();
152}
153
155 IRBuilder<> Builder(F.getContext());
156 for (auto *AWS : Shape.CoroAwaitSuspends)
157 lowerAwaitSuspend(Builder, AWS, Shape);
158}
159
161 const coro::Shape &Shape, Value *FramePtr,
162 CallGraph *CG) {
165 return;
166
167 Shape.emitDealloc(Builder, FramePtr, CG);
168}
169
170/// Create a pointer to the switch destroy function field in the coroutine
171/// frame.
173 IRBuilder<> &Builder, Value *FramePtr) {
174 auto *Offset = ConstantInt::get(Type::getInt64Ty(FramePtr->getContext()),
176 return Builder.CreateInBoundsPtrAdd(FramePtr, Offset, "destroy.addr");
177}
178
179/// Make resume-clone coro.free conditional on whether the frame is elided.
180///
181/// The destroy slot holds the cleanup clone for an elided frame and the destroy
182/// clone for a heap frame. Load it before user code can reentrantly destroy the
183/// enclosing caller frame, then use the cached comparison to suppress only the
184/// deallocation. The resume clone has already performed the shared coroutine
185/// cleanup, so calling either clone here would run that cleanup twice.
187 Function &Resume, Function &Cleanup) {
188 Value *FramePtr = Resume.getArg(0);
189 IRBuilder<> EntryBuilder(Resume.getEntryBlock().getTerminator());
190 Value *DestroyAddr = createSwitchDestroyPtr(Shape, EntryBuilder, FramePtr);
191 Value *DestroyFn = EntryBuilder.CreateLoad(Shape.getSwitchResumePointerType(),
192 DestroyAddr, "destroy");
193 Value *CleanupFn =
194 EntryBuilder.CreatePointerCast(&Cleanup, DestroyFn->getType());
195 Value *IsElided =
196 EntryBuilder.CreateICmpEQ(DestroyFn, CleanupFn, "is.elided");
197
199 for (User *U : FramePtr->users()) {
200 if (auto *CF = dyn_cast<CoroFreeInst>(U))
201 CoroFrees.push_back(CF);
202 }
203
204 for (CoroFreeInst *CF : CoroFrees) {
205 IRBuilder<> Builder(CF);
206 auto *Null = ConstantPointerNull::get(cast<PointerType>(CF->getType()));
207 Value *Replacement =
208 Builder.CreateSelect(IsElided, Null, FramePtr, "coro.free");
209 // Add unknown branch weights to the select since whether the frame is
210 // heap-allocated or elided cannot be determined.
211 applyProfMetadataIfEnabled(Replacement, [&](Instruction *Inst) {
213 Inst->getFunction());
214 });
215 CF->replaceAllUsesWith(Replacement);
216 CF->eraseFromParent();
217 }
218}
219
220/// Replace an llvm.coro.end.async.
221/// Will inline the must tail call function call if there is one.
222/// \returns true if cleanup of the coro.end block is needed, false otherwise.
224 IRBuilder<> Builder(End);
225
226 auto *EndAsync = dyn_cast<CoroAsyncEndInst>(End);
227 if (!EndAsync) {
228 Builder.CreateRetVoid();
229 return true /*needs cleanup of coro.end block*/;
230 }
231
232 auto *MustTailCallFunc = EndAsync->getMustTailCallFunction();
233 if (!MustTailCallFunc) {
234 Builder.CreateRetVoid();
235 return true /*needs cleanup of coro.end block*/;
236 }
237
238 // Move the must tail call from the predecessor block into the end block.
239 auto *CoroEndBlock = End->getParent();
240 auto *MustTailCallFuncBlock = CoroEndBlock->getSinglePredecessor();
241 assert(MustTailCallFuncBlock && "Must have a single predecessor block");
242 auto It = MustTailCallFuncBlock->getTerminator()->getIterator();
243 auto *MustTailCall = cast<CallInst>(&*std::prev(It));
244 CoroEndBlock->splice(End->getIterator(), MustTailCallFuncBlock,
245 MustTailCall->getIterator());
246
247 // Insert the return instruction.
248 Builder.SetInsertPoint(End);
249 Builder.CreateRetVoid();
250 InlineFunctionInfo FnInfo;
251
252 // Remove the rest of the block, by splitting it into an unreachable block.
253 auto *BB = End->getParent();
254 BB->splitBasicBlock(End);
255 BB->getTerminator()->eraseFromParent();
256
257 auto InlineRes = InlineFunction(*MustTailCall, FnInfo);
258 assert(InlineRes.isSuccess() && "Expected inlining to succeed");
259 (void)InlineRes;
260
261 // We have cleaned up the coro.end block above.
262 return false;
263}
264
265/// Replace a non-unwind call to llvm.coro.end.
267 const coro::Shape &Shape, Value *FramePtr,
268 bool InRamp, CallGraph *CG) {
269 // Start inserting right before the coro.end.
270 IRBuilder<> Builder(End);
271
272 // Create the return instruction.
273 switch (Shape.ABI) {
274 // The cloned functions in switch-lowering always return void.
276 assert(!cast<CoroEndInst>(End)->hasResults() &&
277 "switch coroutine should not return any values");
278 // coro.end doesn't immediately end the coroutine in the main function
279 // in this lowering, because we need to deallocate the coroutine.
280 if (InRamp)
281 return;
282 Builder.CreateRetVoid();
283 break;
284
285 // In async lowering this returns.
286 case coro::ABI::Async: {
287 bool CoroEndBlockNeedsCleanup = replaceCoroEndAsync(End);
288 if (!CoroEndBlockNeedsCleanup)
289 return;
290 break;
291 }
292
293 // In unique continuation lowering, the continuations always return void.
294 // But we may have implicitly allocated storage.
296 maybeFreeRetconStorage(Builder, Shape, FramePtr, CG);
297 auto *CoroEnd = cast<CoroEndInst>(End);
298 auto *RetTy = Shape.getResumeFunctionType()->getReturnType();
299
300 if (!CoroEnd->hasResults()) {
301 assert(RetTy->isVoidTy());
302 Builder.CreateRetVoid();
303 break;
304 }
305
306 auto *CoroResults = CoroEnd->getResults();
307 unsigned NumReturns = CoroResults->numReturns();
308
309 if (auto *RetStructTy = dyn_cast<StructType>(RetTy)) {
310 assert(RetStructTy->getNumElements() == NumReturns &&
311 "numbers of returns should match resume function singature");
312 Value *ReturnValue = PoisonValue::get(RetStructTy);
313 unsigned Idx = 0;
314 for (Value *RetValEl : CoroResults->return_values())
315 ReturnValue = Builder.CreateInsertValue(ReturnValue, RetValEl, Idx++);
316 Builder.CreateRet(ReturnValue);
317 } else if (NumReturns == 0) {
318 assert(RetTy->isVoidTy());
319 Builder.CreateRetVoid();
320 } else {
321 assert(NumReturns == 1);
322 Builder.CreateRet(*CoroResults->retval_begin());
323 }
324 CoroResults->replaceAllUsesWith(
325 ConstantTokenNone::get(CoroResults->getContext()));
326 CoroResults->eraseFromParent();
327 break;
328 }
329
330 // In non-unique continuation lowering, we signal completion by returning
331 // a null continuation.
332 case coro::ABI::Retcon: {
333 assert(!cast<CoroEndInst>(End)->hasResults() &&
334 "retcon coroutine should not return any values");
335 maybeFreeRetconStorage(Builder, Shape, FramePtr, CG);
336 auto RetTy = Shape.getResumeFunctionType()->getReturnType();
337 auto RetStructTy = dyn_cast<StructType>(RetTy);
338 PointerType *ContinuationTy =
339 cast<PointerType>(RetStructTy ? RetStructTy->getElementType(0) : RetTy);
340
341 Value *ReturnValue = ConstantPointerNull::get(ContinuationTy);
342 if (RetStructTy) {
343 ReturnValue = Builder.CreateInsertValue(PoisonValue::get(RetStructTy),
344 ReturnValue, 0);
345 }
346 Builder.CreateRet(ReturnValue);
347 break;
348 }
349 }
350
351 // Remove the rest of the block, by splitting it into an unreachable block.
352 auto *BB = End->getParent();
353 BB->splitBasicBlock(End);
354 BB->getTerminator()->eraseFromParent();
355}
356
357/// Create a pointer to the switch index field in the coroutine frame.
359 IRBuilder<> &Builder, Value *FramePtr) {
360 auto *Offset = ConstantInt::get(Type::getInt64Ty(FramePtr->getContext()),
362 return Builder.CreateInBoundsPtrAdd(FramePtr, Offset, "index.addr");
363}
364
365// Mark a coroutine as done, which implies that the coroutine is finished and
366// never gets resumed.
367//
368// In resume-switched ABI, the done state is represented by storing zero in
369// ResumeFnAddr.
370//
371// NOTE: We couldn't omit the argument `FramePtr`. It is necessary because the
372// pointer to the frame in splitted function is not stored in `Shape`.
373static void markCoroutineAsDone(IRBuilder<> &Builder, const coro::Shape &Shape,
374 Value *FramePtr) {
375 assert(
376 Shape.ABI == coro::ABI::Switch &&
377 "markCoroutineAsDone is only supported for Switch-Resumed ABI for now.");
378 // Resume function pointer is always first
380 Builder.CreateStore(NullPtr, FramePtr);
381
382 // If the coroutine don't have unwind coro end, we could omit the store to
383 // the final suspend point since we could infer the coroutine is suspended
384 // at the final suspend point by the nullness of ResumeFnAddr.
385 // However, we can't skip it if the coroutine have unwind coro end. Since
386 // the coroutine reaches unwind coro end is considered suspended at the
387 // final suspend point (the ResumeFnAddr is null) but in fact the coroutine
388 // didn't complete yet. We need the IndexVal for the final suspend point
389 // to make the states clear.
392 assert(cast<CoroSuspendInst>(Shape.CoroSuspends.back())->isFinal() &&
393 "The final suspend should only live in the last position of "
394 "CoroSuspends.");
395 ConstantInt *IndexVal = Shape.getIndex(Shape.CoroSuspends.size() - 1);
396 Value *FinalIndex = createSwitchIndexPtr(Shape, Builder, FramePtr);
397 Builder.CreateStore(IndexVal, FinalIndex);
398 }
399}
400
401/// Replace an unwind call to llvm.coro.end.
402static void replaceUnwindCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape,
403 Value *FramePtr, bool InRamp, CallGraph *CG) {
404 IRBuilder<> Builder(End);
405
406 switch (Shape.ABI) {
407 // In switch-lowering, this does nothing in the main function.
408 case coro::ABI::Switch: {
409 // In C++'s specification, the coroutine should be marked as done
410 // if promise.unhandled_exception() throws. The frontend will
411 // call coro.end(true) along this path.
412 //
413 // FIXME: We should refactor this once there is other language
414 // which uses Switch-Resumed style other than C++.
415 markCoroutineAsDone(Builder, Shape, FramePtr);
416 if (InRamp)
417 return;
418 break;
419 }
420 // In async lowering this does nothing.
421 case coro::ABI::Async:
422 break;
423 // In continuation-lowering, this frees the continuation storage.
426 maybeFreeRetconStorage(Builder, Shape, FramePtr, CG);
427 break;
428 }
429
430 // If coro.end has an associated bundle, add cleanupret instruction.
431 if (auto Bundle = End->getOperandBundle(LLVMContext::OB_funclet)) {
432 auto *FromPad = cast<CleanupPadInst>(Bundle->Inputs[0]);
433 auto *CleanupRet = Builder.CreateCleanupRet(FromPad, nullptr);
434 End->getParent()->splitBasicBlock(End);
435 CleanupRet->getParent()->getTerminator()->eraseFromParent();
436 }
437}
438
439static void replaceCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape,
440 Value *FramePtr, bool InRamp, CallGraph *CG) {
441 if (End->isUnwind())
442 replaceUnwindCoroEnd(End, Shape, FramePtr, InRamp, CG);
443 else
444 replaceFallthroughCoroEnd(End, Shape, FramePtr, InRamp, CG);
445 End->eraseFromParent();
446}
447
448// In the resume function, we remove the last case (when coro::Shape is built,
449// the final suspend point (if present) is always the last element of
450// CoroSuspends array) since it is an undefined behavior to resume a coroutine
451// suspended at the final suspend point.
452// In the destroy function, if it isn't possible that the ResumeFnAddr is NULL
453// and the coroutine doesn't suspend at the final suspend point actually (this
454// is possible since the coroutine is considered suspended at the final suspend
455// point if promise.unhandled_exception() exits via an exception), we can
456// remove the last case.
459 Shape.SwitchLowering.HasFinalSuspend);
460
461 if (isSwitchDestroyFunction() && Shape.SwitchLowering.HasUnwindCoroEnd)
462 return;
463
464 auto *Switch = cast<SwitchInst>(VMap[Shape.SwitchLowering.ResumeSwitch]);
465 auto FinalCaseIt = std::prev(Switch->case_end());
466 BasicBlock *ResumeBB = FinalCaseIt->getCaseSuccessor();
467
468 // Use SwitchInstProfUpdateWrapper to remove the case, keeping the profile
469 // branch weights in sync with the switch successors.
470 SwitchInstProfUpdateWrapper SwitchWrapper(*Switch);
471 SwitchWrapper.removeCase(FinalCaseIt);
473 BasicBlock *OldSwitchBB = Switch->getParent();
474 auto *NewSwitchBB = OldSwitchBB->splitBasicBlock(Switch, "Switch");
475 Builder.SetInsertPoint(OldSwitchBB->getTerminator());
476
477 if (NewF->isCoroOnlyDestroyWhenComplete()) {
478 // When the coroutine can only be destroyed when complete, we don't need
479 // to generate code for other cases.
480 Builder.CreateBr(ResumeBB);
481 } else {
482 // Resume function pointer is always first
483 auto *Load =
484 Builder.CreateLoad(Shape.getSwitchResumePointerType(), NewFramePtr);
485 auto *Cond = Builder.CreateIsNull(Load);
486 auto *Br = Builder.CreateCondBr(Cond, ResumeBB, NewSwitchBB);
489 Inst->getFunction());
490 });
491 }
492 OldSwitchBB->getTerminator()->eraseFromParent();
493 }
494}
495
496static FunctionType *
498 auto *AsyncSuspend = cast<CoroSuspendAsyncInst>(Suspend);
499 auto *StructTy = cast<StructType>(AsyncSuspend->getType());
500 auto &Context = Suspend->getParent()->getParent()->getContext();
501 auto *VoidTy = Type::getVoidTy(Context);
502 return FunctionType::get(VoidTy, StructTy->elements(), false);
503}
504
506 const Twine &Suffix,
507 Module::iterator InsertBefore,
508 AnyCoroSuspendInst *ActiveSuspend) {
509 Module *M = OrigF.getParent();
510 auto *FnTy = (Shape.ABI != coro::ABI::Async)
511 ? Shape.getResumeFunctionType()
512 : getFunctionTypeFromAsyncSuspend(ActiveSuspend);
513
514 Function *NewF =
516 OrigF.getAddressSpace(), OrigF.getName() + Suffix);
517
518 M->getFunctionList().insert(InsertBefore, NewF);
519
520 return NewF;
521}
522
523/// Replace uses of the active llvm.coro.suspend.retcon/async call with the
524/// arguments to the continuation function.
525///
526/// This assumes that the builder has a meaningful insertion point.
529 Shape.ABI == coro::ABI::Async);
530
531 auto NewS = VMap[ActiveSuspend];
532 if (NewS->use_empty())
533 return;
534
535 // Copy out all the continuation arguments after the buffer pointer into
536 // an easily-indexed data structure for convenience.
538 // The async ABI includes all arguments -- including the first argument.
539 bool IsAsyncABI = Shape.ABI == coro::ABI::Async;
540 for (auto I = IsAsyncABI ? NewF->arg_begin() : std::next(NewF->arg_begin()),
541 E = NewF->arg_end();
542 I != E; ++I)
543 Args.push_back(&*I);
544
545 // If the suspend returns a single scalar value, we can just do a simple
546 // replacement.
547 if (!isa<StructType>(NewS->getType())) {
548 assert(Args.size() == 1);
549 NewS->replaceAllUsesWith(Args.front());
550 return;
551 }
552
553 // Try to peephole extracts of an aggregate return.
554 for (Use &U : llvm::make_early_inc_range(NewS->uses())) {
555 auto *EVI = dyn_cast<ExtractValueInst>(U.getUser());
556 if (!EVI || EVI->getNumIndices() != 1)
557 continue;
558
559 EVI->replaceAllUsesWith(Args[EVI->getIndices().front()]);
560 EVI->eraseFromParent();
561 }
562
563 // If we have no remaining uses, we're done.
564 if (NewS->use_empty())
565 return;
566
567 // Otherwise, we need to create an aggregate.
568 Value *Aggr = PoisonValue::get(NewS->getType());
569 for (auto [Idx, Arg] : llvm::enumerate(Args))
570 Aggr = Builder.CreateInsertValue(Aggr, Arg, Idx);
571
572 NewS->replaceAllUsesWith(Aggr);
573}
574
576 Value *SuspendResult;
577
578 switch (Shape.ABI) {
579 // In switch lowering, replace coro.suspend with the appropriate value
580 // for the type of function we're extracting.
581 // Replacing coro.suspend with (0) will result in control flow proceeding to
582 // a resume label associated with a suspend point, replacing it with (1) will
583 // result in control flow proceeding to a cleanup label associated with this
584 // suspend point.
586 SuspendResult = Builder.getInt8(isSwitchDestroyFunction() ? 1 : 0);
587 break;
588
589 // In async lowering there are no uses of the result.
590 case coro::ABI::Async:
591 return;
592
593 // In returned-continuation lowering, the arguments from earlier
594 // continuations are theoretically arbitrary, and they should have been
595 // spilled.
598 return;
599 }
600
601 for (AnyCoroSuspendInst *CS : Shape.CoroSuspends) {
602 // The active suspend was handled earlier.
603 if (CS == ActiveSuspend)
604 continue;
605
606 auto *MappedCS = cast<AnyCoroSuspendInst>(VMap[CS]);
607 MappedCS->replaceAllUsesWith(SuspendResult);
608 MappedCS->eraseFromParent();
609 }
610}
611
613 for (AnyCoroEndInst *CE : Shape.CoroEnds) {
614 // We use a null call graph because there's no call graph node for
615 // the cloned function yet. We'll just be rebuilding that later.
616 auto *NewCE = cast<AnyCoroEndInst>(VMap[CE]);
617 replaceCoroEnd(NewCE, Shape, NewFramePtr, /*in ramp*/ false, nullptr);
618 }
619}
620
622 auto &Ctx = OrigF.getContext();
623 for (auto *II : Shape.CoroIsInRampInsts) {
624 auto *NewII = cast<CoroIsInRampInst>(VMap[II]);
625 NewII->replaceAllUsesWith(ConstantInt::getFalse(Ctx));
626 NewII->eraseFromParent();
627 }
628}
629
631 ValueToValueMapTy *VMap) {
632 if (Shape.ABI == coro::ABI::Async && Shape.CoroSuspends.empty())
633 return;
634 Value *CachedSlot = nullptr;
635 auto getSwiftErrorSlot = [&](Type *ValueTy) -> Value * {
636 if (CachedSlot)
637 return CachedSlot;
638
639 // Check if the function has a swifterror argument.
640 for (auto &Arg : F.args()) {
641 if (Arg.isSwiftError()) {
642 CachedSlot = &Arg;
643 return &Arg;
644 }
645 }
646
647 // Create a swifterror alloca.
648 IRBuilder<> Builder(&F.getEntryBlock(),
649 F.getEntryBlock().getFirstNonPHIOrDbg());
650 auto Alloca = Builder.CreateAlloca(ValueTy);
651 Alloca->setSwiftError(true);
652
653 CachedSlot = Alloca;
654 return Alloca;
655 };
656
657 for (CallInst *Op : Shape.SwiftErrorOps) {
658 auto MappedOp = VMap ? cast<CallInst>((*VMap)[Op]) : Op;
659 IRBuilder<> Builder(MappedOp);
660
661 // If there are no arguments, this is a 'get' operation.
662 Value *MappedResult;
663 if (Op->arg_empty()) {
664 auto ValueTy = Op->getType();
665 auto Slot = getSwiftErrorSlot(ValueTy);
666 MappedResult = Builder.CreateLoad(ValueTy, Slot);
667 } else {
668 assert(Op->arg_size() == 1);
669 auto Value = MappedOp->getArgOperand(0);
670 auto ValueTy = Value->getType();
671 auto Slot = getSwiftErrorSlot(ValueTy);
672 Builder.CreateStore(Value, Slot);
673 MappedResult = Slot;
674 }
675
676 MappedOp->replaceAllUsesWith(MappedResult);
677 MappedOp->eraseFromParent();
678 }
679
680 // If we're updating the original function, we've invalidated SwiftErrorOps.
681 if (VMap == nullptr) {
682 Shape.SwiftErrorOps.clear();
683 }
684}
685
686/// Returns all debug records in F.
689 SmallVector<DbgVariableRecord *> DbgVariableRecords;
690 for (auto &I : instructions(F)) {
691 for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange()))
692 DbgVariableRecords.push_back(&DVR);
693 }
694 return DbgVariableRecords;
695}
696
700
702 auto DbgVariableRecords = collectDbgVariableRecords(*NewF);
704
705 // Only 64-bit ABIs have a register we can refer to with the entry value.
706 bool UseEntryValue = OrigF.getParent()->getTargetTriple().isArch64Bit();
707 for (DbgVariableRecord *DVR : DbgVariableRecords)
708 coro::salvageDebugInfo(ArgToAllocaMap, *DVR, UseEntryValue);
709
710 // Remove all salvaged dbg.declare intrinsics that became
711 // either unreachable or stale due to the CoroSplit transformation.
712 DominatorTree DomTree(*NewF);
713 auto IsUnreachableBlock = [&](BasicBlock *BB) {
714 return !isPotentiallyReachable(&NewF->getEntryBlock(), BB, nullptr,
715 &DomTree);
716 };
717 auto RemoveOne = [&](DbgVariableRecord *DVI) {
718 if (IsUnreachableBlock(DVI->getParent()))
719 DVI->eraseFromParent();
720 else if (isa_and_nonnull<AllocaInst>(DVI->getVariableLocationOp(0))) {
721 // Count all non-debuginfo uses in reachable blocks.
722 unsigned Uses = 0;
723 for (auto *User : DVI->getVariableLocationOp(0)->users())
724 if (auto *I = dyn_cast<Instruction>(User))
725 if (!isa<AllocaInst>(I) && !IsUnreachableBlock(I->getParent()))
726 ++Uses;
727 if (!Uses)
728 DVI->eraseFromParent();
729 }
730 };
731 for_each(DbgVariableRecords, RemoveOne);
732}
733
735 // In the original function, the AllocaSpillBlock is a block immediately
736 // following the allocation of the frame object which defines GEPs for
737 // all the allocas that have been moved into the frame, and it ends by
738 // branching to the original beginning of the coroutine. Make this
739 // the entry block of the cloned function.
740 auto *Entry = cast<BasicBlock>(VMap[Shape.AllocaSpillBlock]);
741 auto *OldEntry = &NewF->getEntryBlock();
742 Entry->setName("entry" + Suffix);
743 Entry->moveBefore(OldEntry);
744 Entry->getTerminator()->eraseFromParent();
745
746 // Clear all predecessors of the new entry block. There should be
747 // exactly one predecessor, which we created when splitting out
748 // AllocaSpillBlock to begin with.
749 assert(Entry->hasOneUse());
750 auto BranchToEntry = cast<UncondBrInst>(Entry->user_back());
751 Builder.SetInsertPoint(BranchToEntry);
752 Builder.CreateUnreachable();
753 BranchToEntry->eraseFromParent();
754
755 // Branch from the entry to the appropriate place.
756 Builder.SetInsertPoint(Entry);
757 switch (Shape.ABI) {
758 case coro::ABI::Switch: {
759 // In switch-lowering, we built a resume-entry block in the original
760 // function. Make the entry block branch to this.
761 auto *SwitchBB =
762 cast<BasicBlock>(VMap[Shape.SwitchLowering.ResumeEntryBlock]);
763 Builder.CreateBr(SwitchBB);
764 SwitchBB->moveAfter(Entry);
765 break;
766 }
767 case coro::ABI::Async:
770 // In continuation ABIs, we want to branch to immediately after the
771 // active suspend point. Earlier phases will have put the suspend in its
772 // own basic block, so just thread our jump directly to its successor.
773 assert((Shape.ABI == coro::ABI::Async &&
775 ((Shape.ABI == coro::ABI::Retcon ||
779 auto Branch = cast<UncondBrInst>(MappedCS->getNextNode());
780 Builder.CreateBr(Branch->getSuccessor(0));
781 break;
782 }
783 }
784
785 // Any static alloca that's still being used but not reachable from the new
786 // entry needs to be moved to the new entry.
787 Function *F = OldEntry->getParent();
788 DominatorTree DT{*F};
790 auto *Alloca = dyn_cast<AllocaInst>(&I);
791 if (!Alloca || I.use_empty())
792 continue;
793 if (DT.isReachableFromEntry(I.getParent()) ||
794 !isa<ConstantInt>(Alloca->getArraySize()))
795 continue;
796 I.moveBefore(*Entry, Entry->getFirstInsertionPt());
797 }
798}
799
800/// Derive the value of the new frame pointer.
802 // Builder should be inserting to the front of the new entry block.
803
804 switch (Shape.ABI) {
805 // In switch-lowering, the argument is the frame pointer.
807 return &*NewF->arg_begin();
808 // In async-lowering, one of the arguments is an async context as determined
809 // by the `llvm.coro.id.async` intrinsic. We can retrieve the async context of
810 // the resume function from the async context projection function associated
811 // with the active suspend. The frame is located as a tail to the async
812 // context header.
813 case coro::ABI::Async: {
814 auto *ActiveAsyncSuspend = cast<CoroSuspendAsyncInst>(ActiveSuspend);
815 auto ContextIdx = ActiveAsyncSuspend->getStorageArgumentIndex() & 0xff;
816 auto *CalleeContext = NewF->getArg(ContextIdx);
817 auto *ProjectionFunc =
818 ActiveAsyncSuspend->getAsyncContextProjectionFunction();
819 auto DbgLoc =
821 // Calling i8* (i8*)
822 auto *CallerContext = Builder.CreateCall(ProjectionFunc->getFunctionType(),
823 ProjectionFunc, CalleeContext);
824 CallerContext->setCallingConv(ProjectionFunc->getCallingConv());
825 CallerContext->setDebugLoc(DbgLoc);
826 // The frame is located after the async_context header.
827 auto &Context = Builder.getContext();
828 auto *FramePtrAddr = Builder.CreateInBoundsPtrAdd(
829 CallerContext,
830 ConstantInt::get(Type::getInt64Ty(Context),
831 Shape.AsyncLowering.FrameOffset),
832 "async.ctx.frameptr");
833 // Inline the projection function.
835 auto InlineRes = InlineFunction(*CallerContext, InlineInfo);
836 assert(InlineRes.isSuccess());
837 (void)InlineRes;
838 return FramePtrAddr;
839 }
840 // In continuation-lowering, the argument is the opaque storage.
843 Argument *NewStorage = &*NewF->arg_begin();
844 auto FramePtrTy = PointerType::getUnqual(Shape.FramePtr->getContext());
845
846 // If the storage is inline, just bitcast to the storage to the frame type.
847 if (Shape.RetconLowering.IsFrameInlineInStorage)
848 return NewStorage;
849
850 // Otherwise, load the real frame from the opaque storage.
851 return Builder.CreateLoad(FramePtrTy, NewStorage);
852 }
853 }
854 llvm_unreachable("bad ABI");
855}
856
857/// Adjust the scope line of the funclet to the first line number after the
858/// suspend point. This avoids a jump in the line table from the function
859/// declaration (where prologue instructions are attributed to) to the suspend
860/// point.
861/// Only adjust the scope line when the files are the same.
862/// If no candidate line number is found, fallback to the line of ActiveSuspend.
863static void updateScopeLine(Instruction *ActiveSuspend,
864 DISubprogram &SPToUpdate) {
865 if (!ActiveSuspend)
866 return;
867
868 // No subsequent instruction -> fallback to the location of ActiveSuspend.
869 if (!ActiveSuspend->getNextNode()) {
870 if (auto DL = ActiveSuspend->getDebugLoc())
871 if (SPToUpdate.getFile() == DL->getFile())
872 SPToUpdate.setScopeLine(DL->getLine());
873 return;
874 }
875
877 // Corosplit splits the BB around ActiveSuspend, so the meaningful
878 // instructions are not in the same BB.
879 // FIXME: remove this hardcoded number of tries.
880 for (unsigned Repeat = 0; Repeat < 2; Repeat++) {
882 if (!Branch)
883 break;
884 Successor = Branch->getSuccessor()->getFirstNonPHIOrDbg();
885 }
886
887 // Find the first successor of ActiveSuspend with a non-zero line location.
888 // If that matches the file of ActiveSuspend, use it.
889 BasicBlock *PBB = Successor->getParent();
890 for (; Successor != PBB->end(); Successor = std::next(Successor)) {
892 auto DL = Successor->getDebugLoc();
893 if (!DL || DL.getLine() == 0)
894 continue;
895
896 if (SPToUpdate.getFile() == DL->getFile()) {
897 SPToUpdate.setScopeLine(DL.getLine());
898 return;
899 }
900
901 break;
902 }
903
904 // If the search above failed, fallback to the location of ActiveSuspend.
905 if (auto DL = ActiveSuspend->getDebugLoc())
906 if (SPToUpdate.getFile() == DL->getFile())
907 SPToUpdate.setScopeLine(DL->getLine());
908}
909
910static void addFramePointerAttrs(AttributeList &Attrs, LLVMContext &Context,
911 unsigned ParamIndex, uint64_t Size,
912 Align Alignment, bool NoAlias) {
913 AttrBuilder ParamAttrs(Context);
914 ParamAttrs.addAttribute(Attribute::NonNull);
915 ParamAttrs.addAttribute(Attribute::NoUndef);
916
917 if (NoAlias)
918 ParamAttrs.addAttribute(Attribute::NoAlias);
919
920 ParamAttrs.addAlignmentAttr(Alignment);
921 ParamAttrs.addDereferenceableAttr(Size);
922 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
923}
924
925static void addAsyncContextAttrs(AttributeList &Attrs, LLVMContext &Context,
926 unsigned ParamIndex) {
927 AttrBuilder ParamAttrs(Context);
928 ParamAttrs.addAttribute(Attribute::SwiftAsync);
929 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
930}
931
932static void addSwiftSelfAttrs(AttributeList &Attrs, LLVMContext &Context,
933 unsigned ParamIndex) {
934 AttrBuilder ParamAttrs(Context);
935 ParamAttrs.addAttribute(Attribute::SwiftSelf);
936 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
937}
938
939/// Clone the body of the original function into a resume function of
940/// some sort.
942 assert(NewF);
943
944 // Replace all args with dummy instructions. If an argument is the old frame
945 // pointer, the dummy will be replaced by the new frame pointer once it is
946 // computed below. Uses of all other arguments should have already been
947 // rewritten by buildCoroutineFrame() to use loads/stores on the coroutine
948 // frame.
950 for (Argument &A : OrigF.args()) {
951 DummyArgs.push_back(new FreezeInst(PoisonValue::get(A.getType())));
952 VMap[&A] = DummyArgs.back();
953 }
954
956
957 // Ignore attempts to change certain attributes of the function.
958 // TODO: maybe there should be a way to suppress this during cloning?
959 auto savedVisibility = NewF->getVisibility();
960 auto savedUnnamedAddr = NewF->getUnnamedAddr();
961 auto savedDLLStorageClass = NewF->getDLLStorageClass();
962
963 // NewF's linkage (which CloneFunctionInto does *not* change) might not
964 // be compatible with the visibility of OrigF (which it *does* change),
965 // so protect against that.
966 auto savedLinkage = NewF->getLinkage();
968
971
972 auto &Context = NewF->getContext();
973
974 if (DISubprogram *SP = NewF->getSubprogram()) {
975 assert(SP != OrigF.getSubprogram() && SP->isDistinct());
977
978 // Update the linkage name and the function name to reflect the modified
979 // name.
980 MDString *NewLinkageName = MDString::get(Context, NewF->getName());
981 SP->replaceLinkageName(NewLinkageName);
982 if (DISubprogram *Decl = SP->getDeclaration()) {
983 TempDISubprogram NewDecl = Decl->clone();
984 NewDecl->replaceLinkageName(NewLinkageName);
985 SP->replaceDeclaration(MDNode::replaceWithUniqued(std::move(NewDecl)));
986 }
987 }
988
989 NewF->setLinkage(savedLinkage);
990 NewF->setVisibility(savedVisibility);
991 NewF->setUnnamedAddr(savedUnnamedAddr);
992 NewF->setDLLStorageClass(savedDLLStorageClass);
993 // The function sanitizer metadata needs to match the signature of the
994 // function it is being attached to. However this does not hold for split
995 // functions here. Thus remove the metadata for split functions.
996 if (Shape.ABI == coro::ABI::Switch &&
997 NewF->hasMetadata(LLVMContext::MD_func_sanitize))
998 NewF->eraseMetadata(LLVMContext::MD_func_sanitize);
999
1000 // Replace the attributes of the new function:
1001 auto OrigAttrs = NewF->getAttributes();
1002 auto NewAttrs = AttributeList();
1003
1004 switch (Shape.ABI) {
1005 case coro::ABI::Switch:
1006 // Bootstrap attributes by copying function attributes from the
1007 // original function. This should include optimization settings and so on.
1008 NewAttrs = NewAttrs.addFnAttributes(
1009 Context, AttrBuilder(Context, OrigAttrs.getFnAttrs()));
1010
1011 addFramePointerAttrs(NewAttrs, Context, 0, Shape.FrameSize,
1012 Shape.FrameAlign, /*NoAlias=*/false);
1013 break;
1014 case coro::ABI::Async: {
1015 auto *ActiveAsyncSuspend = cast<CoroSuspendAsyncInst>(ActiveSuspend);
1016 if (OrigF.hasParamAttribute(Shape.AsyncLowering.ContextArgNo,
1017 Attribute::SwiftAsync)) {
1018 uint32_t ArgAttributeIndices =
1019 ActiveAsyncSuspend->getStorageArgumentIndex();
1020 auto ContextArgIndex = ArgAttributeIndices & 0xff;
1021 addAsyncContextAttrs(NewAttrs, Context, ContextArgIndex);
1022
1023 // `swiftasync` must preceed `swiftself` so 0 is not a valid index for
1024 // `swiftself`.
1025 auto SwiftSelfIndex = ArgAttributeIndices >> 8;
1026 if (SwiftSelfIndex)
1027 addSwiftSelfAttrs(NewAttrs, Context, SwiftSelfIndex);
1028 }
1029
1030 // Transfer the original function's attributes.
1031 auto FnAttrs = OrigF.getAttributes().getFnAttrs();
1032 NewAttrs = NewAttrs.addFnAttributes(Context, AttrBuilder(Context, FnAttrs));
1033 break;
1034 }
1035 case coro::ABI::Retcon:
1037 // If we have a continuation prototype, just use its attributes,
1038 // full-stop.
1039 NewAttrs = Shape.RetconLowering.ResumePrototype->getAttributes();
1040
1041 /// FIXME: Is it really good to add the NoAlias attribute?
1042 addFramePointerAttrs(NewAttrs, Context, 0,
1043 Shape.getRetconCoroId()->getStorageSize(),
1044 Shape.getRetconCoroId()->getStorageAlignment(),
1045 /*NoAlias=*/true);
1046
1047 break;
1048 }
1049
1050 switch (Shape.ABI) {
1051 // In these ABIs, the cloned functions always return 'void', and the
1052 // existing return sites are meaningless. Note that for unique
1053 // continuations, this includes the returns associated with suspends;
1054 // this is fine because we can't suspend twice.
1055 case coro::ABI::Switch:
1057 // Remove old returns.
1058 for (ReturnInst *Return : Returns)
1059 changeToUnreachable(Return);
1060 break;
1061
1062 // With multi-suspend continuations, we'll already have eliminated the
1063 // original returns and inserted returns before all the suspend points,
1064 // so we want to leave any returns in place.
1065 case coro::ABI::Retcon:
1066 break;
1067 // Async lowering will insert musttail call functions at all suspend points
1068 // followed by a return.
1069 // Don't change returns to unreachable because that will trip up the verifier.
1070 // These returns should be unreachable from the clone.
1071 case coro::ABI::Async:
1072 break;
1073 }
1074
1075 NewF->setAttributes(NewAttrs);
1076 NewF->setCallingConv(Shape.getResumeFunctionCC());
1077
1078 // Set up the new entry block.
1080
1081 // Turn symmetric transfers into musttail calls.
1082 for (CallInst *ResumeCall : Shape.SymmetricTransfers) {
1083 ResumeCall = cast<CallInst>(VMap[ResumeCall]);
1084 if (TTI.supportsTailCallFor(ResumeCall)) {
1085 // FIXME: Could we support symmetric transfer effectively without
1086 // musttail?
1087 ResumeCall->setTailCallKind(CallInst::TCK_MustTail);
1088 }
1089
1090 // Put a 'ret void' after the call, and split any remaining instructions to
1091 // an unreachable block.
1092 BasicBlock *BB = ResumeCall->getParent();
1093 BB->splitBasicBlock(ResumeCall->getNextNode());
1094 Builder.SetInsertPoint(BB->getTerminator());
1095 Builder.CreateRetVoid();
1097 }
1098
1099 Builder.SetInsertPoint(&NewF->getEntryBlock().front());
1101
1102 // Remap frame pointer.
1103 Value *OldFramePtr = VMap[Shape.FramePtr];
1104 NewFramePtr->takeName(OldFramePtr);
1105 OldFramePtr->replaceAllUsesWith(NewFramePtr);
1106
1107 // Remap vFrame pointer.
1108 auto *NewVFrame = Builder.CreateBitCast(
1109 NewFramePtr, PointerType::getUnqual(Builder.getContext()), "vFrame");
1110 Value *OldVFrame = cast<Value>(VMap[Shape.CoroBegin]);
1111 if (OldVFrame != NewVFrame)
1112 OldVFrame->replaceAllUsesWith(NewVFrame);
1113
1114 // All uses of the arguments should have been resolved by this point,
1115 // so we can safely remove the dummy values.
1116 for (Instruction *DummyArg : DummyArgs) {
1117 DummyArg->replaceAllUsesWith(PoisonValue::get(DummyArg->getType()));
1118 DummyArg->deleteValue();
1119 }
1120
1121 switch (Shape.ABI) {
1122 case coro::ABI::Switch:
1123 // Rewrite final suspend handling as it is not done via switch (allows to
1124 // remove final case from the switch, since it is undefined behavior to
1125 // resume the coroutine suspended at the final suspend point.
1126 if (Shape.SwitchLowering.HasFinalSuspend)
1128 break;
1129 case coro::ABI::Async:
1130 case coro::ABI::Retcon:
1132 // Replace uses of the active suspend with the corresponding
1133 // continuation-function arguments.
1134 assert(ActiveSuspend != nullptr &&
1135 "no active suspend when lowering a continuation-style coroutine");
1137 break;
1138 }
1139
1140 // Handle suspends.
1142
1143 // Handle swifterror.
1145
1146 // Remove coro.end intrinsics.
1148
1150
1151 // Salvage debug info that points into the coroutine frame.
1153}
1154
1156 // Create a new function matching the original type
1157 NewF = createCloneDeclaration(OrigF, Shape, Suffix, OrigF.getParent()->end(),
1159
1160 // Clone the function
1162
1163 // Override EntryCount for the cloned resume function with the true sum of
1164 // all suspension points profile counts.
1165 if (FKind == coro::CloneKind::SwitchResume && OrigF.hasProfileData() &&
1166 Shape.ResumeEntryCount.has_value()) {
1167 NewF->setEntryCount(Shape.ResumeEntryCount.value());
1168 }
1169
1170 // Replacing coro.free with 'null' in cleanup to suppress deallocation code.
1173}
1174
1176 assert(Shape.ABI == coro::ABI::Async);
1177
1178 auto *FuncPtrStruct = cast<ConstantStruct>(
1180 auto *OrigRelativeFunOffset = FuncPtrStruct->getOperand(0);
1181 auto *OrigContextSize = FuncPtrStruct->getOperand(1);
1182 auto *NewContextSize = ConstantInt::get(OrigContextSize->getType(),
1184 auto *NewFuncPtrStruct = ConstantStruct::get(
1185 FuncPtrStruct->getType(), OrigRelativeFunOffset, NewContextSize);
1186
1187 Shape.AsyncLowering.AsyncFuncPointer->setInitializer(NewFuncPtrStruct);
1188}
1189
1191 if (Shape.ABI == coro::ABI::Async)
1193
1194 for (CoroAlignInst *CA : Shape.CoroAligns) {
1196 ConstantInt::get(CA->getType(), Shape.FrameAlign.value()));
1197 CA->eraseFromParent();
1198 }
1199
1200 if (Shape.CoroSizes.empty())
1201 return;
1202
1203 // In the same function all coro.sizes should have the same result type.
1204 auto *SizeIntrin = Shape.CoroSizes.back();
1205 auto *SizeConstant = ConstantInt::get(SizeIntrin->getType(),
1207
1208 for (CoroSizeInst *CS : Shape.CoroSizes) {
1209 CS->replaceAllUsesWith(SizeConstant);
1210 CS->eraseFromParent();
1211 }
1212}
1213
1216
1217#ifndef NDEBUG
1218 // For now, we do a mandatory verification step because we don't
1219 // entirely trust this pass. Note that we don't want to add a verifier
1220 // pass to FPM below because it will also verify all the global data.
1221 if (verifyFunction(F, &errs()))
1222 report_fatal_error("Broken function");
1223#endif
1224}
1225
1226// Coroutine has no suspend points. Remove heap allocation for the coroutine
1227// frame if possible.
1229 auto *CoroBegin = Shape.CoroBegin;
1230 switch (Shape.ABI) {
1231 case coro::ABI::Switch: {
1232 if (auto *AllocInst = Shape.getSwitchCoroId()->getCoroAlloc()) {
1233 coro::elideCoroFree(CoroBegin);
1234
1235 IRBuilder<> Builder(AllocInst);
1236 // Create an alloca for a byte array of the frame size
1237 auto *FrameTy = ArrayType::get(Type::getInt8Ty(Builder.getContext()),
1238 Shape.FrameSize);
1239 auto *Frame = Builder.CreateAlloca(
1240 FrameTy, nullptr, AllocInst->getFunction()->getName() + ".Frame");
1241 Frame->setAlignment(Shape.FrameAlign);
1242 AllocInst->replaceAllUsesWith(Builder.getFalse());
1243 AllocInst->eraseFromParent();
1244 CoroBegin->replaceAllUsesWith(Frame);
1245 } else {
1246 CoroBegin->replaceAllUsesWith(CoroBegin->getMem());
1247 }
1248
1249 break;
1250 }
1251 case coro::ABI::Async:
1252 case coro::ABI::Retcon:
1254 CoroBegin->replaceAllUsesWith(PoisonValue::get(CoroBegin->getType()));
1255 break;
1256 }
1257
1258 CoroBegin->eraseFromParent();
1259 Shape.CoroBegin = nullptr;
1260}
1261
1262// SimplifySuspendPoint needs to check that there is no calls between
1263// coro_save and coro_suspend, since any of the calls may potentially resume
1264// the coroutine and if that is the case we cannot eliminate the suspend point.
1266 for (Instruction &I : R) {
1267 // Assume that no intrinsic can resume the coroutine.
1268 if (isa<IntrinsicInst>(I))
1269 continue;
1270
1271 if (isa<CallBase>(I))
1272 return true;
1273 }
1274 return false;
1275}
1276
1277static bool hasCallsInBlocksBetween(BasicBlock *SaveBB, BasicBlock *ResDesBB) {
1280
1281 Set.insert(SaveBB);
1282 Worklist.push_back(ResDesBB);
1283
1284 // Accumulate all blocks between SaveBB and ResDesBB. Because CoroSaveIntr
1285 // returns a token consumed by suspend instruction, all blocks in between
1286 // will have to eventually hit SaveBB when going backwards from ResDesBB.
1287 while (!Worklist.empty()) {
1288 auto *BB = Worklist.pop_back_val();
1289 Set.insert(BB);
1290 for (auto *Pred : predecessors(BB))
1291 if (!Set.contains(Pred))
1292 Worklist.push_back(Pred);
1293 }
1294
1295 // SaveBB and ResDesBB are checked separately in hasCallsBetween.
1296 Set.erase(SaveBB);
1297 Set.erase(ResDesBB);
1298
1299 for (auto *BB : Set)
1300 if (hasCallsInBlockBetween({BB->getFirstNonPHIIt(), BB->end()}))
1301 return true;
1302
1303 return false;
1304}
1305
1306static bool hasCallsBetween(Instruction *Save, Instruction *ResumeOrDestroy) {
1307 auto *SaveBB = Save->getParent();
1308 auto *ResumeOrDestroyBB = ResumeOrDestroy->getParent();
1309 BasicBlock::iterator SaveIt = Save->getIterator();
1310 BasicBlock::iterator ResumeOrDestroyIt = ResumeOrDestroy->getIterator();
1311
1312 if (SaveBB == ResumeOrDestroyBB)
1313 return hasCallsInBlockBetween({std::next(SaveIt), ResumeOrDestroyIt});
1314
1315 // Any calls from Save to the end of the block?
1316 if (hasCallsInBlockBetween({std::next(SaveIt), SaveBB->end()}))
1317 return true;
1318
1319 // Any calls from begging of the block up to ResumeOrDestroy?
1321 {ResumeOrDestroyBB->getFirstNonPHIIt(), ResumeOrDestroyIt}))
1322 return true;
1323
1324 // Any calls in all of the blocks between SaveBB and ResumeOrDestroyBB?
1325 if (hasCallsInBlocksBetween(SaveBB, ResumeOrDestroyBB))
1326 return true;
1327
1328 return false;
1329}
1330
1331// If a SuspendIntrin is preceded by Resume or Destroy, we can eliminate the
1332// suspend point and replace it with nornal control flow.
1334 CoroBeginInst *CoroBegin) {
1335 Instruction *Prev = Suspend->getPrevNode();
1336 if (!Prev) {
1337 auto *Pred = Suspend->getParent()->getSinglePredecessor();
1338 if (!Pred)
1339 return false;
1340 Prev = Pred->getTerminator();
1341 }
1342
1343 CallBase *CB = dyn_cast<CallBase>(Prev);
1344 if (!CB)
1345 return false;
1346
1347 auto *Callee = CB->getCalledOperand()->stripPointerCasts();
1348
1349 // See if the callsite is for resumption or destruction of the coroutine.
1350 auto *SubFn = dyn_cast<CoroSubFnInst>(Callee);
1351 if (!SubFn)
1352 return false;
1353
1354 // Does not refer to the current coroutine, we cannot do anything with it.
1355 if (SubFn->getFrame() != CoroBegin)
1356 return false;
1357
1358 // See if the transformation is safe. Specifically, see if there are any
1359 // calls in between Save and CallInstr. They can potenitally resume the
1360 // coroutine rendering this optimization unsafe.
1361 auto *Save = Suspend->getCoroSave();
1362 if (hasCallsBetween(Save, CB))
1363 return false;
1364
1365 // Replace llvm.coro.suspend with the value that results in resumption over
1366 // the resume or cleanup path.
1367 Suspend->replaceAllUsesWith(SubFn->getRawIndex());
1368 Suspend->eraseFromParent();
1369 Save->eraseFromParent();
1370
1371 // No longer need a call to coro.resume or coro.destroy.
1372 if (auto *Invoke = dyn_cast<InvokeInst>(CB)) {
1373 UncondBrInst::Create(Invoke->getNormalDest(), Invoke->getIterator());
1374 }
1375
1376 // Grab the CalledValue from CB before erasing the CallInstr.
1377 auto *CalledValue = CB->getCalledOperand();
1378 CB->eraseFromParent();
1379
1380 // If no more users remove it. Usually it is a bitcast of SubFn.
1381 if (CalledValue != SubFn && CalledValue->user_empty())
1382 if (auto *I = dyn_cast<Instruction>(CalledValue))
1383 I->eraseFromParent();
1384
1385 // Now we are good to remove SubFn.
1386 if (SubFn->user_empty())
1387 SubFn->eraseFromParent();
1388
1389 return true;
1390}
1391
1392// Remove suspend points that are simplified.
1394 // Currently, the only simplification we do is switch-lowering-specific.
1395 if (Shape.ABI != coro::ABI::Switch)
1396 return;
1397
1398 auto &S = Shape.CoroSuspends;
1399 size_t I = 0, N = S.size();
1400 if (N == 0)
1401 return;
1402
1403 size_t ChangedFinalIndex = std::numeric_limits<size_t>::max();
1404 while (true) {
1405 auto SI = cast<CoroSuspendInst>(S[I]);
1406 // Leave final.suspend to handleFinalSuspend since it is undefined behavior
1407 // to resume a coroutine suspended at the final suspend point.
1408 if (!SI->isFinal() && simplifySuspendPoint(SI, Shape.CoroBegin)) {
1409 if (--N == I)
1410 break;
1411
1412 std::swap(S[I], S[N]);
1413
1414 if (cast<CoroSuspendInst>(S[I])->isFinal()) {
1416 ChangedFinalIndex = I;
1417 }
1418
1419 continue;
1420 }
1421 if (++I == N)
1422 break;
1423 }
1424 S.resize(N);
1425
1426 // Maintain final.suspend in case final suspend was swapped.
1427 // Due to we requrie the final suspend to be the last element of CoroSuspends.
1428 if (ChangedFinalIndex < N) {
1429 assert(cast<CoroSuspendInst>(S[ChangedFinalIndex])->isFinal());
1430 std::swap(S[ChangedFinalIndex], S.back());
1431 }
1432}
1433
1434namespace {
1435
1436struct SwitchCoroutineSplitter {
1437 static void split(Function &F, coro::Shape &Shape,
1438 SmallVectorImpl<Function *> &Clones,
1439 TargetTransformInfo &TTI) {
1440 assert(Shape.ABI == coro::ABI::Switch);
1441
1442 // Create a resume clone by cloning the body of the original function,
1443 // setting new entry block and replacing coro.suspend an appropriate value
1444 // to force resume or cleanup pass for every suspend point.
1445 createResumeEntryBlock(F, Shape);
1446 auto *ResumeClone = coro::SwitchCloner::createClone(
1447 F, ".resume", Shape, coro::CloneKind::SwitchResume, TTI);
1448 auto *DestroyClone = coro::SwitchCloner::createClone(
1449 F, ".destroy", Shape, coro::CloneKind::SwitchUnwind, TTI);
1450 auto *CleanupClone = coro::SwitchCloner::createClone(
1451 F, ".cleanup", Shape, coro::CloneKind::SwitchCleanup, TTI);
1452
1454 replaceSwitchResumeCoroFree(Shape, *ResumeClone, *CleanupClone);
1455
1456 postSplitCleanup(*ResumeClone);
1457 postSplitCleanup(*DestroyClone);
1458 postSplitCleanup(*CleanupClone);
1459
1460 // Store addresses resume/destroy/cleanup functions in the coroutine frame.
1461 updateCoroFrame(Shape, ResumeClone, DestroyClone, CleanupClone);
1462
1463 assert(Clones.empty());
1464 Clones.push_back(ResumeClone);
1465 Clones.push_back(DestroyClone);
1466 Clones.push_back(CleanupClone);
1467
1468 // Create a constant array referring to resume/destroy/clone functions
1469 // pointed by the last argument of @llvm.coro.info, so that CoroElide pass
1470 // can determined correct function to call.
1471 setCoroInfo(F, Shape, Clones);
1472 }
1473
1474 // Create a variant of ramp function that does not perform heap allocation
1475 // for a switch ABI coroutine.
1476 //
1477 // The newly split `.noalloc` ramp function has the following differences:
1478 // - Has one additional frame pointer parameter in lieu of dynamic
1479 // allocation.
1480 // - Suppressed allocations by replacing coro.alloc and coro.free.
1481 static Function *createNoAllocVariant(Function &F, coro::Shape &Shape,
1482 SmallVectorImpl<Function *> &Clones) {
1483 assert(Shape.ABI == coro::ABI::Switch);
1484 auto *OrigFnTy = F.getFunctionType();
1485 auto OldParams = OrigFnTy->params();
1486
1487 SmallVector<Type *> NewParams;
1488 NewParams.reserve(OldParams.size() + 1);
1489 NewParams.append(OldParams.begin(), OldParams.end());
1490 NewParams.push_back(PointerType::getUnqual(Shape.FramePtr->getContext()));
1491
1492 auto *NewFnTy = FunctionType::get(OrigFnTy->getReturnType(), NewParams,
1493 OrigFnTy->isVarArg());
1494 Function *NoAllocF = Function::Create(
1495 NewFnTy, F.getLinkage(), F.getAddressSpace(), F.getName() + ".noalloc");
1496
1497 ValueToValueMapTy VMap;
1498 unsigned int Idx = 0;
1499 for (const auto &I : F.args()) {
1500 VMap[&I] = NoAllocF->getArg(Idx++);
1501 }
1502 // We just appended the frame pointer as the last argument of the new
1503 // function.
1504 auto FrameIdx = NoAllocF->arg_size() - 1;
1506 CloneFunctionInto(NoAllocF, &F, VMap,
1507 CloneFunctionChangeType::LocalChangesOnly, Returns);
1508
1509 if (Shape.CoroBegin) {
1510 auto *NewCoroBegin =
1512 coro::elideCoroFree(NewCoroBegin);
1513 coro::suppressCoroAllocs(cast<CoroIdInst>(NewCoroBegin->getId()));
1514 NewCoroBegin->replaceAllUsesWith(NoAllocF->getArg(FrameIdx));
1515 NewCoroBegin->eraseFromParent();
1516 }
1517
1518 Module *M = F.getParent();
1519 M->getFunctionList().insert(M->end(), NoAllocF);
1520
1521 removeUnreachableBlocks(*NoAllocF);
1522 auto NewAttrs = NoAllocF->getAttributes();
1523 // When we elide allocation, we read these attributes to determine the
1524 // frame size and alignment.
1525 addFramePointerAttrs(NewAttrs, NoAllocF->getContext(), FrameIdx,
1526 Shape.FrameSize, Shape.FrameAlign,
1527 /*NoAlias=*/false);
1528
1529 NoAllocF->setAttributes(NewAttrs);
1530
1531 Clones.push_back(NoAllocF);
1532 // Reset the original function's coro info, make the new noalloc variant
1533 // connected to the original ramp function.
1534 setCoroInfo(F, Shape, Clones);
1535 // After copying, set the linkage to internal linkage. Original function
1536 // may have different linkage, but optimization dependent on this function
1537 // generally relies on LTO.
1539 return NoAllocF;
1540 }
1541
1542private:
1543 // Create an entry block for a resume function with a switch that will jump to
1544 // suspend points.
1545 static void createResumeEntryBlock(Function &F, coro::Shape &Shape) {
1546 LLVMContext &C = F.getContext();
1547
1548 DIBuilder DBuilder(*F.getParent(), /*AllowUnresolved*/ false);
1549 DISubprogram *DIS = F.getSubprogram();
1550 // If there is no DISubprogram for F, it implies the function is compiled
1551 // without debug info. So we also don't generate debug info for the
1552 // suspension points.
1553 bool AddDebugLabels = DIS && DIS->getUnit() &&
1554 (DIS->getUnit()->getEmissionKind() ==
1555 DICompileUnit::DebugEmissionKind::FullDebug);
1556
1557 // resume.entry:
1558 // %index.addr = getelementptr inbounds %f.Frame, %f.Frame* %FramePtr, i32
1559 // 0, i32 2 % index = load i32, i32* %index.addr switch i32 %index, label
1560 // %unreachable [
1561 // i32 0, label %resume.0
1562 // i32 1, label %resume.1
1563 // ...
1564 // ]
1565
1566 auto *NewEntry = BasicBlock::Create(C, "resume.entry", &F);
1567 auto *UnreachBB = BasicBlock::Create(C, "unreachable", &F);
1568
1569 IRBuilder<> Builder(NewEntry);
1570 auto *FramePtr = Shape.FramePtr;
1571 Value *GepIndex = createSwitchIndexPtr(Shape, Builder, FramePtr);
1572 auto *Index = Builder.CreateLoad(Shape.getIndexType(), GepIndex, "index");
1573 auto *Switch =
1574 Builder.CreateSwitch(Index, UnreachBB, Shape.CoroSuspends.size());
1576
1577 // Split all coro.suspend calls
1578 size_t SuspendIndex = 0;
1579 SmallVector<uint64_t, 8> SwitchWeights64;
1580 // Default destination (unreachable) has weight 0
1581 SwitchWeights64.push_back(0);
1582
1583 for (auto *AnyS : Shape.CoroSuspends) {
1584 auto *S = cast<CoroSuspendInst>(AnyS);
1585 ConstantInt *IndexVal = Shape.getIndex(SuspendIndex);
1586
1587 // Replace CoroSave with a store to Index:
1588 // %index.addr = getelementptr %f.frame... (index field number)
1589 // store i32 %IndexVal, i32* %index.addr1
1590 auto *Save = S->getCoroSave();
1591 Builder.SetInsertPoint(Save);
1592 if (S->isFinal()) {
1593 // The coroutine should be marked done if it reaches the final suspend
1594 // point.
1595 markCoroutineAsDone(Builder, Shape, FramePtr);
1596 } else {
1597 Value *GepIndex = createSwitchIndexPtr(Shape, Builder, FramePtr);
1598 Builder.CreateStore(IndexVal, GepIndex);
1599 }
1600
1602 Save->eraseFromParent();
1603
1604 // Split block before and after coro.suspend and add a jump from an entry
1605 // switch:
1606 //
1607 // whateverBB:
1608 // whatever
1609 // %0 = call i8 @llvm.coro.suspend(token none, i1 false)
1610 // switch i8 %0, label %suspend[i8 0, label %resume
1611 // i8 1, label %cleanup]
1612 // becomes:
1613 //
1614 // whateverBB:
1615 // whatever
1616 // br label %resume.0.landing
1617 //
1618 // resume.0: ; <--- jump from the switch in the resume.entry
1619 // #dbg_label(...) ; <--- artificial label for debuggers
1620 // %0 = tail call i8 @llvm.coro.suspend(token none, i1 false)
1621 // br label %resume.0.landing
1622 //
1623 // resume.0.landing:
1624 // %1 = phi i8[-1, %whateverBB], [%0, %resume.0]
1625 // switch i8 % 1, label %suspend [i8 0, label %resume
1626 // i8 1, label %cleanup]
1627
1628 auto *SuspendBB = S->getParent();
1629 auto *ResumeBB =
1630 SuspendBB->splitBasicBlock(S, "resume." + Twine(SuspendIndex));
1631 auto *LandingBB = ResumeBB->splitBasicBlock(
1632 S->getNextNode(), ResumeBB->getName() + Twine(".landing"));
1633 Switch->addCase(IndexVal, ResumeBB);
1634
1635 // Get pre-split frequency for this suspend point
1636 uint64_t Weight = 1; // Default fallback weight
1637 auto It = Shape.SuspendFreqs.find(AnyS);
1638 if (It != Shape.SuspendFreqs.end()) {
1639 Weight = It->second;
1640 }
1641 SwitchWeights64.push_back(Weight);
1642
1643 cast<UncondBrInst>(SuspendBB->getTerminator())->setSuccessor(LandingBB);
1644 auto *PN = PHINode::Create(Builder.getInt8Ty(), 2, "");
1645 PN->insertBefore(LandingBB->begin());
1646 S->replaceAllUsesWith(PN);
1647 PN->addIncoming(Builder.getInt8(-1), SuspendBB);
1648 PN->addIncoming(S, ResumeBB);
1649
1650 if (AddDebugLabels) {
1651 if (DebugLoc SuspendLoc = S->getDebugLoc()) {
1652 std::string LabelName =
1653 ("__coro_resume_" + Twine(SuspendIndex)).str();
1654 // Take the "inlined at" location recursively, if present. This is
1655 // mandatory as the DILabel insertion checks that the scopes of label
1656 // and the attached location match. This is not the case when the
1657 // suspend location has been inlined due to pointing to the original
1658 // scope.
1659 DILocation *DILoc = SuspendLoc;
1660 while (DILocation *InlinedAt = DILoc->getInlinedAt())
1661 DILoc = InlinedAt;
1662
1663 DILabel *ResumeLabel =
1664 DBuilder.createLabel(DIS, LabelName, DILoc->getFile(),
1665 SuspendLoc.getLine(), SuspendLoc.getCol(),
1666 /*IsArtificial=*/true,
1667 /*CoroSuspendIdx=*/SuspendIndex,
1668 /*AlwaysPreserve=*/false);
1669 DBuilder.insertLabel(ResumeLabel, DILoc, ResumeBB->begin());
1670 }
1671 }
1672
1673 ++SuspendIndex;
1674 }
1675
1676 if (!Shape.SuspendFreqs.empty()) {
1677 auto SwitchWeights32 = llvm::fitWeights(SwitchWeights64);
1678 MDBuilder MDB(C);
1679 Switch->setMetadata(LLVMContext::MD_prof,
1680 MDB.createBranchWeights(SwitchWeights32));
1681 }
1682
1683 Builder.SetInsertPoint(UnreachBB);
1684 Builder.CreateUnreachable();
1685 DBuilder.finalize();
1686
1687 Shape.SwitchLowering.ResumeEntryBlock = NewEntry;
1688 }
1689
1690 // Store addresses of Resume/Destroy/Cleanup functions in the coroutine frame.
1691 static void updateCoroFrame(coro::Shape &Shape, Function *ResumeFn,
1692 Function *DestroyFn, Function *CleanupFn) {
1693 IRBuilder<> Builder(&*Shape.getInsertPtAfterFramePtr());
1694 LLVMContext &C = ResumeFn->getContext();
1695
1696 // Resume function pointer
1697 Value *ResumeAddr = Shape.FramePtr;
1698 Builder.CreateStore(ResumeFn, ResumeAddr);
1699
1700 Value *DestroyOrCleanupFn = DestroyFn;
1701
1702 CoroIdInst *CoroId = Shape.getSwitchCoroId();
1703 if (CoroAllocInst *CA = CoroId->getCoroAlloc()) {
1704 // If there is a CoroAlloc and it returns false (meaning we elide the
1705 // allocation, use CleanupFn instead of DestroyFn).
1706 DestroyOrCleanupFn = Builder.CreateSelect(CA, DestroyFn, CleanupFn);
1707 applyProfMetadataIfEnabled(DestroyOrCleanupFn, [&](Instruction *Inst) {
1709 CoroId->getFunction());
1710 });
1711 }
1712
1713 // Destroy function pointer
1714 Value *DestroyAddr = Builder.CreateInBoundsPtrAdd(
1715 Shape.FramePtr,
1716 ConstantInt::get(Type::getInt64Ty(C),
1718 "destroy.addr");
1719 Builder.CreateStore(DestroyOrCleanupFn, DestroyAddr);
1720 }
1721
1722 // Create a global constant array containing pointers to functions provided
1723 // and set Info parameter of CoroBegin to point at this constant. Example:
1724 //
1725 // @f.resumers = internal constant [2 x void(%f.frame*)*]
1726 // [void(%f.frame*)* @f.resume, void(%f.frame*)*
1727 // @f.destroy]
1728 // define void @f() {
1729 // ...
1730 // call i8* @llvm.coro.begin(i8* null, i32 0, i8* null,
1731 // i8* bitcast([2 x void(%f.frame*)*] * @f.resumers to
1732 // i8*))
1733 //
1734 // Assumes that all the functions have the same signature.
1735 static void setCoroInfo(Function &F, coro::Shape &Shape,
1737 // This only works under the switch-lowering ABI because coro elision
1738 // only works on the switch-lowering ABI.
1739 SmallVector<Constant *, 4> Args(Fns);
1740 assert(!Args.empty());
1741 Function *Part = *Fns.begin();
1742 Module *M = Part->getParent();
1743 auto *ArrTy = ArrayType::get(Part->getType(), Args.size());
1744
1745 auto *ConstVal = ConstantArray::get(ArrTy, Args);
1746 auto *GV = new GlobalVariable(*M, ConstVal->getType(), /*isConstant=*/true,
1747 GlobalVariable::PrivateLinkage, ConstVal,
1748 F.getName() + Twine(".resumers"));
1749
1750 // Update coro.begin instruction to refer to this constant.
1751 LLVMContext &C = F.getContext();
1752 auto *BC = ConstantExpr::getPointerCast(GV, PointerType::getUnqual(C));
1753 Shape.getSwitchCoroId()->setInfo(BC);
1754 }
1755};
1756
1757} // namespace
1758
1761 auto *ResumeIntrinsic = Suspend->getResumeFunction();
1762 auto &Context = Suspend->getParent()->getParent()->getContext();
1763 auto *Int8PtrTy = PointerType::getUnqual(Context);
1764
1765 IRBuilder<> Builder(ResumeIntrinsic);
1766 auto *Val = Builder.CreateBitOrPointerCast(Continuation, Int8PtrTy);
1767 ResumeIntrinsic->replaceAllUsesWith(Val);
1768 ResumeIntrinsic->eraseFromParent();
1770 PoisonValue::get(Int8PtrTy));
1771}
1772
1773/// Coerce the arguments in \p FnArgs according to \p FnTy in \p CallArgs.
1774static void coerceArguments(IRBuilder<> &Builder, FunctionType *FnTy,
1775 ArrayRef<Value *> FnArgs,
1776 SmallVectorImpl<Value *> &CallArgs) {
1777 size_t ArgIdx = 0;
1778 for (auto *paramTy : FnTy->params()) {
1779 assert(ArgIdx < FnArgs.size());
1780 if (paramTy != FnArgs[ArgIdx]->getType())
1781 CallArgs.push_back(
1782 Builder.CreateBitOrPointerCast(FnArgs[ArgIdx], paramTy));
1783 else
1784 CallArgs.push_back(FnArgs[ArgIdx]);
1785 ++ArgIdx;
1786 }
1787}
1788
1792 IRBuilder<> &Builder) {
1793 auto *FnTy = MustTailCallFn->getFunctionType();
1794 // Coerce the arguments, llvm optimizations seem to ignore the types in
1795 // vaarg functions and throws away casts in optimized mode.
1796 SmallVector<Value *, 8> CallArgs;
1797 coerceArguments(Builder, FnTy, Arguments, CallArgs);
1798
1799 auto *TailCall = Builder.CreateCall(FnTy, MustTailCallFn, CallArgs);
1800 // Skip targets which don't support tail call.
1801 if (TTI.supportsTailCallFor(TailCall)) {
1802 TailCall->setTailCallKind(CallInst::TCK_MustTail);
1803 }
1804 TailCall->setDebugLoc(Loc);
1805 TailCall->setCallingConv(MustTailCallFn->getCallingConv());
1806 return TailCall;
1807}
1808
1813 assert(Clones.empty());
1814 // Reset various things that the optimizer might have decided it
1815 // "knows" about the coroutine function due to not seeing a return.
1816 F.removeFnAttr(Attribute::NoReturn);
1817 F.removeRetAttr(Attribute::NoAlias);
1818 F.removeRetAttr(Attribute::NonNull);
1819
1820 auto &Context = F.getContext();
1821 auto *Int8PtrTy = PointerType::getUnqual(Context);
1822
1823 auto *Id = Shape.getAsyncCoroId();
1824 IRBuilder<> Builder(Id);
1825
1826 auto *FramePtr = Id->getStorage();
1827 FramePtr = Builder.CreateBitOrPointerCast(FramePtr, Int8PtrTy);
1828 FramePtr = Builder.CreateInBoundsPtrAdd(
1829 FramePtr,
1830 ConstantInt::get(Type::getInt64Ty(Context),
1831 Shape.AsyncLowering.FrameOffset),
1832 "async.ctx.frameptr");
1833
1834 // Map all uses of llvm.coro.begin to the allocated frame pointer.
1835 {
1836 // Make sure we don't invalidate Shape.FramePtr.
1837 TrackingVH<Value> Handle(Shape.FramePtr);
1838 Shape.CoroBegin->replaceAllUsesWith(FramePtr);
1839 Shape.FramePtr = Handle.getValPtr();
1840 }
1841
1842 // Create all the functions in order after the main function.
1843 auto NextF = std::next(F.getIterator());
1844
1845 // Create a continuation function for each of the suspend points.
1846 Clones.reserve(Shape.CoroSuspends.size());
1847 for (auto [Idx, CS] : llvm::enumerate(Shape.CoroSuspends)) {
1848 auto *Suspend = cast<CoroSuspendAsyncInst>(CS);
1849
1850 // Create the clone declaration.
1851 auto ResumeNameSuffix = ".resume.";
1852 auto ProjectionFunctionName =
1853 Suspend->getAsyncContextProjectionFunction()->getName();
1854 bool UseSwiftMangling = false;
1855 if (ProjectionFunctionName == "__swift_async_resume_project_context") {
1856 ResumeNameSuffix = "TQ";
1857 UseSwiftMangling = true;
1858 } else if (ProjectionFunctionName == "__swift_async_resume_get_context") {
1859 ResumeNameSuffix = "TY";
1860 UseSwiftMangling = true;
1861 }
1863 F, Shape,
1864 UseSwiftMangling ? ResumeNameSuffix + Twine(Idx) + "_"
1865 : ResumeNameSuffix + Twine(Idx),
1866 NextF, Suspend);
1867 Clones.push_back(Continuation);
1868
1869 // Insert a branch to a new return block immediately before the suspend
1870 // point.
1871 auto *SuspendBB = Suspend->getParent();
1872 auto *NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1873 auto *Branch = cast<UncondBrInst>(SuspendBB->getTerminator());
1874
1875 // Place it before the first suspend.
1876 auto *ReturnBB =
1877 BasicBlock::Create(F.getContext(), "coro.return", &F, NewSuspendBB);
1878 Branch->setSuccessor(0, ReturnBB);
1879
1880 IRBuilder<> Builder(ReturnBB);
1881
1882 // Insert the call to the tail call function and inline it.
1883 auto *Fn = Suspend->getMustTailCallFunction();
1884 SmallVector<Value *, 8> Args(Suspend->args());
1885 auto FnArgs = ArrayRef<Value *>(Args).drop_front(
1887 auto *TailCall = coro::createMustTailCall(Suspend->getDebugLoc(), Fn, TTI,
1888 FnArgs, Builder);
1889 Builder.CreateRetVoid();
1890 InlineFunctionInfo FnInfo;
1891 (void)InlineFunction(*TailCall, FnInfo);
1892
1893 // Replace the lvm.coro.async.resume intrisic call.
1895 }
1896
1897 assert(Clones.size() == Shape.CoroSuspends.size());
1898
1899 for (auto [Idx, CS] : llvm::enumerate(Shape.CoroSuspends)) {
1900 auto *Suspend = CS;
1901 auto *Clone = Clones[Idx];
1902
1903 coro::BaseCloner::createClone(F, "resume." + Twine(Idx), Shape, Clone,
1904 Suspend, TTI);
1905 }
1906}
1907
1912 assert(Clones.empty());
1913
1914 // Reset various things that the optimizer might have decided it
1915 // "knows" about the coroutine function due to not seeing a return.
1916 F.removeFnAttr(Attribute::NoReturn);
1917 F.removeRetAttr(Attribute::NoAlias);
1918 F.removeRetAttr(Attribute::NonNull);
1919
1920 // Allocate the frame.
1921 auto *Id = Shape.getRetconCoroId();
1922 Value *RawFramePtr;
1923 if (Shape.RetconLowering.IsFrameInlineInStorage) {
1924 RawFramePtr = Id->getStorage();
1925 } else {
1926 IRBuilder<> Builder(Id);
1927
1928 auto FrameSize = Builder.getInt64(Shape.FrameSize);
1929
1930 // Allocate. We don't need to update the call graph node because we're
1931 // going to recompute it from scratch after splitting.
1932 // FIXME: pass the required alignment
1933 RawFramePtr = Shape.emitAlloc(Builder, FrameSize, nullptr);
1934 RawFramePtr =
1935 Builder.CreateBitCast(RawFramePtr, Shape.CoroBegin->getType());
1936
1937 // Stash the allocated frame pointer in the continuation storage.
1938 Builder.CreateStore(RawFramePtr, Id->getStorage());
1939 }
1940
1941 // Map all uses of llvm.coro.begin to the allocated frame pointer.
1942 {
1943 // Make sure we don't invalidate Shape.FramePtr.
1944 TrackingVH<Value> Handle(Shape.FramePtr);
1945 Shape.CoroBegin->replaceAllUsesWith(RawFramePtr);
1946 Shape.FramePtr = Handle.getValPtr();
1947 }
1948
1949 // Create a unique return block.
1950 BasicBlock *ReturnBB = nullptr;
1951 PHINode *ContinuationPhi = nullptr;
1952 SmallVector<PHINode *, 4> ReturnPHIs;
1953
1954 // Create all the functions in order after the main function.
1955 auto NextF = std::next(F.getIterator());
1956
1957 // Create a continuation function for each of the suspend points.
1958 Clones.reserve(Shape.CoroSuspends.size());
1959 for (auto [Idx, CS] : llvm::enumerate(Shape.CoroSuspends)) {
1960 auto Suspend = cast<CoroSuspendRetconInst>(CS);
1961
1962 // Create the clone declaration.
1964 F, Shape, ".resume." + Twine(Idx), NextF, nullptr);
1965 Clones.push_back(Continuation);
1966
1967 // Insert a branch to the unified return block immediately before
1968 // the suspend point.
1969 auto SuspendBB = Suspend->getParent();
1970 auto NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1971 auto Branch = cast<UncondBrInst>(SuspendBB->getTerminator());
1972
1973 // Create the unified return block.
1974 if (!ReturnBB) {
1975 // Place it before the first suspend.
1976 ReturnBB =
1977 BasicBlock::Create(F.getContext(), "coro.return", &F, NewSuspendBB);
1978 Shape.RetconLowering.ReturnBlock = ReturnBB;
1979
1980 IRBuilder<> Builder(ReturnBB);
1981
1982 // First, the continuation.
1983 ContinuationPhi =
1984 Builder.CreatePHI(Continuation->getType(), Shape.CoroSuspends.size());
1985
1986 // Create PHIs for all other return values.
1987 assert(ReturnPHIs.empty());
1988
1989 // Next, all the directly-yielded values.
1990 for (auto *ResultTy : Shape.getRetconResultTypes())
1991 ReturnPHIs.push_back(
1992 Builder.CreatePHI(ResultTy, Shape.CoroSuspends.size()));
1993
1994 // Build the return value.
1995 auto RetTy = F.getReturnType();
1996
1997 // Cast the continuation value if necessary.
1998 // We can't rely on the types matching up because that type would
1999 // have to be infinite.
2000 auto CastedContinuationTy =
2001 (ReturnPHIs.empty() ? RetTy : RetTy->getStructElementType(0));
2002 auto *CastedContinuation =
2003 Builder.CreateBitCast(ContinuationPhi, CastedContinuationTy);
2004
2005 Value *RetV = CastedContinuation;
2006 if (!ReturnPHIs.empty()) {
2007 auto ValueIdx = 0;
2008 RetV = PoisonValue::get(RetTy);
2009 RetV = Builder.CreateInsertValue(RetV, CastedContinuation, ValueIdx++);
2010
2011 for (auto Phi : ReturnPHIs)
2012 RetV = Builder.CreateInsertValue(RetV, Phi, ValueIdx++);
2013 }
2014
2015 Builder.CreateRet(RetV);
2016 }
2017
2018 // Branch to the return block.
2019 Branch->setSuccessor(0, ReturnBB);
2020 assert(ContinuationPhi);
2021 ContinuationPhi->addIncoming(Continuation, SuspendBB);
2022 for (auto [Phi, VUse] :
2023 llvm::zip_equal(ReturnPHIs, Suspend->value_operands()))
2024 Phi->addIncoming(VUse, SuspendBB);
2025 }
2026
2027 assert(Clones.size() == Shape.CoroSuspends.size());
2028
2029 for (auto [Idx, CS] : llvm::enumerate(Shape.CoroSuspends)) {
2030 auto Suspend = CS;
2031 auto Clone = Clones[Idx];
2032
2033 coro::BaseCloner::createClone(F, "resume." + Twine(Idx), Shape, Clone,
2034 Suspend, TTI);
2035 }
2036}
2037
2038namespace {
2039class PrettyStackTraceFunction : public PrettyStackTraceEntry {
2040 Function &F;
2041
2042public:
2043 PrettyStackTraceFunction(Function &F) : F(F) {}
2044 void print(raw_ostream &OS) const override {
2045 OS << "While splitting coroutine ";
2046 F.printAsOperand(OS, /*print type*/ false, F.getParent());
2047 OS << "\n";
2048 }
2049};
2050} // namespace
2051
2052/// Remove calls to llvm.coro.end in the original function.
2054 if (Shape.ABI != coro::ABI::Switch) {
2055 for (auto *End : Shape.CoroEnds) {
2056 replaceCoroEnd(End, Shape, Shape.FramePtr, /*in ramp*/ true, nullptr);
2057 }
2058 } else {
2059 for (llvm::AnyCoroEndInst *End : Shape.CoroEnds)
2060 End->eraseFromParent();
2061 }
2062}
2063
2065 for (auto *II : Shape.CoroIsInRampInsts) {
2066 auto &Ctx = II->getContext();
2067 II->replaceAllUsesWith(ConstantInt::getTrue(Ctx));
2068 II->eraseFromParent();
2069 }
2070}
2071
2073 for (auto *U : F.users()) {
2074 if (auto *CB = dyn_cast<CallBase>(U)) {
2075 auto *Caller = CB->getFunction();
2076 if (Caller && Caller->isPresplitCoroutine() &&
2077 CB->hasFnAttr(llvm::Attribute::CoroElideSafe))
2078 return true;
2079 }
2080 }
2081 return false;
2082}
2083
2087 SwitchCoroutineSplitter::split(F, Shape, Clones, TTI);
2088}
2089
2092 bool OptimizeFrame) {
2093 PrettyStackTraceFunction prettyStackTrace(F);
2094
2095 auto &Shape = ABI.Shape;
2096 assert(Shape.CoroBegin);
2097
2098 lowerAwaitSuspends(F, Shape);
2099
2100 simplifySuspendPoints(Shape);
2101
2102 normalizeCoroutine(F, Shape, TTI);
2103 ABI.buildCoroutineFrame(OptimizeFrame);
2105
2106 bool isNoSuspendCoroutine = Shape.CoroSuspends.empty();
2107
2108 bool shouldCreateNoAllocVariant =
2109 !isNoSuspendCoroutine && Shape.ABI == coro::ABI::Switch &&
2110 hasSafeElideCaller(F) && !F.hasFnAttribute(llvm::Attribute::NoInline);
2111 if (Shape.ABI == coro::ABI::Switch)
2113 shouldCreateNoAllocVariant;
2114
2115 // If there are no suspend points, no split required, just remove
2116 // the allocation and deallocation blocks, they are not needed.
2117 if (isNoSuspendCoroutine) {
2119 } else {
2120 ABI.splitCoroutine(F, Shape, Clones, TTI);
2121 }
2122
2123 // Replace all the swifterror operations in the original function.
2124 // This invalidates SwiftErrorOps in the Shape.
2125 replaceSwiftErrorOps(F, Shape, nullptr);
2126
2127 // Salvage debug intrinsics that point into the coroutine frame in the
2128 // original function. The Cloner has already salvaged debug info in the new
2129 // coroutine funclets.
2131 auto DbgVariableRecords = collectDbgVariableRecords(F);
2132 for (DbgVariableRecord *DVR : DbgVariableRecords)
2133 coro::salvageDebugInfo(ArgToAllocaMap, *DVR, false /*UseEntryValue*/);
2134
2137
2138 if (shouldCreateNoAllocVariant)
2139 SwitchCoroutineSplitter::createNoAllocVariant(F, Shape, Clones);
2140}
2141
2143 LazyCallGraph::Node &N, const coro::Shape &Shape,
2147
2148 auto *CurrentSCC = &C;
2149 if (!Clones.empty()) {
2150 switch (Shape.ABI) {
2151 case coro::ABI::Switch:
2152 // The resume clone's elided-frame check holds a reference to the cleanup
2153 // clone. Add the cleanup clone first, so populating the resume node does
2154 // not materialize an unregistered cleanup node.
2156 assert(Clones.size() >= 3 && "expected switch coroutine clones");
2157 CG.addSplitFunction(N.getFunction(), *Clones[2]);
2158 CG.addSplitFunction(N.getFunction(), *Clones[1]);
2159 CG.addSplitFunction(N.getFunction(), *Clones[0]);
2160 for (Function *Clone : drop_begin(Clones, 3))
2161 CG.addSplitFunction(N.getFunction(), *Clone);
2162 } else {
2163 // Each clone in the Switch lowering is independent of the other
2164 // clones. Let the LazyCallGraph know about each one separately.
2165 for (Function *Clone : Clones)
2166 CG.addSplitFunction(N.getFunction(), *Clone);
2167 }
2168 break;
2169 case coro::ABI::Async:
2170 case coro::ABI::Retcon:
2172 // Each clone in the Async/Retcon lowering references of the other clones.
2173 // Let the LazyCallGraph know about all of them at once.
2174 if (!Clones.empty())
2175 CG.addSplitRefRecursiveFunctions(N.getFunction(), Clones);
2176 break;
2177 }
2178
2179 // Let the CGSCC infra handle the changes to the original function.
2180 CurrentSCC = &updateCGAndAnalysisManagerForCGSCCPass(CG, *CurrentSCC, N, AM,
2181 UR, FAM);
2182 }
2183
2184 // Do some cleanup and let the CGSCC infra see if we've cleaned up any edges
2185 // to the split functions.
2186 postSplitCleanup(N.getFunction());
2187 CurrentSCC = &updateCGAndAnalysisManagerForFunctionPass(CG, *CurrentSCC, N,
2188 AM, UR, FAM);
2189 return *CurrentSCC;
2190}
2191
2192/// Replace a call to llvm.coro.prepare.retcon.
2193static void replacePrepare(CallInst *Prepare, LazyCallGraph &CG,
2195 auto CastFn = Prepare->getArgOperand(0); // as an i8*
2196 auto Fn = CastFn->stripPointerCasts(); // as its original type
2197
2198 // Attempt to peephole this pattern:
2199 // %0 = bitcast [[TYPE]] @some_function to i8*
2200 // %1 = call @llvm.coro.prepare.retcon(i8* %0)
2201 // %2 = bitcast %1 to [[TYPE]]
2202 // ==>
2203 // %2 = @some_function
2204 for (Use &U : llvm::make_early_inc_range(Prepare->uses())) {
2205 // Look for bitcasts back to the original function type.
2206 auto *Cast = dyn_cast<BitCastInst>(U.getUser());
2207 if (!Cast || Cast->getType() != Fn->getType())
2208 continue;
2209
2210 // Replace and remove the cast.
2211 Cast->replaceAllUsesWith(Fn);
2212 Cast->eraseFromParent();
2213 }
2214
2215 // Replace any remaining uses with the function as an i8*.
2216 // This can never directly be a callee, so we don't need to update CG.
2217 Prepare->replaceAllUsesWith(CastFn);
2218 Prepare->eraseFromParent();
2219
2220 // Kill dead bitcasts.
2221 while (auto *Cast = dyn_cast<BitCastInst>(CastFn)) {
2222 if (!Cast->use_empty())
2223 break;
2224 CastFn = Cast->getOperand(0);
2225 Cast->eraseFromParent();
2226 }
2227}
2228
2229static bool replaceAllPrepares(Function *PrepareFn, LazyCallGraph &CG,
2231 bool Changed = false;
2232 for (Use &P : llvm::make_early_inc_range(PrepareFn->uses())) {
2233 // Intrinsics can only be used in calls.
2234 auto *Prepare = cast<CallInst>(P.getUser());
2235 replacePrepare(Prepare, CG, C);
2236 Changed = true;
2237 }
2238
2239 return Changed;
2240}
2241
2242static void addPrepareFunction(const Module &M,
2244 StringRef Name) {
2245 auto *PrepareFn = M.getFunction(Name);
2246 if (PrepareFn && !PrepareFn->use_empty())
2247 Fns.push_back(PrepareFn);
2248}
2249
2250static std::unique_ptr<coro::BaseABI>
2252 std::function<bool(Instruction &)> IsMatCallback,
2253 const SmallVector<CoroSplitPass::BaseABITy> GenCustomABIs) {
2254 if (S.CoroBegin->hasCustomABI()) {
2255 unsigned CustomABI = S.CoroBegin->getCustomABI();
2256 if (CustomABI >= GenCustomABIs.size())
2257 llvm_unreachable("Custom ABI not found amoung those specified");
2258 return GenCustomABIs[CustomABI](F, S);
2259 }
2260
2261 switch (S.ABI) {
2262 case coro::ABI::Switch:
2263 return std::make_unique<coro::SwitchABI>(F, S, IsMatCallback);
2264 case coro::ABI::Async:
2265 return std::make_unique<coro::AsyncABI>(F, S, IsMatCallback);
2266 case coro::ABI::Retcon:
2267 return std::make_unique<coro::AnyRetconABI>(F, S, IsMatCallback);
2269 return std::make_unique<coro::AnyRetconABI>(F, S, IsMatCallback);
2270 }
2271 llvm_unreachable("Unknown ABI");
2272}
2273
2275 : CreateAndInitABI([](Function &F, coro::Shape &S) {
2276 std::unique_ptr<coro::BaseABI> ABI =
2278 ABI->init();
2279 return ABI;
2280 }),
2281 OptimizeFrame(OptimizeFrame) {}
2282
2285 : CreateAndInitABI([=](Function &F, coro::Shape &S) {
2286 std::unique_ptr<coro::BaseABI> ABI =
2288 ABI->init();
2289 return ABI;
2290 }),
2291 OptimizeFrame(OptimizeFrame) {}
2292
2293// For back compatibility, constructor takes a materializable callback and
2294// creates a generator for an ABI with a modified materializable callback.
2295CoroSplitPass::CoroSplitPass(std::function<bool(Instruction &)> IsMatCallback,
2296 bool OptimizeFrame)
2297 : CreateAndInitABI([=](Function &F, coro::Shape &S) {
2298 std::unique_ptr<coro::BaseABI> ABI =
2299 CreateNewABI(F, S, IsMatCallback, {});
2300 ABI->init();
2301 return ABI;
2302 }),
2303 OptimizeFrame(OptimizeFrame) {}
2304
2305// For back compatibility, constructor takes a materializable callback and
2306// creates a generator for an ABI with a modified materializable callback.
2308 std::function<bool(Instruction &)> IsMatCallback,
2310 : CreateAndInitABI([=](Function &F, coro::Shape &S) {
2311 std::unique_ptr<coro::BaseABI> ABI =
2312 CreateNewABI(F, S, IsMatCallback, GenCustomABIs);
2313 ABI->init();
2314 return ABI;
2315 }),
2316 OptimizeFrame(OptimizeFrame) {}
2317
2321 // NB: One invariant of a valid LazyCallGraph::SCC is that it must contain a
2322 // non-zero number of nodes, so we assume that here and grab the first
2323 // node's function's module.
2324 Module &M = *C.begin()->getFunction().getParent();
2325 auto &FAM =
2326 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
2327
2328 // Check for uses of llvm.coro.prepare.retcon/async.
2329 SmallVector<Function *, 2> PrepareFns;
2330 addPrepareFunction(M, PrepareFns, "llvm.coro.prepare.retcon");
2331 addPrepareFunction(M, PrepareFns, "llvm.coro.prepare.async");
2332
2333 // Find coroutines for processing.
2335 for (LazyCallGraph::Node &N : C)
2336 if (N.getFunction().isPresplitCoroutine())
2337 Coroutines.push_back(&N);
2338
2339 if (Coroutines.empty() && PrepareFns.empty())
2340 return PreservedAnalyses::all();
2341
2342 auto *CurrentSCC = &C;
2343 // Split all the coroutines.
2344 for (LazyCallGraph::Node *N : Coroutines) {
2345 Function &F = N->getFunction();
2346 LLVM_DEBUG(dbgs() << "CoroSplit: Processing coroutine '" << F.getName()
2347 << "\n");
2348
2349 // The suspend-crossing algorithm in buildCoroutineFrame gets tripped up
2350 // by unreachable blocks, so remove them as a first pass. Remove the
2351 // unreachable blocks before collecting intrinsics into Shape.
2353
2354 coro::Shape Shape(F);
2355 if (!Shape.CoroBegin)
2356 continue;
2357
2358 F.setSplittedCoroutine();
2359
2360 // Query BFI and populate SuspendFreqs right before splitting.
2361 auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
2362 for (auto *AnyS : Shape.CoroSuspends) {
2363 BasicBlock *BB = AnyS->getParent();
2364 uint64_t Freq = BFI.getBlockFreq(BB).getFrequency();
2365 Shape.SuspendFreqs[AnyS] = Freq;
2366
2367 // Query BFI to get the actual estimated execution profile count of the
2368 // basic block where this suspension point resides.
2369 std::optional<uint64_t> Count =
2370 BFI.getBlockProfileCount(BB, /*AllowSynthetic=*/true);
2371 if (Count.has_value()) {
2372 if (!Shape.ResumeEntryCount.has_value()) {
2373 // For the first suspend point visited, initialize the total sum.
2374 Shape.ResumeEntryCount = Count.value();
2375 } else {
2376 // Accumulate the absolute execution count of each subsequent suspend
2377 // point into the total sum.
2378 Shape.ResumeEntryCount.value() += Count.value();
2379 }
2380 }
2381 }
2382
2383 std::unique_ptr<coro::BaseABI> ABI = CreateAndInitABI(F, Shape);
2384
2386 auto &TTI = FAM.getResult<TargetIRAnalysis>(F);
2387 doSplitCoroutine(F, Clones, *ABI, TTI, OptimizeFrame);
2389 *N, Shape, Clones, *CurrentSCC, CG, AM, UR, FAM);
2390
2391 auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
2392 ORE.emit([&]() {
2393 return OptimizationRemark(DEBUG_TYPE, "CoroSplit", &F)
2394 << "Split '" << ore::NV("function", F.getName())
2395 << "' (frame_size=" << ore::NV("frame_size", Shape.FrameSize)
2396 << ", align=" << ore::NV("align", Shape.FrameAlign.value()) << ")";
2397 });
2398
2399 if (!Shape.CoroSuspends.empty()) {
2400 // Run the CGSCC pipeline on the original and newly split functions.
2401 UR.CWorklist.insert(CurrentSCC);
2402 for (Function *Clone : Clones)
2403 UR.CWorklist.insert(CG.lookupSCC(CG.get(*Clone)));
2404 } else if (Shape.ABI == coro::ABI::Async) {
2405 // Reprocess the function to inline the tail called return function of
2406 // coro.async.end.
2407 UR.CWorklist.insert(&C);
2408 }
2409 }
2410
2411 for (auto *PrepareFn : PrepareFns) {
2412 replaceAllPrepares(PrepareFn, CG, *CurrentSCC);
2413 }
2414
2415 return PreservedAnalyses::none();
2416}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
AMDGPU Lower Kernel Arguments
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file provides interfaces used to manipulate a call graph, regardless if it is a "old style" Call...
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void addSwiftSelfAttrs(AttributeList &Attrs, LLVMContext &Context, unsigned ParamIndex)
static bool hasCallsBetween(Instruction *Save, Instruction *ResumeOrDestroy)
static LazyCallGraph::SCC & updateCallGraphAfterCoroutineSplit(LazyCallGraph::Node &N, const coro::Shape &Shape, const SmallVectorImpl< Function * > &Clones, LazyCallGraph::SCC &C, LazyCallGraph &CG, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM)
static void replaceFallthroughCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, Value *FramePtr, bool InRamp, CallGraph *CG)
Replace a non-unwind call to llvm.coro.end.
static void replaceSwiftErrorOps(Function &F, coro::Shape &Shape, ValueToValueMapTy *VMap)
static void replaceCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, Value *FramePtr, bool InRamp, CallGraph *CG)
static void addAsyncContextAttrs(AttributeList &Attrs, LLVMContext &Context, unsigned ParamIndex)
static void maybeFreeRetconStorage(IRBuilder<> &Builder, const coro::Shape &Shape, Value *FramePtr, CallGraph *CG)
static bool hasCallsInBlocksBetween(BasicBlock *SaveBB, BasicBlock *ResDesBB)
static Function * createCloneDeclaration(Function &OrigF, coro::Shape &Shape, const Twine &Suffix, Module::iterator InsertBefore, AnyCoroSuspendInst *ActiveSuspend)
static FunctionType * getFunctionTypeFromAsyncSuspend(AnyCoroSuspendInst *Suspend)
static void updateScopeLine(Instruction *ActiveSuspend, DISubprogram &SPToUpdate)
Adjust the scope line of the funclet to the first line number after the suspend point.
static void removeCoroIsInRampFromRampFunction(const coro::Shape &Shape)
static void replaceSwitchResumeCoroFree(const coro::Shape &Shape, Function &Resume, Function &Cleanup)
Make resume-clone coro.free conditional on whether the frame is elided.
static void addPrepareFunction(const Module &M, SmallVectorImpl< Function * > &Fns, StringRef Name)
static Value * createSwitchDestroyPtr(const coro::Shape &Shape, IRBuilder<> &Builder, Value *FramePtr)
Create a pointer to the switch destroy function field in the coroutine frame.
static SmallVector< DbgVariableRecord * > collectDbgVariableRecords(Function &F)
Returns all debug records in F.
static void simplifySuspendPoints(coro::Shape &Shape)
static void addFramePointerAttrs(AttributeList &Attrs, LLVMContext &Context, unsigned ParamIndex, uint64_t Size, Align Alignment, bool NoAlias)
static bool hasSafeElideCaller(Function &F)
static bool replaceAllPrepares(Function *PrepareFn, LazyCallGraph &CG, LazyCallGraph::SCC &C)
static void replaceFrameSizeAndAlignment(coro::Shape &Shape)
static std::unique_ptr< coro::BaseABI > CreateNewABI(Function &F, coro::Shape &S, std::function< bool(Instruction &)> IsMatCallback, const SmallVector< CoroSplitPass::BaseABITy > GenCustomABIs)
static bool replaceCoroEndAsync(AnyCoroEndInst *End)
Replace an llvm.coro.end.async.
static void doSplitCoroutine(Function &F, SmallVectorImpl< Function * > &Clones, coro::BaseABI &ABI, TargetTransformInfo &TTI, bool OptimizeFrame)
static bool hasCallsInBlockBetween(iterator_range< BasicBlock::iterator > R)
static bool simplifySuspendPoint(CoroSuspendInst *Suspend, CoroBeginInst *CoroBegin)
static Value * createSwitchIndexPtr(const coro::Shape &Shape, IRBuilder<> &Builder, Value *FramePtr)
Create a pointer to the switch index field in the coroutine frame.
static void removeCoroEndsFromRampFunction(const coro::Shape &Shape)
Remove calls to llvm.coro.end in the original function.
static void markCoroutineAsDone(IRBuilder<> &Builder, const coro::Shape &Shape, Value *FramePtr)
static void updateAsyncFuncPointerContextSize(coro::Shape &Shape)
static void coerceArguments(IRBuilder<> &Builder, FunctionType *FnTy, ArrayRef< Value * > FnArgs, SmallVectorImpl< Value * > &CallArgs)
Coerce the arguments in FnArgs according to FnTy in CallArgs.
static void replaceUnwindCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, Value *FramePtr, bool InRamp, CallGraph *CG)
Replace an unwind call to llvm.coro.end.
static void lowerAwaitSuspend(IRBuilder<> &Builder, CoroAwaitSuspendInst *CB, coro::Shape &Shape)
Definition CoroSplit.cpp:89
static void lowerAwaitSuspends(Function &F, coro::Shape &Shape)
static void handleNoSuspendCoroutine(coro::Shape &Shape)
static void postSplitCleanup(Function &F)
static void replacePrepare(CallInst *Prepare, LazyCallGraph &CG, LazyCallGraph::SCC &C)
Replace a call to llvm.coro.prepare.retcon.
static void replaceAsyncResumeFunction(CoroSuspendAsyncInst *Suspend, Value *Continuation)
@ InlineInfo
This file defines the DenseMap class.
This file contains constants used for implementing Dwarf debug support.
#define DEBUG_TYPE
ManagedStatic< HTTPClientCleanup > Cleanup
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
Module.h This file contains the declarations for the Module class.
Implements a lazy call graph analysis and related passes for the new pass manager.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
uint64_t IntrinsicInst * II
#define P(N)
FunctionAnalysisManager FAM
This file provides a priority worklist.
This file contains the declarations for profiling metadata utility functions.
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
#define LLVM_DEBUG(...)
Definition Debug.h:119
static SymbolRef::Type getType(const Symbol *Sym)
Definition TapiFile.cpp:39
This pass exposes codegen information to IR-level passes.
static const unsigned FramePtr
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
bool isUnwind() const
Definition CoroInstr.h:716
CoroAllocInst * getCoroAlloc()
Definition CoroInstr.h:118
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
iterator begin() const
Definition ArrayRef.h:129
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator end()
Definition BasicBlock.h:474
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
Analysis pass which computes BlockFrequencyInfo.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
std::optional< OperandBundleUse > getOperandBundle(StringRef Name) const
Return an operand bundle by name, if present.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Value * getCalledOperand() const
Value * getArgOperand(unsigned i) const
AttributeList getAttributes() const
Return the attributes for this call.
The basic data container for the call graph of a Module of IR.
Definition CallGraph.h:72
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static LLVM_ABI Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
This is the shared class of boolean and integer constants.
Definition Constants.h:87
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
static LLVM_ABI ConstantTokenNone * get(LLVMContext &Context)
Return the ConstantTokenNone.
This represents the llvm.coro.align instruction.
Definition CoroInstr.h:671
This represents the llvm.coro.await.suspend.{void,bool,handle} instructions.
Definition CoroInstr.h:86
Value * getFrame() const
Definition CoroInstr.h:92
Value * getAwaiter() const
Definition CoroInstr.h:90
Function * getWrapperFunction() const
Definition CoroInstr.h:94
This class represents the llvm.coro.begin or llvm.coro.begin.custom.abi instructions.
Definition CoroInstr.h:479
bool hasCustomABI() const
Definition CoroInstr.h:487
int getCustomABI() const
Definition CoroInstr.h:491
This represents the llvm.coro.free instruction.
Definition CoroInstr.h:448
void setInfo(Constant *C)
Definition CoroInstr.h:215
This represents the llvm.coro.size instruction.
Definition CoroInstr.h:659
This represents the llvm.coro.suspend.async instruction.
Definition CoroInstr.h:593
CoroAsyncResumeInst * getResumeFunction() const
Definition CoroInstr.h:614
This represents the llvm.coro.suspend instruction.
Definition CoroInstr.h:561
CoroSaveInst * getCoroSave() const
Definition CoroInstr.h:565
DIFile * getFile() const
Subprogram description. Uses SubclassData1.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
A debug info location.
Definition DebugLoc.h:126
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:122
LLVM_ABI bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
This class represents a freeze function that returns random concrete value if an operand is either a ...
A proxy from a FunctionAnalysisManager to an SCC.
Class to represent function types.
Type * getReturnType() const
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:168
const BasicBlock & getEntryBlock() const
Definition Function.h:786
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition Function.h:211
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Definition Function.h:246
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:272
AttributeList getAttributes() const
Return the attribute list for this Function.
Definition Function.h:328
void setAttributes(AttributeList Attrs)
Set the attribute list for this Function.
Definition Function.h:331
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:353
size_t arg_size() const
Definition Function.h:878
Argument * getArg(unsigned i) const
Definition Function.h:863
void setLinkage(LinkageTypes LT)
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
PointerType * getType() const
Global values are always pointers.
@ InternalLinkage
Rename collisions when linking (static functions).
Definition GlobalValue.h:60
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
LLVM_ABI void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
Definition Globals.cpp:613
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2290
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2375
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Definition IRBuilder.h:1906
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2893
This class captures the data input to the InlineFunction call, and records the auxiliary results prod...
Definition Cloning.h:259
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
A node in the call graph.
An SCC of the call graph.
A lazily constructed view of the call graph of a module.
LLVM_ABI void addSplitFunction(Function &OriginalFunction, Function &NewFunction)
Add a new function split/outlined from an existing function.
LLVM_ABI void addSplitRefRecursiveFunctions(Function &OriginalFunction, ArrayRef< Function * > NewFunctions)
Add new ref-recursive functions split/outlined from an existing function.
Node & get(Function &F)
Get a graph node for a given function, scanning it to populate the graph data as necessary.
SCC * lookupSCC(Node &N) const
Lookup a function's SCC in the graph.
static std::enable_if_t< std::is_base_of< MDNode, T >::value, T * > replaceWithUniqued(std::unique_ptr< T, TempMDNodeDeleter > N)
Replace a temporary node with a uniqued one.
Definition Metadata.h:1301
A single uniqued string.
Definition Metadata.h:722
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
Definition Metadata.cpp:615
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
FunctionListType::iterator iterator
The Function iterators.
Definition Module.h:92
Diagnostic information for applied optimization remarks.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PrettyStackTraceEntry - This class is used to represent a frame of the "pretty" stack trace that is d...
Return a value (possibly void), from a function.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
A wrapper class to simplify modification of SwitchInst cases along with their prof branch_weights met...
LLVM_ABI SwitchInst::CaseIt removeCase(SwitchInst::CaseIt I)
Delegate the call to the underlying SwitchInst::removeCase() and remove correspondent branch weight.
Analysis pass providing the TargetTransformInfo.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
Value handle that tracks a Value across RAUW.
ValueTy * getValPtr() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:343
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
Definition Type.cpp:310
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:282
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:307
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
void setOperand(unsigned i, Value *Val)
Definition User.h:212
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:258
iterator_range< user_iterator > users()
Definition Value.h:426
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition Value.cpp:713
iterator_range< use_iterator > uses()
Definition Value.h:380
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
void splitCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones, TargetTransformInfo &TTI) override
void splitCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones, TargetTransformInfo &TTI) override
Function & F
Definition ABI.h:59
coro::Shape & Shape
Definition ABI.h:60
AnyCoroSuspendInst * ActiveSuspend
The active suspend instruction; meaningful only for continuation and async ABIs.
Definition CoroCloner.h:57
Value * deriveNewFramePointer()
Derive the value of the new frame pointer.
TargetTransformInfo & TTI
Definition CoroCloner.h:49
coro::Shape & Shape
Definition CoroCloner.h:46
static Function * createClone(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, Function *NewF, AnyCoroSuspendInst *ActiveSuspend, TargetTransformInfo &TTI)
Create a clone for a continuation lowering.
Definition CoroCloner.h:83
ValueToValueMapTy VMap
Definition CoroCloner.h:51
const Twine & Suffix
Definition CoroCloner.h:45
void replaceRetconOrAsyncSuspendUses()
Replace uses of the active llvm.coro.suspend.retcon/async call with the arguments to the continuation...
virtual void create()
Clone the body of the original function into a resume function of some sort.
void splitCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones, TargetTransformInfo &TTI) override
static Function * createClone(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, CloneKind FKind, TargetTransformInfo &TTI)
Create a clone for a switch lowering.
Definition CoroCloner.h:139
void create() override
Clone the body of the original function into a resume function of some sort.
const ParentTy * getParent() const
Definition ilist_node.h:34
self_iterator getIterator()
Definition ilist_node.h:123
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition ilist_node.h:348
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
CallInst * Call
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ Async
The "async continuation" lowering, where each suspend point creates a single continuation function.
Definition CoroShape.h:49
@ RetconOnce
The "unique returned-continuation" lowering, where each suspend point creates a single continuation f...
Definition CoroShape.h:44
@ Retcon
The "returned-continuation" lowering, where each suspend point creates a single continuation function...
Definition CoroShape.h:37
@ Switch
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
Definition CoroShape.h:32
void suppressCoroAllocs(CoroIdInst *CoroId)
Replaces all @llvm.coro.alloc intrinsics calls associated with a given call @llvm....
void normalizeCoroutine(Function &F, coro::Shape &Shape, TargetTransformInfo &TTI)
CallInst * createMustTailCall(DebugLoc Loc, Function *MustTailCallFn, TargetTransformInfo &TTI, ArrayRef< Value * > Arguments, IRBuilder<> &)
LLVM_ABI bool isTriviallyMaterializable(Instruction &I)
@ SwitchCleanup
The shared cleanup function for a switch lowering.
Definition CoroCloner.h:33
@ SwitchResume
The shared resume function for a switch lowering.
Definition CoroCloner.h:27
@ Continuation
An individual continuation function.
Definition CoroCloner.h:36
void elideCoroFree(Value *FramePtr)
void salvageDebugInfo(SmallDenseMap< Argument *, AllocaInst *, 4 > &ArgToAllocaMap, DbgVariableRecord &DVR, bool UseEntryValue)
Attempts to rewrite the location operand of debug records in terms of the coroutine frame pointer,...
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
@ Offset
Definition DWP.cpp:578
auto cast_if_present(const Y &Val)
cast_if_present<X> - Functionally identical to cast, except that a null value is accepted.
Definition Casting.h:683
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1732
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
Definition STLExtras.h:840
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
LLVM_ABI void setExplicitlyUnknownBranchWeightsIfProfiled(Instruction &I, StringRef PassName, const Function *F=nullptr)
Like setExplicitlyUnknownBranchWeights(...), but only sets unknown branch weights in the new instruct...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
@ Load
The value being inserted comes from a load (InsertElement only).
LLVM_ABI LazyCallGraph::SCC & updateCGAndAnalysisManagerForFunctionPass(LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM)
Helper to update the call graph after running a function pass.
LLVM_ABI LazyCallGraph::SCC & updateCGAndAnalysisManagerForCGSCCPass(LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM)
Helper to update the call graph after running a CGSCC pass.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
LLVM_ABI void applyProfMetadataIfEnabled(Value *V, llvm::function_ref< void(Instruction *)> setMetadataCallback)
bool isa_and_nonnull(const Y &Val)
Definition Casting.h:676
LLVM_ABI InlineResult InlineFunction(CallBase &CB, InlineFunctionInfo &IFI, bool MergeAttributes=false, AAResults *CalleeAAR=nullptr, bool InsertLifetime=true, bool TrackInlineHistory=false, Function *ForwardVarArgsTo=nullptr, OptimizationRemarkEmitter *ORE=nullptr)
This function inlines the called function into the basic block of the caller.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
AnalysisManager< LazyCallGraph::SCC, LazyCallGraph & > CGSCCAnalysisManager
The CGSCC analysis manager.
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
LLVM_ABI BasicBlock::iterator skipDebugIntrinsics(BasicBlock::iterator It)
Advance It while it points to a debug instruction and return the result.
LLVM_ABI SmallVector< uint32_t > fitWeights(ArrayRef< uint64_t > Weights)
Push the weights right to fit in uint32_t.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
iterator_range< SplittingIterator > split(StringRef Str, StringRef Separator)
Split the specified string over a separator and return a range-compatible iterable over its partition...
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...
Definition Casting.h:547
LLVM_ABI unsigned changeToUnreachable(Instruction *I, bool PreserveLCSSA=false, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Insert an unreachable instruction before the specified instruction, making it and the rest of the cod...
Definition Local.cpp:2552
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
TargetTransformInfo TTI
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr, const CycleInfo *CI=nullptr)
Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...
Definition CFG.cpp:335
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
LLVM_ABI void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, CloneFunctionChangeType Changes, SmallVectorImpl< ReturnInst * > &Returns, const char *NameSuffix="", ClonedCodeInfo *CodeInfo=nullptr, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr)
Clone OldFunc into NewFunc, transforming the old arguments into references to VMap values.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto predecessors(const MachineBasicBlock *BB)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
LLVM_ABI bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
Definition Local.cpp:2914
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...
SmallPriorityWorklist< LazyCallGraph::SCC *, 1 > & CWorklist
Worklist of the SCCs queued for processing.
LLVM_ABI PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
LLVM_ABI CoroSplitPass(bool OptimizeFrame=false)
BaseABITy CreateAndInitABI
Definition CoroSplit.h:54
CallInst * makeSubFnCall(Value *Arg, int Index, Instruction *InsertPt)
SmallVector< CallInst *, 2 > SymmetricTransfers
Definition CoroShape.h:67
SmallVector< CoroAwaitSuspendInst *, 4 > CoroAwaitSuspends
Definition CoroShape.h:66
AsyncLoweringStorage AsyncLowering
Definition CoroShape.h:150
FunctionType * getResumeFunctionType() const
Definition CoroShape.h:183
IntegerType * getIndexType() const
Definition CoroShape.h:168
PointerType * getSwitchResumePointerType() const
Definition CoroShape.h:177
CoroIdInst * getSwitchCoroId() const
Definition CoroShape.h:153
SmallVector< CoroSizeInst *, 2 > CoroSizes
Definition CoroShape.h:58
SmallVector< AnyCoroSuspendInst *, 4 > CoroSuspends
Definition CoroShape.h:60
uint64_t FrameSize
Definition CoroShape.h:108
std::optional< uint64_t > ResumeEntryCount
Definition CoroShape.h:65
ConstantInt * getIndex(uint64_t Value) const
Definition CoroShape.h:173
SwitchLoweringStorage SwitchLowering
Definition CoroShape.h:148
CoroBeginInst * CoroBegin
Definition CoroShape.h:55
SmallDenseMap< AnyCoroSuspendInst *, uint64_t, 4 > SuspendFreqs
Definition CoroShape.h:63
BasicBlock::iterator getInsertPtAfterFramePtr() const
Definition CoroShape.h:243
SmallVector< CoroIsInRampInst *, 2 > CoroIsInRampInsts
Definition CoroShape.h:57
LLVM_ABI void emitDealloc(IRBuilder<> &Builder, Value *Ptr, CallGraph *CG) const
Deallocate memory according to the rules of the active lowering.
RetconLoweringStorage RetconLowering
Definition CoroShape.h:149
SmallVector< CoroAlignInst *, 2 > CoroAligns
Definition CoroShape.h:59
SmallVector< AnyCoroEndInst *, 4 > CoroEnds
Definition CoroShape.h:56
SmallVector< CallInst *, 2 > SwiftErrorOps
Definition CoroShape.h:70