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