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.getContext());
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(),
648 F.getEntryBlock().getFirstNonPHIOrDbg());
649 auto Alloca = Builder.CreateAlloca(ValueTy);
650 Alloca->setSwiftError(true);
651
652 CachedSlot = Alloca;
653 return Alloca;
654 };
655
656 for (CallInst *Op : Shape.SwiftErrorOps) {
657 auto MappedOp = VMap ? cast<CallInst>((*VMap)[Op]) : Op;
658 IRBuilder<> Builder(MappedOp);
659
660 // If there are no arguments, this is a 'get' operation.
661 Value *MappedResult;
662 if (Op->arg_empty()) {
663 auto ValueTy = Op->getType();
664 auto Slot = getSwiftErrorSlot(ValueTy);
665 MappedResult = Builder.CreateLoad(ValueTy, Slot);
666 } else {
667 assert(Op->arg_size() == 1);
668 auto Value = MappedOp->getArgOperand(0);
669 auto ValueTy = Value->getType();
670 auto Slot = getSwiftErrorSlot(ValueTy);
671 Builder.CreateStore(Value, Slot);
672 MappedResult = Slot;
673 }
674
675 MappedOp->replaceAllUsesWith(MappedResult);
676 MappedOp->eraseFromParent();
677 }
678
679 // If we're updating the original function, we've invalidated SwiftErrorOps.
680 if (VMap == nullptr) {
681 Shape.SwiftErrorOps.clear();
682 }
683}
684
685/// Returns all debug records in F.
688 SmallVector<DbgVariableRecord *> DbgVariableRecords;
689 for (auto &I : instructions(F)) {
690 for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange()))
691 DbgVariableRecords.push_back(&DVR);
692 }
693 return DbgVariableRecords;
694}
695
699
701 auto DbgVariableRecords = collectDbgVariableRecords(*NewF);
703
704 // Only 64-bit ABIs have a register we can refer to with the entry value.
705 bool UseEntryValue = OrigF.getParent()->getTargetTriple().isArch64Bit();
706 for (DbgVariableRecord *DVR : DbgVariableRecords)
707 coro::salvageDebugInfo(ArgToAllocaMap, *DVR, UseEntryValue);
708
709 // Remove all salvaged dbg.declare intrinsics that became
710 // either unreachable or stale due to the CoroSplit transformation.
711 DominatorTree DomTree(*NewF);
712 auto IsUnreachableBlock = [&](BasicBlock *BB) {
713 return !isPotentiallyReachable(&NewF->getEntryBlock(), BB, nullptr,
714 &DomTree);
715 };
716 auto RemoveOne = [&](DbgVariableRecord *DVI) {
717 if (IsUnreachableBlock(DVI->getParent()))
718 DVI->eraseFromParent();
719 else if (isa_and_nonnull<AllocaInst>(DVI->getVariableLocationOp(0))) {
720 // Count all non-debuginfo uses in reachable blocks.
721 unsigned Uses = 0;
722 for (auto *User : DVI->getVariableLocationOp(0)->users())
723 if (auto *I = dyn_cast<Instruction>(User))
724 if (!isa<AllocaInst>(I) && !IsUnreachableBlock(I->getParent()))
725 ++Uses;
726 if (!Uses)
727 DVI->eraseFromParent();
728 }
729 };
730 for_each(DbgVariableRecords, RemoveOne);
731}
732
734 // In the original function, the AllocaSpillBlock is a block immediately
735 // following the allocation of the frame object which defines GEPs for
736 // all the allocas that have been moved into the frame, and it ends by
737 // branching to the original beginning of the coroutine. Make this
738 // the entry block of the cloned function.
739 auto *Entry = cast<BasicBlock>(VMap[Shape.AllocaSpillBlock]);
740 auto *OldEntry = &NewF->getEntryBlock();
741 Entry->setName("entry" + Suffix);
742 Entry->moveBefore(OldEntry);
743 Entry->getTerminator()->eraseFromParent();
744
745 // Clear all predecessors of the new entry block. There should be
746 // exactly one predecessor, which we created when splitting out
747 // AllocaSpillBlock to begin with.
748 assert(Entry->hasOneUse());
749 auto BranchToEntry = cast<UncondBrInst>(Entry->user_back());
750 Builder.SetInsertPoint(BranchToEntry);
751 Builder.CreateUnreachable();
752 BranchToEntry->eraseFromParent();
753
754 // Branch from the entry to the appropriate place.
755 Builder.SetInsertPoint(Entry);
756 switch (Shape.ABI) {
757 case coro::ABI::Switch: {
758 // In switch-lowering, we built a resume-entry block in the original
759 // function. Make the entry block branch to this.
760 auto *SwitchBB =
761 cast<BasicBlock>(VMap[Shape.SwitchLowering.ResumeEntryBlock]);
762 Builder.CreateBr(SwitchBB);
763 SwitchBB->moveAfter(Entry);
764 break;
765 }
766 case coro::ABI::Async:
769 // In continuation ABIs, we want to branch to immediately after the
770 // active suspend point. Earlier phases will have put the suspend in its
771 // own basic block, so just thread our jump directly to its successor.
772 assert((Shape.ABI == coro::ABI::Async &&
774 ((Shape.ABI == coro::ABI::Retcon ||
778 auto Branch = cast<UncondBrInst>(MappedCS->getNextNode());
779 Builder.CreateBr(Branch->getSuccessor(0));
780 break;
781 }
782 }
783
784 // Any static alloca that's still being used but not reachable from the new
785 // entry needs to be moved to the new entry.
786 Function *F = OldEntry->getParent();
787 DominatorTree DT{*F};
789 auto *Alloca = dyn_cast<AllocaInst>(&I);
790 if (!Alloca || I.use_empty())
791 continue;
792 if (DT.isReachableFromEntry(I.getParent()) ||
793 !isa<ConstantInt>(Alloca->getArraySize()))
794 continue;
795 I.moveBefore(*Entry, Entry->getFirstInsertionPt());
796 }
797}
798
799/// Derive the value of the new frame pointer.
801 // Builder should be inserting to the front of the new entry block.
802
803 switch (Shape.ABI) {
804 // In switch-lowering, the argument is the frame pointer.
806 return &*NewF->arg_begin();
807 // In async-lowering, one of the arguments is an async context as determined
808 // by the `llvm.coro.id.async` intrinsic. We can retrieve the async context of
809 // the resume function from the async context projection function associated
810 // with the active suspend. The frame is located as a tail to the async
811 // context header.
812 case coro::ABI::Async: {
813 auto *ActiveAsyncSuspend = cast<CoroSuspendAsyncInst>(ActiveSuspend);
814 auto ContextIdx = ActiveAsyncSuspend->getStorageArgumentIndex() & 0xff;
815 auto *CalleeContext = NewF->getArg(ContextIdx);
816 auto *ProjectionFunc =
817 ActiveAsyncSuspend->getAsyncContextProjectionFunction();
818 auto DbgLoc =
820 // Calling i8* (i8*)
821 auto *CallerContext = Builder.CreateCall(ProjectionFunc->getFunctionType(),
822 ProjectionFunc, CalleeContext);
823 CallerContext->setCallingConv(ProjectionFunc->getCallingConv());
824 CallerContext->setDebugLoc(DbgLoc);
825 // The frame is located after the async_context header.
826 auto &Context = Builder.getContext();
827 auto *FramePtrAddr = Builder.CreateInBoundsPtrAdd(
828 CallerContext,
829 ConstantInt::get(Type::getInt64Ty(Context),
830 Shape.AsyncLowering.FrameOffset),
831 "async.ctx.frameptr");
832 // Inline the projection function.
834 auto InlineRes = InlineFunction(*CallerContext, InlineInfo);
835 assert(InlineRes.isSuccess());
836 (void)InlineRes;
837 return FramePtrAddr;
838 }
839 // In continuation-lowering, the argument is the opaque storage.
842 Argument *NewStorage = &*NewF->arg_begin();
843 auto FramePtrTy = PointerType::getUnqual(Shape.FramePtr->getContext());
844
845 // If the storage is inline, just bitcast to the storage to the frame type.
846 if (Shape.RetconLowering.IsFrameInlineInStorage)
847 return NewStorage;
848
849 // Otherwise, load the real frame from the opaque storage.
850 return Builder.CreateLoad(FramePtrTy, NewStorage);
851 }
852 }
853 llvm_unreachable("bad ABI");
854}
855
856/// Adjust the scope line of the funclet to the first line number after the
857/// suspend point. This avoids a jump in the line table from the function
858/// declaration (where prologue instructions are attributed to) to the suspend
859/// point.
860/// Only adjust the scope line when the files are the same.
861/// If no candidate line number is found, fallback to the line of ActiveSuspend.
862static void updateScopeLine(Instruction *ActiveSuspend,
863 DISubprogram &SPToUpdate) {
864 if (!ActiveSuspend)
865 return;
866
867 // No subsequent instruction -> fallback to the location of ActiveSuspend.
868 if (!ActiveSuspend->getNextNode()) {
869 if (auto DL = ActiveSuspend->getDebugLoc())
870 if (SPToUpdate.getFile() == DL->getFile())
871 SPToUpdate.setScopeLine(DL->getLine());
872 return;
873 }
874
876 // Corosplit splits the BB around ActiveSuspend, so the meaningful
877 // instructions are not in the same BB.
878 // FIXME: remove this hardcoded number of tries.
879 for (unsigned Repeat = 0; Repeat < 2; Repeat++) {
881 if (!Branch)
882 break;
883 Successor = Branch->getSuccessor()->getFirstNonPHIOrDbg();
884 }
885
886 // Find the first successor of ActiveSuspend with a non-zero line location.
887 // If that matches the file of ActiveSuspend, use it.
888 BasicBlock *PBB = Successor->getParent();
889 for (; Successor != PBB->end(); Successor = std::next(Successor)) {
891 auto DL = Successor->getDebugLoc();
892 if (!DL || DL.getLine() == 0)
893 continue;
894
895 if (SPToUpdate.getFile() == DL->getFile()) {
896 SPToUpdate.setScopeLine(DL.getLine());
897 return;
898 }
899
900 break;
901 }
902
903 // If the search above failed, fallback to the location of ActiveSuspend.
904 if (auto DL = ActiveSuspend->getDebugLoc())
905 if (SPToUpdate.getFile() == DL->getFile())
906 SPToUpdate.setScopeLine(DL->getLine());
907}
908
909static void addFramePointerAttrs(AttributeList &Attrs, LLVMContext &Context,
910 unsigned ParamIndex, uint64_t Size,
911 Align Alignment, bool NoAlias) {
912 AttrBuilder ParamAttrs(Context);
913 ParamAttrs.addAttribute(Attribute::NonNull);
914 ParamAttrs.addAttribute(Attribute::NoUndef);
915
916 if (NoAlias)
917 ParamAttrs.addAttribute(Attribute::NoAlias);
918
919 ParamAttrs.addAlignmentAttr(Alignment);
920 ParamAttrs.addDereferenceableAttr(Size);
921 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
922}
923
924static void addAsyncContextAttrs(AttributeList &Attrs, LLVMContext &Context,
925 unsigned ParamIndex) {
926 AttrBuilder ParamAttrs(Context);
927 ParamAttrs.addAttribute(Attribute::SwiftAsync);
928 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
929}
930
931static void addSwiftSelfAttrs(AttributeList &Attrs, LLVMContext &Context,
932 unsigned ParamIndex) {
933 AttrBuilder ParamAttrs(Context);
934 ParamAttrs.addAttribute(Attribute::SwiftSelf);
935 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
936}
937
938/// Clone the body of the original function into a resume function of
939/// some sort.
941 assert(NewF);
942
943 // Replace all args with dummy instructions. If an argument is the old frame
944 // pointer, the dummy will be replaced by the new frame pointer once it is
945 // computed below. Uses of all other arguments should have already been
946 // rewritten by buildCoroutineFrame() to use loads/stores on the coroutine
947 // frame.
949 for (Argument &A : OrigF.args()) {
950 DummyArgs.push_back(new FreezeInst(PoisonValue::get(A.getType())));
951 VMap[&A] = DummyArgs.back();
952 }
953
955
956 // Ignore attempts to change certain attributes of the function.
957 // TODO: maybe there should be a way to suppress this during cloning?
958 auto savedVisibility = NewF->getVisibility();
959 auto savedUnnamedAddr = NewF->getUnnamedAddr();
960 auto savedDLLStorageClass = NewF->getDLLStorageClass();
961
962 // NewF's linkage (which CloneFunctionInto does *not* change) might not
963 // be compatible with the visibility of OrigF (which it *does* change),
964 // so protect against that.
965 auto savedLinkage = NewF->getLinkage();
967
970
971 auto &Context = NewF->getContext();
972
973 if (DISubprogram *SP = NewF->getSubprogram()) {
974 assert(SP != OrigF.getSubprogram() && SP->isDistinct());
976
977 // Update the linkage name and the function name to reflect the modified
978 // name.
979 MDString *NewLinkageName = MDString::get(Context, NewF->getName());
980 SP->replaceLinkageName(NewLinkageName);
981 if (DISubprogram *Decl = SP->getDeclaration()) {
982 TempDISubprogram NewDecl = Decl->clone();
983 NewDecl->replaceLinkageName(NewLinkageName);
984 SP->replaceDeclaration(MDNode::replaceWithUniqued(std::move(NewDecl)));
985 }
986 }
987
988 NewF->setLinkage(savedLinkage);
989 NewF->setVisibility(savedVisibility);
990 NewF->setUnnamedAddr(savedUnnamedAddr);
991 NewF->setDLLStorageClass(savedDLLStorageClass);
992 // The function sanitizer metadata needs to match the signature of the
993 // function it is being attached to. However this does not hold for split
994 // functions here. Thus remove the metadata for split functions.
995 if (Shape.ABI == coro::ABI::Switch &&
996 NewF->hasMetadata(LLVMContext::MD_func_sanitize))
997 NewF->eraseMetadata(LLVMContext::MD_func_sanitize);
998
999 // Replace the attributes of the new function:
1000 auto OrigAttrs = NewF->getAttributes();
1001 auto NewAttrs = AttributeList();
1002
1003 switch (Shape.ABI) {
1004 case coro::ABI::Switch:
1005 // Bootstrap attributes by copying function attributes from the
1006 // original function. This should include optimization settings and so on.
1007 NewAttrs = NewAttrs.addFnAttributes(
1008 Context, AttrBuilder(Context, OrigAttrs.getFnAttrs()));
1009
1010 addFramePointerAttrs(NewAttrs, Context, 0, Shape.FrameSize,
1011 Shape.FrameAlign, /*NoAlias=*/false);
1012 break;
1013 case coro::ABI::Async: {
1014 auto *ActiveAsyncSuspend = cast<CoroSuspendAsyncInst>(ActiveSuspend);
1015 if (OrigF.hasParamAttribute(Shape.AsyncLowering.ContextArgNo,
1016 Attribute::SwiftAsync)) {
1017 uint32_t ArgAttributeIndices =
1018 ActiveAsyncSuspend->getStorageArgumentIndex();
1019 auto ContextArgIndex = ArgAttributeIndices & 0xff;
1020 addAsyncContextAttrs(NewAttrs, Context, ContextArgIndex);
1021
1022 // `swiftasync` must preceed `swiftself` so 0 is not a valid index for
1023 // `swiftself`.
1024 auto SwiftSelfIndex = ArgAttributeIndices >> 8;
1025 if (SwiftSelfIndex)
1026 addSwiftSelfAttrs(NewAttrs, Context, SwiftSelfIndex);
1027 }
1028
1029 // Transfer the original function's attributes.
1030 auto FnAttrs = OrigF.getAttributes().getFnAttrs();
1031 NewAttrs = NewAttrs.addFnAttributes(Context, AttrBuilder(Context, FnAttrs));
1032 break;
1033 }
1034 case coro::ABI::Retcon:
1036 // If we have a continuation prototype, just use its attributes,
1037 // full-stop.
1038 NewAttrs = Shape.RetconLowering.ResumePrototype->getAttributes();
1039
1040 /// FIXME: Is it really good to add the NoAlias attribute?
1041 addFramePointerAttrs(NewAttrs, Context, 0,
1042 Shape.getRetconCoroId()->getStorageSize(),
1043 Shape.getRetconCoroId()->getStorageAlignment(),
1044 /*NoAlias=*/true);
1045
1046 break;
1047 }
1048
1049 switch (Shape.ABI) {
1050 // In these ABIs, the cloned functions always return 'void', and the
1051 // existing return sites are meaningless. Note that for unique
1052 // continuations, this includes the returns associated with suspends;
1053 // this is fine because we can't suspend twice.
1054 case coro::ABI::Switch:
1056 // Remove old returns.
1057 for (ReturnInst *Return : Returns)
1058 changeToUnreachable(Return);
1059 break;
1060
1061 // With multi-suspend continuations, we'll already have eliminated the
1062 // original returns and inserted returns before all the suspend points,
1063 // so we want to leave any returns in place.
1064 case coro::ABI::Retcon:
1065 break;
1066 // Async lowering will insert musttail call functions at all suspend points
1067 // followed by a return.
1068 // Don't change returns to unreachable because that will trip up the verifier.
1069 // These returns should be unreachable from the clone.
1070 case coro::ABI::Async:
1071 break;
1072 }
1073
1074 NewF->setAttributes(NewAttrs);
1075 NewF->setCallingConv(Shape.getResumeFunctionCC());
1076
1077 // Set up the new entry block.
1079
1080 // Turn symmetric transfers into musttail calls.
1081 for (CallInst *ResumeCall : Shape.SymmetricTransfers) {
1082 ResumeCall = cast<CallInst>(VMap[ResumeCall]);
1083 if (TTI.supportsTailCallFor(ResumeCall)) {
1084 // FIXME: Could we support symmetric transfer effectively without
1085 // musttail?
1086 ResumeCall->setTailCallKind(CallInst::TCK_MustTail);
1087 }
1088
1089 // Put a 'ret void' after the call, and split any remaining instructions to
1090 // an unreachable block.
1091 BasicBlock *BB = ResumeCall->getParent();
1092 BB->splitBasicBlock(ResumeCall->getNextNode());
1093 Builder.SetInsertPoint(BB->getTerminator());
1094 Builder.CreateRetVoid();
1096 }
1097
1098 Builder.SetInsertPoint(&NewF->getEntryBlock().front());
1100
1101 // Remap frame pointer.
1102 Value *OldFramePtr = VMap[Shape.FramePtr];
1103 NewFramePtr->takeName(OldFramePtr);
1104 OldFramePtr->replaceAllUsesWith(NewFramePtr);
1105
1106 // Remap vFrame pointer.
1107 auto *NewVFrame = Builder.CreateBitCast(
1108 NewFramePtr, PointerType::getUnqual(Builder.getContext()), "vFrame");
1109 Value *OldVFrame = cast<Value>(VMap[Shape.CoroBegin]);
1110 if (OldVFrame != NewVFrame)
1111 OldVFrame->replaceAllUsesWith(NewVFrame);
1112
1113 // All uses of the arguments should have been resolved by this point,
1114 // so we can safely remove the dummy values.
1115 for (Instruction *DummyArg : DummyArgs) {
1116 DummyArg->replaceAllUsesWith(PoisonValue::get(DummyArg->getType()));
1117 DummyArg->deleteValue();
1118 }
1119
1120 switch (Shape.ABI) {
1121 case coro::ABI::Switch:
1122 // Rewrite final suspend handling as it is not done via switch (allows to
1123 // remove final case from the switch, since it is undefined behavior to
1124 // resume the coroutine suspended at the final suspend point.
1125 if (Shape.SwitchLowering.HasFinalSuspend)
1127 break;
1128 case coro::ABI::Async:
1129 case coro::ABI::Retcon:
1131 // Replace uses of the active suspend with the corresponding
1132 // continuation-function arguments.
1133 assert(ActiveSuspend != nullptr &&
1134 "no active suspend when lowering a continuation-style coroutine");
1136 break;
1137 }
1138
1139 // Handle suspends.
1141
1142 // Handle swifterror.
1144
1145 // Remove coro.end intrinsics.
1147
1149
1150 // Salvage debug info that points into the coroutine frame.
1152}
1153
1155 // Create a new function matching the original type
1156 NewF = createCloneDeclaration(OrigF, Shape, Suffix, OrigF.getParent()->end(),
1158
1159 // Clone the function
1161
1162 // Override EntryCount for the cloned resume function with the true sum of
1163 // all suspension points profile counts.
1164 if (FKind == coro::CloneKind::SwitchResume && OrigF.hasProfileData() &&
1165 Shape.ResumeEntryCount.has_value()) {
1166 NewF->setEntryCount(Shape.ResumeEntryCount.value());
1167 }
1168
1169 // Replacing coro.free with 'null' in cleanup to suppress deallocation code.
1172}
1173
1175 assert(Shape.ABI == coro::ABI::Async);
1176
1177 auto *FuncPtrStruct = cast<ConstantStruct>(
1179 auto *OrigRelativeFunOffset = FuncPtrStruct->getOperand(0);
1180 auto *OrigContextSize = FuncPtrStruct->getOperand(1);
1181 auto *NewContextSize = ConstantInt::get(OrigContextSize->getType(),
1183 auto *NewFuncPtrStruct = ConstantStruct::get(
1184 FuncPtrStruct->getType(), OrigRelativeFunOffset, NewContextSize);
1185
1186 Shape.AsyncLowering.AsyncFuncPointer->setInitializer(NewFuncPtrStruct);
1187}
1188
1190 if (Shape.ABI == coro::ABI::Async)
1192
1193 for (CoroAlignInst *CA : Shape.CoroAligns) {
1195 ConstantInt::get(CA->getType(), Shape.FrameAlign.value()));
1196 CA->eraseFromParent();
1197 }
1198
1199 if (Shape.CoroSizes.empty())
1200 return;
1201
1202 // In the same function all coro.sizes should have the same result type.
1203 auto *SizeIntrin = Shape.CoroSizes.back();
1204 auto *SizeConstant = ConstantInt::get(SizeIntrin->getType(),
1206
1207 for (CoroSizeInst *CS : Shape.CoroSizes) {
1208 CS->replaceAllUsesWith(SizeConstant);
1209 CS->eraseFromParent();
1210 }
1211}
1212
1215
1216#ifndef NDEBUG
1217 // For now, we do a mandatory verification step because we don't
1218 // entirely trust this pass. Note that we don't want to add a verifier
1219 // pass to FPM below because it will also verify all the global data.
1220 if (verifyFunction(F, &errs()))
1221 report_fatal_error("Broken function");
1222#endif
1223}
1224
1225// Coroutine has no suspend points. Remove heap allocation for the coroutine
1226// frame if possible.
1228 auto *CoroBegin = Shape.CoroBegin;
1229 switch (Shape.ABI) {
1230 case coro::ABI::Switch: {
1231 if (auto *AllocInst = Shape.getSwitchCoroId()->getCoroAlloc()) {
1232 coro::elideCoroFree(CoroBegin);
1233
1234 IRBuilder<> Builder(AllocInst);
1235 // Create an alloca for a byte array of the frame size
1236 auto *FrameTy = ArrayType::get(Type::getInt8Ty(Builder.getContext()),
1237 Shape.FrameSize);
1238 auto *Frame = Builder.CreateAlloca(
1239 FrameTy, nullptr, AllocInst->getFunction()->getName() + ".Frame");
1240 Frame->setAlignment(Shape.FrameAlign);
1241 AllocInst->replaceAllUsesWith(Builder.getFalse());
1242 AllocInst->eraseFromParent();
1243 CoroBegin->replaceAllUsesWith(Frame);
1244 } else {
1245 CoroBegin->replaceAllUsesWith(CoroBegin->getMem());
1246 }
1247
1248 break;
1249 }
1250 case coro::ABI::Async:
1251 case coro::ABI::Retcon:
1253 CoroBegin->replaceAllUsesWith(PoisonValue::get(CoroBegin->getType()));
1254 break;
1255 }
1256
1257 CoroBegin->eraseFromParent();
1258 Shape.CoroBegin = nullptr;
1259}
1260
1261// SimplifySuspendPoint needs to check that there is no calls between
1262// coro_save and coro_suspend, since any of the calls may potentially resume
1263// the coroutine and if that is the case we cannot eliminate the suspend point.
1265 for (Instruction &I : R) {
1266 // Assume that no intrinsic can resume the coroutine.
1267 if (isa<IntrinsicInst>(I))
1268 continue;
1269
1270 if (isa<CallBase>(I))
1271 return true;
1272 }
1273 return false;
1274}
1275
1276static bool hasCallsInBlocksBetween(BasicBlock *SaveBB, BasicBlock *ResDesBB) {
1279
1280 Set.insert(SaveBB);
1281 Worklist.push_back(ResDesBB);
1282
1283 // Accumulate all blocks between SaveBB and ResDesBB. Because CoroSaveIntr
1284 // returns a token consumed by suspend instruction, all blocks in between
1285 // will have to eventually hit SaveBB when going backwards from ResDesBB.
1286 while (!Worklist.empty()) {
1287 auto *BB = Worklist.pop_back_val();
1288 Set.insert(BB);
1289 for (auto *Pred : predecessors(BB))
1290 if (!Set.contains(Pred))
1291 Worklist.push_back(Pred);
1292 }
1293
1294 // SaveBB and ResDesBB are checked separately in hasCallsBetween.
1295 Set.erase(SaveBB);
1296 Set.erase(ResDesBB);
1297
1298 for (auto *BB : Set)
1299 if (hasCallsInBlockBetween({BB->getFirstNonPHIIt(), BB->end()}))
1300 return true;
1301
1302 return false;
1303}
1304
1305static bool hasCallsBetween(Instruction *Save, Instruction *ResumeOrDestroy) {
1306 auto *SaveBB = Save->getParent();
1307 auto *ResumeOrDestroyBB = ResumeOrDestroy->getParent();
1308 BasicBlock::iterator SaveIt = Save->getIterator();
1309 BasicBlock::iterator ResumeOrDestroyIt = ResumeOrDestroy->getIterator();
1310
1311 if (SaveBB == ResumeOrDestroyBB)
1312 return hasCallsInBlockBetween({std::next(SaveIt), ResumeOrDestroyIt});
1313
1314 // Any calls from Save to the end of the block?
1315 if (hasCallsInBlockBetween({std::next(SaveIt), SaveBB->end()}))
1316 return true;
1317
1318 // Any calls from begging of the block up to ResumeOrDestroy?
1320 {ResumeOrDestroyBB->getFirstNonPHIIt(), ResumeOrDestroyIt}))
1321 return true;
1322
1323 // Any calls in all of the blocks between SaveBB and ResumeOrDestroyBB?
1324 if (hasCallsInBlocksBetween(SaveBB, ResumeOrDestroyBB))
1325 return true;
1326
1327 return false;
1328}
1329
1330// If a SuspendIntrin is preceded by Resume or Destroy, we can eliminate the
1331// suspend point and replace it with nornal control flow.
1333 CoroBeginInst *CoroBegin) {
1334 Instruction *Prev = Suspend->getPrevNode();
1335 if (!Prev) {
1336 auto *Pred = Suspend->getParent()->getSinglePredecessor();
1337 if (!Pred)
1338 return false;
1339 Prev = Pred->getTerminator();
1340 }
1341
1342 CallBase *CB = dyn_cast<CallBase>(Prev);
1343 if (!CB)
1344 return false;
1345
1346 auto *Callee = CB->getCalledOperand()->stripPointerCasts();
1347
1348 // See if the callsite is for resumption or destruction of the coroutine.
1349 auto *SubFn = dyn_cast<CoroSubFnInst>(Callee);
1350 if (!SubFn)
1351 return false;
1352
1353 // Does not refer to the current coroutine, we cannot do anything with it.
1354 if (SubFn->getFrame() != CoroBegin)
1355 return false;
1356
1357 // See if the transformation is safe. Specifically, see if there are any
1358 // calls in between Save and CallInstr. They can potenitally resume the
1359 // coroutine rendering this optimization unsafe.
1360 auto *Save = Suspend->getCoroSave();
1361 if (hasCallsBetween(Save, CB))
1362 return false;
1363
1364 // Replace llvm.coro.suspend with the value that results in resumption over
1365 // the resume or cleanup path.
1366 Suspend->replaceAllUsesWith(SubFn->getRawIndex());
1367 Suspend->eraseFromParent();
1368 Save->eraseFromParent();
1369
1370 // No longer need a call to coro.resume or coro.destroy.
1371 if (auto *Invoke = dyn_cast<InvokeInst>(CB)) {
1372 UncondBrInst::Create(Invoke->getNormalDest(), Invoke->getIterator());
1373 }
1374
1375 // Grab the CalledValue from CB before erasing the CallInstr.
1376 auto *CalledValue = CB->getCalledOperand();
1377 CB->eraseFromParent();
1378
1379 // If no more users remove it. Usually it is a bitcast of SubFn.
1380 if (CalledValue != SubFn && CalledValue->user_empty())
1381 if (auto *I = dyn_cast<Instruction>(CalledValue))
1382 I->eraseFromParent();
1383
1384 // Now we are good to remove SubFn.
1385 if (SubFn->user_empty())
1386 SubFn->eraseFromParent();
1387
1388 return true;
1389}
1390
1391// Remove suspend points that are simplified.
1393 // Currently, the only simplification we do is switch-lowering-specific.
1394 if (Shape.ABI != coro::ABI::Switch)
1395 return;
1396
1397 auto &S = Shape.CoroSuspends;
1398 size_t I = 0, N = S.size();
1399 if (N == 0)
1400 return;
1401
1402 size_t ChangedFinalIndex = std::numeric_limits<size_t>::max();
1403 while (true) {
1404 auto SI = cast<CoroSuspendInst>(S[I]);
1405 // Leave final.suspend to handleFinalSuspend since it is undefined behavior
1406 // to resume a coroutine suspended at the final suspend point.
1407 if (!SI->isFinal() && simplifySuspendPoint(SI, Shape.CoroBegin)) {
1408 if (--N == I)
1409 break;
1410
1411 std::swap(S[I], S[N]);
1412
1413 if (cast<CoroSuspendInst>(S[I])->isFinal()) {
1415 ChangedFinalIndex = I;
1416 }
1417
1418 continue;
1419 }
1420 if (++I == N)
1421 break;
1422 }
1423 S.resize(N);
1424
1425 // Maintain final.suspend in case final suspend was swapped.
1426 // Due to we requrie the final suspend to be the last element of CoroSuspends.
1427 if (ChangedFinalIndex < N) {
1428 assert(cast<CoroSuspendInst>(S[ChangedFinalIndex])->isFinal());
1429 std::swap(S[ChangedFinalIndex], S.back());
1430 }
1431}
1432
1433namespace {
1434
1435struct SwitchCoroutineSplitter {
1436 static void split(Function &F, coro::Shape &Shape,
1437 SmallVectorImpl<Function *> &Clones,
1438 TargetTransformInfo &TTI) {
1439 assert(Shape.ABI == coro::ABI::Switch);
1440
1441 // Create a resume clone by cloning the body of the original function,
1442 // setting new entry block and replacing coro.suspend an appropriate value
1443 // to force resume or cleanup pass for every suspend point.
1444 createResumeEntryBlock(F, Shape);
1445 auto *ResumeClone = coro::SwitchCloner::createClone(
1446 F, ".resume", Shape, coro::CloneKind::SwitchResume, TTI);
1447 auto *DestroyClone = coro::SwitchCloner::createClone(
1448 F, ".destroy", Shape, coro::CloneKind::SwitchUnwind, TTI);
1449 auto *CleanupClone = coro::SwitchCloner::createClone(
1450 F, ".cleanup", Shape, coro::CloneKind::SwitchCleanup, TTI);
1451
1453 replaceSwitchResumeCoroFree(Shape, *ResumeClone, *CleanupClone);
1454
1455 postSplitCleanup(*ResumeClone);
1456 postSplitCleanup(*DestroyClone);
1457 postSplitCleanup(*CleanupClone);
1458
1459 // Store addresses resume/destroy/cleanup functions in the coroutine frame.
1460 updateCoroFrame(Shape, ResumeClone, DestroyClone, CleanupClone);
1461
1462 assert(Clones.empty());
1463 Clones.push_back(ResumeClone);
1464 Clones.push_back(DestroyClone);
1465 Clones.push_back(CleanupClone);
1466
1467 // Create a constant array referring to resume/destroy/clone functions
1468 // pointed by the last argument of @llvm.coro.info, so that CoroElide pass
1469 // can determined correct function to call.
1470 setCoroInfo(F, Shape, Clones);
1471 }
1472
1473 // Create a variant of ramp function that does not perform heap allocation
1474 // for a switch ABI coroutine.
1475 //
1476 // The newly split `.noalloc` ramp function has the following differences:
1477 // - Has one additional frame pointer parameter in lieu of dynamic
1478 // allocation.
1479 // - Suppressed allocations by replacing coro.alloc and coro.free.
1480 static Function *createNoAllocVariant(Function &F, coro::Shape &Shape,
1481 SmallVectorImpl<Function *> &Clones) {
1482 assert(Shape.ABI == coro::ABI::Switch);
1483 auto *OrigFnTy = F.getFunctionType();
1484 auto OldParams = OrigFnTy->params();
1485
1486 SmallVector<Type *> NewParams;
1487 NewParams.reserve(OldParams.size() + 1);
1488 NewParams.append(OldParams.begin(), OldParams.end());
1489 NewParams.push_back(PointerType::getUnqual(Shape.FramePtr->getContext()));
1490
1491 auto *NewFnTy = FunctionType::get(OrigFnTy->getReturnType(), NewParams,
1492 OrigFnTy->isVarArg());
1493 Function *NoAllocF = Function::Create(
1494 NewFnTy, F.getLinkage(), F.getAddressSpace(), F.getName() + ".noalloc");
1495
1496 ValueToValueMapTy VMap;
1497 unsigned int Idx = 0;
1498 for (const auto &I : F.args()) {
1499 VMap[&I] = NoAllocF->getArg(Idx++);
1500 }
1501 // We just appended the frame pointer as the last argument of the new
1502 // function.
1503 auto FrameIdx = NoAllocF->arg_size() - 1;
1505 CloneFunctionInto(NoAllocF, &F, VMap,
1506 CloneFunctionChangeType::LocalChangesOnly, Returns);
1507
1508 if (Shape.CoroBegin) {
1509 auto *NewCoroBegin =
1511 coro::elideCoroFree(NewCoroBegin);
1512 coro::suppressCoroAllocs(cast<CoroIdInst>(NewCoroBegin->getId()));
1513 NewCoroBegin->replaceAllUsesWith(NoAllocF->getArg(FrameIdx));
1514 NewCoroBegin->eraseFromParent();
1515 }
1516
1517 Module *M = F.getParent();
1518 M->getFunctionList().insert(M->end(), NoAllocF);
1519
1520 removeUnreachableBlocks(*NoAllocF);
1521 auto NewAttrs = NoAllocF->getAttributes();
1522 // When we elide allocation, we read these attributes to determine the
1523 // frame size and alignment.
1524 addFramePointerAttrs(NewAttrs, NoAllocF->getContext(), FrameIdx,
1525 Shape.FrameSize, Shape.FrameAlign,
1526 /*NoAlias=*/false);
1527
1528 NoAllocF->setAttributes(NewAttrs);
1529
1530 Clones.push_back(NoAllocF);
1531 // Reset the original function's coro info, make the new noalloc variant
1532 // connected to the original ramp function.
1533 setCoroInfo(F, Shape, Clones);
1534 // After copying, set the linkage to internal linkage. Original function
1535 // may have different linkage, but optimization dependent on this function
1536 // generally relies on LTO.
1538 return NoAllocF;
1539 }
1540
1541private:
1542 // Create an entry block for a resume function with a switch that will jump to
1543 // suspend points.
1544 static void createResumeEntryBlock(Function &F, coro::Shape &Shape) {
1545 LLVMContext &C = F.getContext();
1546
1547 DIBuilder DBuilder(*F.getParent(), /*AllowUnresolved*/ false);
1548 DISubprogram *DIS = F.getSubprogram();
1549 // If there is no DISubprogram for F, it implies the function is compiled
1550 // without debug info. So we also don't generate debug info for the
1551 // suspension points.
1552 bool AddDebugLabels = DIS && DIS->getUnit() &&
1553 (DIS->getUnit()->getEmissionKind() ==
1554 DICompileUnit::DebugEmissionKind::FullDebug);
1555
1556 // resume.entry:
1557 // %index.addr = getelementptr inbounds %f.Frame, %f.Frame* %FramePtr, i32
1558 // 0, i32 2 % index = load i32, i32* %index.addr switch i32 %index, label
1559 // %unreachable [
1560 // i32 0, label %resume.0
1561 // i32 1, label %resume.1
1562 // ...
1563 // ]
1564
1565 auto *NewEntry = BasicBlock::Create(C, "resume.entry", &F);
1566 auto *UnreachBB = BasicBlock::Create(C, "unreachable", &F);
1567
1568 IRBuilder<> Builder(NewEntry);
1569 auto *FramePtr = Shape.FramePtr;
1570 Value *GepIndex = createSwitchIndexPtr(Shape, Builder, FramePtr);
1571 auto *Index = Builder.CreateLoad(Shape.getIndexType(), GepIndex, "index");
1572 auto *Switch =
1573 Builder.CreateSwitch(Index, UnreachBB, Shape.CoroSuspends.size());
1575
1576 // Split all coro.suspend calls
1577 size_t SuspendIndex = 0;
1578 SmallVector<uint64_t, 8> SwitchWeights64;
1579 // Default destination (unreachable) has weight 0
1580 SwitchWeights64.push_back(0);
1581
1582 for (auto *AnyS : Shape.CoroSuspends) {
1583 auto *S = cast<CoroSuspendInst>(AnyS);
1584 ConstantInt *IndexVal = Shape.getIndex(SuspendIndex);
1585
1586 // Replace CoroSave with a store to Index:
1587 // %index.addr = getelementptr %f.frame... (index field number)
1588 // store i32 %IndexVal, i32* %index.addr1
1589 auto *Save = S->getCoroSave();
1590 Builder.SetInsertPoint(Save);
1591 if (S->isFinal()) {
1592 // The coroutine should be marked done if it reaches the final suspend
1593 // point.
1594 markCoroutineAsDone(Builder, Shape, FramePtr);
1595 } else {
1596 Value *GepIndex = createSwitchIndexPtr(Shape, Builder, FramePtr);
1597 Builder.CreateStore(IndexVal, GepIndex);
1598 }
1599
1601 Save->eraseFromParent();
1602
1603 // Split block before and after coro.suspend and add a jump from an entry
1604 // switch:
1605 //
1606 // whateverBB:
1607 // whatever
1608 // %0 = call i8 @llvm.coro.suspend(token none, i1 false)
1609 // switch i8 %0, label %suspend[i8 0, label %resume
1610 // i8 1, label %cleanup]
1611 // becomes:
1612 //
1613 // whateverBB:
1614 // whatever
1615 // br label %resume.0.landing
1616 //
1617 // resume.0: ; <--- jump from the switch in the resume.entry
1618 // #dbg_label(...) ; <--- artificial label for debuggers
1619 // %0 = tail call i8 @llvm.coro.suspend(token none, i1 false)
1620 // br label %resume.0.landing
1621 //
1622 // resume.0.landing:
1623 // %1 = phi i8[-1, %whateverBB], [%0, %resume.0]
1624 // switch i8 % 1, label %suspend [i8 0, label %resume
1625 // i8 1, label %cleanup]
1626
1627 auto *SuspendBB = S->getParent();
1628 auto *ResumeBB =
1629 SuspendBB->splitBasicBlock(S, "resume." + Twine(SuspendIndex));
1630 auto *LandingBB = ResumeBB->splitBasicBlock(
1631 S->getNextNode(), ResumeBB->getName() + Twine(".landing"));
1632 Switch->addCase(IndexVal, ResumeBB);
1633
1634 // Get pre-split frequency for this suspend point
1635 uint64_t Weight = 1; // Default fallback weight
1636 auto It = Shape.SuspendFreqs.find(AnyS);
1637 if (It != Shape.SuspendFreqs.end()) {
1638 Weight = It->second;
1639 }
1640 SwitchWeights64.push_back(Weight);
1641
1642 cast<UncondBrInst>(SuspendBB->getTerminator())->setSuccessor(LandingBB);
1643 auto *PN = PHINode::Create(Builder.getInt8Ty(), 2, "");
1644 PN->insertBefore(LandingBB->begin());
1645 S->replaceAllUsesWith(PN);
1646 PN->addIncoming(Builder.getInt8(-1), SuspendBB);
1647 PN->addIncoming(S, ResumeBB);
1648
1649 if (AddDebugLabels) {
1650 if (DebugLoc SuspendLoc = S->getDebugLoc()) {
1651 std::string LabelName =
1652 ("__coro_resume_" + Twine(SuspendIndex)).str();
1653 // Take the "inlined at" location recursively, if present. This is
1654 // mandatory as the DILabel insertion checks that the scopes of label
1655 // and the attached location match. This is not the case when the
1656 // suspend location has been inlined due to pointing to the original
1657 // scope.
1658 DILocation *DILoc = SuspendLoc;
1659 while (DILocation *InlinedAt = DILoc->getInlinedAt())
1660 DILoc = InlinedAt;
1661
1662 DILabel *ResumeLabel =
1663 DBuilder.createLabel(DIS, LabelName, DILoc->getFile(),
1664 SuspendLoc.getLine(), SuspendLoc.getCol(),
1665 /*IsArtificial=*/true,
1666 /*CoroSuspendIdx=*/SuspendIndex,
1667 /*AlwaysPreserve=*/false);
1668 DBuilder.insertLabel(ResumeLabel, DILoc, ResumeBB->begin());
1669 }
1670 }
1671
1672 ++SuspendIndex;
1673 }
1674
1675 if (!Shape.SuspendFreqs.empty()) {
1676 auto SwitchWeights32 = llvm::fitWeights(SwitchWeights64);
1677 MDBuilder MDB(C);
1678 Switch->setMetadata(LLVMContext::MD_prof,
1679 MDB.createBranchWeights(SwitchWeights32));
1680 }
1681
1682 Builder.SetInsertPoint(UnreachBB);
1683 Builder.CreateUnreachable();
1684 DBuilder.finalize();
1685
1686 Shape.SwitchLowering.ResumeEntryBlock = NewEntry;
1687 }
1688
1689 // Store addresses of Resume/Destroy/Cleanup functions in the coroutine frame.
1690 static void updateCoroFrame(coro::Shape &Shape, Function *ResumeFn,
1691 Function *DestroyFn, Function *CleanupFn) {
1692 IRBuilder<> Builder(&*Shape.getInsertPtAfterFramePtr());
1693 LLVMContext &C = ResumeFn->getContext();
1694
1695 // Resume function pointer
1696 Value *ResumeAddr = Shape.FramePtr;
1697 Builder.CreateStore(ResumeFn, ResumeAddr);
1698
1699 Value *DestroyOrCleanupFn = DestroyFn;
1700
1701 CoroIdInst *CoroId = Shape.getSwitchCoroId();
1702 if (CoroAllocInst *CA = CoroId->getCoroAlloc()) {
1703 // If there is a CoroAlloc and it returns false (meaning we elide the
1704 // allocation, use CleanupFn instead of DestroyFn).
1705 DestroyOrCleanupFn = Builder.CreateSelect(CA, DestroyFn, CleanupFn);
1706 applyProfMetadataIfEnabled(DestroyOrCleanupFn, [&](Instruction *Inst) {
1708 CoroId->getFunction());
1709 });
1710 }
1711
1712 // Destroy function pointer
1713 Value *DestroyAddr = Builder.CreateInBoundsPtrAdd(
1714 Shape.FramePtr,
1715 ConstantInt::get(Type::getInt64Ty(C),
1717 "destroy.addr");
1718 Builder.CreateStore(DestroyOrCleanupFn, DestroyAddr);
1719 }
1720
1721 // Create a global constant array containing pointers to functions provided
1722 // and set Info parameter of CoroBegin to point at this constant. Example:
1723 //
1724 // @f.resumers = internal constant [2 x void(%f.frame*)*]
1725 // [void(%f.frame*)* @f.resume, void(%f.frame*)*
1726 // @f.destroy]
1727 // define void @f() {
1728 // ...
1729 // call i8* @llvm.coro.begin(i8* null, i32 0, i8* null,
1730 // i8* bitcast([2 x void(%f.frame*)*] * @f.resumers to
1731 // i8*))
1732 //
1733 // Assumes that all the functions have the same signature.
1734 static void setCoroInfo(Function &F, coro::Shape &Shape,
1736 // This only works under the switch-lowering ABI because coro elision
1737 // only works on the switch-lowering ABI.
1738 SmallVector<Constant *, 4> Args(Fns);
1739 assert(!Args.empty());
1740 Function *Part = *Fns.begin();
1741 Module *M = Part->getParent();
1742 auto *ArrTy = ArrayType::get(Part->getType(), Args.size());
1743
1744 auto *ConstVal = ConstantArray::get(ArrTy, Args);
1745 auto *GV = new GlobalVariable(*M, ConstVal->getType(), /*isConstant=*/true,
1746 GlobalVariable::PrivateLinkage, ConstVal,
1747 F.getName() + Twine(".resumers"));
1748
1749 // Update coro.begin instruction to refer to this constant.
1750 LLVMContext &C = F.getContext();
1751 auto *BC = ConstantExpr::getPointerCast(GV, PointerType::getUnqual(C));
1752 Shape.getSwitchCoroId()->setInfo(BC);
1753 }
1754};
1755
1756} // namespace
1757
1760 auto *ResumeIntrinsic = Suspend->getResumeFunction();
1761 auto &Context = Suspend->getParent()->getParent()->getContext();
1762 auto *Int8PtrTy = PointerType::getUnqual(Context);
1763
1764 IRBuilder<> Builder(ResumeIntrinsic);
1765 auto *Val = Builder.CreateBitOrPointerCast(Continuation, Int8PtrTy);
1766 ResumeIntrinsic->replaceAllUsesWith(Val);
1767 ResumeIntrinsic->eraseFromParent();
1769 PoisonValue::get(Int8PtrTy));
1770}
1771
1772/// Coerce the arguments in \p FnArgs according to \p FnTy in \p CallArgs.
1773static void coerceArguments(IRBuilder<> &Builder, FunctionType *FnTy,
1774 ArrayRef<Value *> FnArgs,
1775 SmallVectorImpl<Value *> &CallArgs) {
1776 size_t ArgIdx = 0;
1777 for (auto *paramTy : FnTy->params()) {
1778 assert(ArgIdx < FnArgs.size());
1779 if (paramTy != FnArgs[ArgIdx]->getType())
1780 CallArgs.push_back(
1781 Builder.CreateBitOrPointerCast(FnArgs[ArgIdx], paramTy));
1782 else
1783 CallArgs.push_back(FnArgs[ArgIdx]);
1784 ++ArgIdx;
1785 }
1786}
1787
1791 IRBuilder<> &Builder) {
1792 auto *FnTy = MustTailCallFn->getFunctionType();
1793 // Coerce the arguments, llvm optimizations seem to ignore the types in
1794 // vaarg functions and throws away casts in optimized mode.
1795 SmallVector<Value *, 8> CallArgs;
1796 coerceArguments(Builder, FnTy, Arguments, CallArgs);
1797
1798 auto *TailCall = Builder.CreateCall(FnTy, MustTailCallFn, CallArgs);
1799 // Skip targets which don't support tail call.
1800 if (TTI.supportsTailCallFor(TailCall)) {
1801 TailCall->setTailCallKind(CallInst::TCK_MustTail);
1802 }
1803 TailCall->setDebugLoc(Loc);
1804 TailCall->setCallingConv(MustTailCallFn->getCallingConv());
1805 return TailCall;
1806}
1807
1812 assert(Clones.empty());
1813 // Reset various things that the optimizer might have decided it
1814 // "knows" about the coroutine function due to not seeing a return.
1815 F.removeFnAttr(Attribute::NoReturn);
1816 F.removeRetAttr(Attribute::NoAlias);
1817 F.removeRetAttr(Attribute::NonNull);
1818
1819 auto &Context = F.getContext();
1820 auto *Int8PtrTy = PointerType::getUnqual(Context);
1821
1822 auto *Id = Shape.getAsyncCoroId();
1823 IRBuilder<> Builder(Id);
1824
1825 auto *FramePtr = Id->getStorage();
1826 FramePtr = Builder.CreateBitOrPointerCast(FramePtr, Int8PtrTy);
1827 FramePtr = Builder.CreateInBoundsPtrAdd(
1828 FramePtr,
1829 ConstantInt::get(Type::getInt64Ty(Context),
1830 Shape.AsyncLowering.FrameOffset),
1831 "async.ctx.frameptr");
1832
1833 // Map all uses of llvm.coro.begin to the allocated frame pointer.
1834 {
1835 // Make sure we don't invalidate Shape.FramePtr.
1836 TrackingVH<Value> Handle(Shape.FramePtr);
1837 Shape.CoroBegin->replaceAllUsesWith(FramePtr);
1838 Shape.FramePtr = Handle.getValPtr();
1839 }
1840
1841 // Create all the functions in order after the main function.
1842 auto NextF = std::next(F.getIterator());
1843
1844 // Create a continuation function for each of the suspend points.
1845 Clones.reserve(Shape.CoroSuspends.size());
1846 for (auto [Idx, CS] : llvm::enumerate(Shape.CoroSuspends)) {
1847 auto *Suspend = cast<CoroSuspendAsyncInst>(CS);
1848
1849 // Create the clone declaration.
1850 auto ResumeNameSuffix = ".resume.";
1851 auto ProjectionFunctionName =
1852 Suspend->getAsyncContextProjectionFunction()->getName();
1853 bool UseSwiftMangling = false;
1854 if (ProjectionFunctionName == "__swift_async_resume_project_context") {
1855 ResumeNameSuffix = "TQ";
1856 UseSwiftMangling = true;
1857 } else if (ProjectionFunctionName == "__swift_async_resume_get_context") {
1858 ResumeNameSuffix = "TY";
1859 UseSwiftMangling = true;
1860 }
1862 F, Shape,
1863 UseSwiftMangling ? ResumeNameSuffix + Twine(Idx) + "_"
1864 : ResumeNameSuffix + Twine(Idx),
1865 NextF, Suspend);
1866 Clones.push_back(Continuation);
1867
1868 // Insert a branch to a new return block immediately before the suspend
1869 // point.
1870 auto *SuspendBB = Suspend->getParent();
1871 auto *NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1872 auto *Branch = cast<UncondBrInst>(SuspendBB->getTerminator());
1873
1874 // Place it before the first suspend.
1875 auto *ReturnBB =
1876 BasicBlock::Create(F.getContext(), "coro.return", &F, NewSuspendBB);
1877 Branch->setSuccessor(0, ReturnBB);
1878
1879 IRBuilder<> Builder(ReturnBB);
1880
1881 // Insert the call to the tail call function and inline it.
1882 auto *Fn = Suspend->getMustTailCallFunction();
1883 SmallVector<Value *, 8> Args(Suspend->args());
1884 auto FnArgs = ArrayRef<Value *>(Args).drop_front(
1886 auto *TailCall = coro::createMustTailCall(Suspend->getDebugLoc(), Fn, TTI,
1887 FnArgs, Builder);
1888 Builder.CreateRetVoid();
1889 InlineFunctionInfo FnInfo;
1890 (void)InlineFunction(*TailCall, FnInfo);
1891
1892 // Replace the lvm.coro.async.resume intrisic call.
1894 }
1895
1896 assert(Clones.size() == Shape.CoroSuspends.size());
1897
1898 for (auto [Idx, CS] : llvm::enumerate(Shape.CoroSuspends)) {
1899 auto *Suspend = CS;
1900 auto *Clone = Clones[Idx];
1901
1902 coro::BaseCloner::createClone(F, "resume." + Twine(Idx), Shape, Clone,
1903 Suspend, TTI);
1904 }
1905}
1906
1911 assert(Clones.empty());
1912
1913 // Reset various things that the optimizer might have decided it
1914 // "knows" about the coroutine function due to not seeing a return.
1915 F.removeFnAttr(Attribute::NoReturn);
1916 F.removeRetAttr(Attribute::NoAlias);
1917 F.removeRetAttr(Attribute::NonNull);
1918
1919 // Allocate the frame.
1920 auto *Id = Shape.getRetconCoroId();
1921 Value *RawFramePtr;
1922 if (Shape.RetconLowering.IsFrameInlineInStorage) {
1923 RawFramePtr = Id->getStorage();
1924 } else {
1925 IRBuilder<> Builder(Id);
1926
1927 auto FrameSize = Builder.getInt64(Shape.FrameSize);
1928
1929 // Allocate. We don't need to update the call graph node because we're
1930 // going to recompute it from scratch after splitting.
1931 // FIXME: pass the required alignment
1932 RawFramePtr = Shape.emitAlloc(Builder, FrameSize, nullptr);
1933 RawFramePtr =
1934 Builder.CreateBitCast(RawFramePtr, Shape.CoroBegin->getType());
1935
1936 // Stash the allocated frame pointer in the continuation storage.
1937 Builder.CreateStore(RawFramePtr, Id->getStorage());
1938 }
1939
1940 // Map all uses of llvm.coro.begin to the allocated frame pointer.
1941 {
1942 // Make sure we don't invalidate Shape.FramePtr.
1943 TrackingVH<Value> Handle(Shape.FramePtr);
1944 Shape.CoroBegin->replaceAllUsesWith(RawFramePtr);
1945 Shape.FramePtr = Handle.getValPtr();
1946 }
1947
1948 // Create a unique return block.
1949 BasicBlock *ReturnBB = nullptr;
1950 PHINode *ContinuationPhi = nullptr;
1951 SmallVector<PHINode *, 4> ReturnPHIs;
1952
1953 // Create all the functions in order after the main function.
1954 auto NextF = std::next(F.getIterator());
1955
1956 // Create a continuation function for each of the suspend points.
1957 Clones.reserve(Shape.CoroSuspends.size());
1958 for (auto [Idx, CS] : llvm::enumerate(Shape.CoroSuspends)) {
1959 auto Suspend = cast<CoroSuspendRetconInst>(CS);
1960
1961 // Create the clone declaration.
1963 F, Shape, ".resume." + Twine(Idx), NextF, nullptr);
1964 Clones.push_back(Continuation);
1965
1966 // Insert a branch to the unified return block immediately before
1967 // the suspend point.
1968 auto SuspendBB = Suspend->getParent();
1969 auto NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1970 auto Branch = cast<UncondBrInst>(SuspendBB->getTerminator());
1971
1972 // Create the unified return block.
1973 if (!ReturnBB) {
1974 // Place it before the first suspend.
1975 ReturnBB =
1976 BasicBlock::Create(F.getContext(), "coro.return", &F, NewSuspendBB);
1977 Shape.RetconLowering.ReturnBlock = ReturnBB;
1978
1979 IRBuilder<> Builder(ReturnBB);
1980
1981 // First, the continuation.
1982 ContinuationPhi =
1983 Builder.CreatePHI(Continuation->getType(), Shape.CoroSuspends.size());
1984
1985 // Create PHIs for all other return values.
1986 assert(ReturnPHIs.empty());
1987
1988 // Next, all the directly-yielded values.
1989 for (auto *ResultTy : Shape.getRetconResultTypes())
1990 ReturnPHIs.push_back(
1991 Builder.CreatePHI(ResultTy, Shape.CoroSuspends.size()));
1992
1993 // Build the return value.
1994 auto RetTy = F.getReturnType();
1995
1996 // Cast the continuation value if necessary.
1997 // We can't rely on the types matching up because that type would
1998 // have to be infinite.
1999 auto CastedContinuationTy =
2000 (ReturnPHIs.empty() ? RetTy : RetTy->getStructElementType(0));
2001 auto *CastedContinuation =
2002 Builder.CreateBitCast(ContinuationPhi, CastedContinuationTy);
2003
2004 Value *RetV = CastedContinuation;
2005 if (!ReturnPHIs.empty()) {
2006 auto ValueIdx = 0;
2007 RetV = PoisonValue::get(RetTy);
2008 RetV = Builder.CreateInsertValue(RetV, CastedContinuation, ValueIdx++);
2009
2010 for (auto Phi : ReturnPHIs)
2011 RetV = Builder.CreateInsertValue(RetV, Phi, ValueIdx++);
2012 }
2013
2014 Builder.CreateRet(RetV);
2015 }
2016
2017 // Branch to the return block.
2018 Branch->setSuccessor(0, ReturnBB);
2019 assert(ContinuationPhi);
2020 ContinuationPhi->addIncoming(Continuation, SuspendBB);
2021 for (auto [Phi, VUse] :
2022 llvm::zip_equal(ReturnPHIs, Suspend->value_operands()))
2023 Phi->addIncoming(VUse, SuspendBB);
2024 }
2025
2026 assert(Clones.size() == Shape.CoroSuspends.size());
2027
2028 for (auto [Idx, CS] : llvm::enumerate(Shape.CoroSuspends)) {
2029 auto Suspend = CS;
2030 auto Clone = Clones[Idx];
2031
2032 coro::BaseCloner::createClone(F, "resume." + Twine(Idx), Shape, Clone,
2033 Suspend, TTI);
2034 }
2035}
2036
2037namespace {
2038class PrettyStackTraceFunction : public PrettyStackTraceEntry {
2039 Function &F;
2040
2041public:
2042 PrettyStackTraceFunction(Function &F) : F(F) {}
2043 void print(raw_ostream &OS) const override {
2044 OS << "While splitting coroutine ";
2045 F.printAsOperand(OS, /*print type*/ false, F.getParent());
2046 OS << "\n";
2047 }
2048};
2049} // namespace
2050
2051/// Remove calls to llvm.coro.end in the original function.
2053 if (Shape.ABI != coro::ABI::Switch) {
2054 for (auto *End : Shape.CoroEnds) {
2055 replaceCoroEnd(End, Shape, Shape.FramePtr, /*in ramp*/ true, nullptr);
2056 }
2057 } else {
2058 for (llvm::AnyCoroEndInst *End : Shape.CoroEnds)
2059 End->eraseFromParent();
2060 }
2061}
2062
2064 for (auto *II : Shape.CoroIsInRampInsts) {
2065 auto &Ctx = II->getContext();
2066 II->replaceAllUsesWith(ConstantInt::getTrue(Ctx));
2067 II->eraseFromParent();
2068 }
2069}
2070
2072 for (auto *U : F.users()) {
2073 if (auto *CB = dyn_cast<CallBase>(U)) {
2074 auto *Caller = CB->getFunction();
2075 if (Caller && Caller->isPresplitCoroutine() &&
2076 CB->hasFnAttr(llvm::Attribute::CoroElideSafe))
2077 return true;
2078 }
2079 }
2080 return false;
2081}
2082
2086 SwitchCoroutineSplitter::split(F, Shape, Clones, TTI);
2087}
2088
2091 bool OptimizeFrame) {
2092 PrettyStackTraceFunction prettyStackTrace(F);
2093
2094 auto &Shape = ABI.Shape;
2095 assert(Shape.CoroBegin);
2096
2097 lowerAwaitSuspends(F, Shape);
2098
2099 simplifySuspendPoints(Shape);
2100
2101 normalizeCoroutine(F, Shape, TTI);
2102 ABI.buildCoroutineFrame(OptimizeFrame);
2104
2105 bool isNoSuspendCoroutine = Shape.CoroSuspends.empty();
2106
2107 bool shouldCreateNoAllocVariant =
2108 !isNoSuspendCoroutine && Shape.ABI == coro::ABI::Switch &&
2109 hasSafeElideCaller(F) && !F.hasFnAttribute(llvm::Attribute::NoInline);
2110 if (Shape.ABI == coro::ABI::Switch)
2112 shouldCreateNoAllocVariant;
2113
2114 // If there are no suspend points, no split required, just remove
2115 // the allocation and deallocation blocks, they are not needed.
2116 if (isNoSuspendCoroutine) {
2118 } else {
2119 ABI.splitCoroutine(F, Shape, Clones, TTI);
2120 }
2121
2122 // Replace all the swifterror operations in the original function.
2123 // This invalidates SwiftErrorOps in the Shape.
2124 replaceSwiftErrorOps(F, Shape, nullptr);
2125
2126 // Salvage debug intrinsics that point into the coroutine frame in the
2127 // original function. The Cloner has already salvaged debug info in the new
2128 // coroutine funclets.
2130 auto DbgVariableRecords = collectDbgVariableRecords(F);
2131 for (DbgVariableRecord *DVR : DbgVariableRecords)
2132 coro::salvageDebugInfo(ArgToAllocaMap, *DVR, false /*UseEntryValue*/);
2133
2136
2137 if (shouldCreateNoAllocVariant)
2138 SwitchCoroutineSplitter::createNoAllocVariant(F, Shape, Clones);
2139}
2140
2142 LazyCallGraph::Node &N, const coro::Shape &Shape,
2146
2147 auto *CurrentSCC = &C;
2148 if (!Clones.empty()) {
2149 switch (Shape.ABI) {
2150 case coro::ABI::Switch:
2151 // The resume clone's elided-frame check holds a reference to the cleanup
2152 // clone. Add the cleanup clone first, so populating the resume node does
2153 // not materialize an unregistered cleanup node.
2155 assert(Clones.size() >= 3 && "expected switch coroutine clones");
2156 CG.addSplitFunction(N.getFunction(), *Clones[2]);
2157 CG.addSplitFunction(N.getFunction(), *Clones[1]);
2158 CG.addSplitFunction(N.getFunction(), *Clones[0]);
2159 for (Function *Clone : drop_begin(Clones, 3))
2160 CG.addSplitFunction(N.getFunction(), *Clone);
2161 } else {
2162 // Each clone in the Switch lowering is independent of the other
2163 // clones. Let the LazyCallGraph know about each one separately.
2164 for (Function *Clone : Clones)
2165 CG.addSplitFunction(N.getFunction(), *Clone);
2166 }
2167 break;
2168 case coro::ABI::Async:
2169 case coro::ABI::Retcon:
2171 // Each clone in the Async/Retcon lowering references of the other clones.
2172 // Let the LazyCallGraph know about all of them at once.
2173 if (!Clones.empty())
2174 CG.addSplitRefRecursiveFunctions(N.getFunction(), Clones);
2175 break;
2176 }
2177
2178 // Let the CGSCC infra handle the changes to the original function.
2179 CurrentSCC = &updateCGAndAnalysisManagerForCGSCCPass(CG, *CurrentSCC, N, AM,
2180 UR, FAM);
2181 }
2182
2183 // Do some cleanup and let the CGSCC infra see if we've cleaned up any edges
2184 // to the split functions.
2185 postSplitCleanup(N.getFunction());
2186 CurrentSCC = &updateCGAndAnalysisManagerForFunctionPass(CG, *CurrentSCC, N,
2187 AM, UR, FAM);
2188 return *CurrentSCC;
2189}
2190
2191/// Replace a call to llvm.coro.prepare.retcon.
2192static void replacePrepare(CallInst *Prepare, LazyCallGraph &CG,
2194 auto CastFn = Prepare->getArgOperand(0); // as an i8*
2195 auto Fn = CastFn->stripPointerCasts(); // as its original type
2196
2197 // Attempt to peephole this pattern:
2198 // %0 = bitcast [[TYPE]] @some_function to i8*
2199 // %1 = call @llvm.coro.prepare.retcon(i8* %0)
2200 // %2 = bitcast %1 to [[TYPE]]
2201 // ==>
2202 // %2 = @some_function
2203 for (Use &U : llvm::make_early_inc_range(Prepare->uses())) {
2204 // Look for bitcasts back to the original function type.
2205 auto *Cast = dyn_cast<BitCastInst>(U.getUser());
2206 if (!Cast || Cast->getType() != Fn->getType())
2207 continue;
2208
2209 // Replace and remove the cast.
2210 Cast->replaceAllUsesWith(Fn);
2211 Cast->eraseFromParent();
2212 }
2213
2214 // Replace any remaining uses with the function as an i8*.
2215 // This can never directly be a callee, so we don't need to update CG.
2216 Prepare->replaceAllUsesWith(CastFn);
2217 Prepare->eraseFromParent();
2218
2219 // Kill dead bitcasts.
2220 while (auto *Cast = dyn_cast<BitCastInst>(CastFn)) {
2221 if (!Cast->use_empty())
2222 break;
2223 CastFn = Cast->getOperand(0);
2224 Cast->eraseFromParent();
2225 }
2226}
2227
2228static bool replaceAllPrepares(Function *PrepareFn, LazyCallGraph &CG,
2230 bool Changed = false;
2231 for (Use &P : llvm::make_early_inc_range(PrepareFn->uses())) {
2232 // Intrinsics can only be used in calls.
2233 auto *Prepare = cast<CallInst>(P.getUser());
2234 replacePrepare(Prepare, CG, C);
2235 Changed = true;
2236 }
2237
2238 return Changed;
2239}
2240
2241static void addPrepareFunction(const Module &M,
2243 StringRef Name) {
2244 auto *PrepareFn = M.getFunction(Name);
2245 if (PrepareFn && !PrepareFn->use_empty())
2246 Fns.push_back(PrepareFn);
2247}
2248
2249static std::unique_ptr<coro::BaseABI>
2251 std::function<bool(Instruction &)> IsMatCallback,
2252 const SmallVector<CoroSplitPass::BaseABITy> GenCustomABIs) {
2253 if (S.CoroBegin->hasCustomABI()) {
2254 unsigned CustomABI = S.CoroBegin->getCustomABI();
2255 if (CustomABI >= GenCustomABIs.size())
2256 llvm_unreachable("Custom ABI not found amoung those specified");
2257 return GenCustomABIs[CustomABI](F, S);
2258 }
2259
2260 switch (S.ABI) {
2261 case coro::ABI::Switch:
2262 return std::make_unique<coro::SwitchABI>(F, S, IsMatCallback);
2263 case coro::ABI::Async:
2264 return std::make_unique<coro::AsyncABI>(F, S, IsMatCallback);
2265 case coro::ABI::Retcon:
2266 return std::make_unique<coro::AnyRetconABI>(F, S, IsMatCallback);
2268 return std::make_unique<coro::AnyRetconABI>(F, S, IsMatCallback);
2269 }
2270 llvm_unreachable("Unknown ABI");
2271}
2272
2274 : CreateAndInitABI([](Function &F, coro::Shape &S) {
2275 std::unique_ptr<coro::BaseABI> ABI =
2277 ABI->init();
2278 return ABI;
2279 }),
2280 OptimizeFrame(OptimizeFrame) {}
2281
2284 : CreateAndInitABI([=](Function &F, coro::Shape &S) {
2285 std::unique_ptr<coro::BaseABI> ABI =
2287 ABI->init();
2288 return ABI;
2289 }),
2290 OptimizeFrame(OptimizeFrame) {}
2291
2292// For back compatibility, constructor takes a materializable callback and
2293// creates a generator for an ABI with a modified materializable callback.
2294CoroSplitPass::CoroSplitPass(std::function<bool(Instruction &)> IsMatCallback,
2295 bool OptimizeFrame)
2296 : CreateAndInitABI([=](Function &F, coro::Shape &S) {
2297 std::unique_ptr<coro::BaseABI> ABI =
2298 CreateNewABI(F, S, IsMatCallback, {});
2299 ABI->init();
2300 return ABI;
2301 }),
2302 OptimizeFrame(OptimizeFrame) {}
2303
2304// For back compatibility, constructor takes a materializable callback and
2305// creates a generator for an ABI with a modified materializable callback.
2307 std::function<bool(Instruction &)> IsMatCallback,
2309 : CreateAndInitABI([=](Function &F, coro::Shape &S) {
2310 std::unique_ptr<coro::BaseABI> ABI =
2311 CreateNewABI(F, S, IsMatCallback, GenCustomABIs);
2312 ABI->init();
2313 return ABI;
2314 }),
2315 OptimizeFrame(OptimizeFrame) {}
2316
2320 // NB: One invariant of a valid LazyCallGraph::SCC is that it must contain a
2321 // non-zero number of nodes, so we assume that here and grab the first
2322 // node's function's module.
2323 Module &M = *C.begin()->getFunction().getParent();
2324 auto &FAM =
2325 AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
2326
2327 // Check for uses of llvm.coro.prepare.retcon/async.
2328 SmallVector<Function *, 2> PrepareFns;
2329 addPrepareFunction(M, PrepareFns, "llvm.coro.prepare.retcon");
2330 addPrepareFunction(M, PrepareFns, "llvm.coro.prepare.async");
2331
2332 // Find coroutines for processing.
2334 for (LazyCallGraph::Node &N : C)
2335 if (N.getFunction().isPresplitCoroutine())
2336 Coroutines.push_back(&N);
2337
2338 if (Coroutines.empty() && PrepareFns.empty())
2339 return PreservedAnalyses::all();
2340
2341 auto *CurrentSCC = &C;
2342 // Split all the coroutines.
2343 for (LazyCallGraph::Node *N : Coroutines) {
2344 Function &F = N->getFunction();
2345 LLVM_DEBUG(dbgs() << "CoroSplit: Processing coroutine '" << F.getName()
2346 << "\n");
2347
2348 // The suspend-crossing algorithm in buildCoroutineFrame gets tripped up
2349 // by unreachable blocks, so remove them as a first pass. Remove the
2350 // unreachable blocks before collecting intrinsics into Shape.
2352
2353 coro::Shape Shape(F);
2354 if (!Shape.CoroBegin)
2355 continue;
2356
2357 F.setSplittedCoroutine();
2358
2359 // Query BFI and populate SuspendFreqs right before splitting.
2360 auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
2361 for (auto *AnyS : Shape.CoroSuspends) {
2362 BasicBlock *BB = AnyS->getParent();
2363 uint64_t Freq = BFI.getBlockFreq(BB).getFrequency();
2364 Shape.SuspendFreqs[AnyS] = Freq;
2365
2366 // Query BFI to get the actual estimated execution profile count of the
2367 // basic block where this suspension point resides.
2368 std::optional<uint64_t> Count =
2369 BFI.getBlockProfileCount(BB, /*AllowSynthetic=*/true);
2370 if (Count.has_value()) {
2371 if (!Shape.ResumeEntryCount.has_value()) {
2372 // For the first suspend point visited, initialize the total sum.
2373 Shape.ResumeEntryCount = Count.value();
2374 } else {
2375 // Accumulate the absolute execution count of each subsequent suspend
2376 // point into the total sum.
2377 Shape.ResumeEntryCount.value() += Count.value();
2378 }
2379 }
2380 }
2381
2382 std::unique_ptr<coro::BaseABI> ABI = CreateAndInitABI(F, Shape);
2383
2385 auto &TTI = FAM.getResult<TargetIRAnalysis>(F);
2386 doSplitCoroutine(F, Clones, *ABI, TTI, OptimizeFrame);
2388 *N, Shape, Clones, *CurrentSCC, CG, AM, UR, FAM);
2389
2390 auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
2391 ORE.emit([&]() {
2392 return OptimizationRemark(DEBUG_TYPE, "CoroSplit", &F)
2393 << "Split '" << ore::NV("function", F.getName())
2394 << "' (frame_size=" << ore::NV("frame_size", Shape.FrameSize)
2395 << ", align=" << ore::NV("align", Shape.FrameAlign.value()) << ")";
2396 });
2397
2398 if (!Shape.CoroSuspends.empty()) {
2399 // Run the CGSCC pipeline on the original and newly split functions.
2400 UR.CWorklist.insert(CurrentSCC);
2401 for (Function *Clone : Clones)
2402 UR.CWorklist.insert(CG.lookupSCC(CG.get(*Clone)));
2403 } else if (Shape.ABI == coro::ABI::Async) {
2404 // Reprocess the function to inline the tail called return function of
2405 // coro.async.end.
2406 UR.CWorklist.insert(&C);
2407 }
2408 }
2409
2410 for (auto *PrepareFn : PrepareFns) {
2411 replaceAllPrepares(PrepareFn, CG, *CurrentSCC);
2412 }
2413
2414 return PreservedAnalyses::none();
2415}
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:168
const BasicBlock & getEntryBlock() const
Definition Function.h:793
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition Function.h:211
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Definition Function.h:246
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:272
AttributeList getAttributes() const
Return the attribute list for this Function.
Definition Function.h:328
void setAttributes(AttributeList Attrs)
Set the attribute list for this Function.
Definition Function.h:331
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:353
size_t arg_size() const
Definition Function.h:885
Argument * getArg(unsigned i) const
Definition Function.h:870
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:2300
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2385
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:2903
This class captures the data input to the InlineFunction call, and records the auxiliary results prod...
Definition Cloning.h:259
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
A node in the call graph.
An SCC of the call graph.
A lazily constructed view of the call graph of a module.
LLVM_ABI void addSplitFunction(Function &OriginalFunction, Function &NewFunction)
Add a new function split/outlined from an existing function.
LLVM_ABI void addSplitRefRecursiveFunctions(Function &OriginalFunction, ArrayRef< Function * > NewFunctions)
Add new ref-recursive functions split/outlined from an existing function.
Node & get(Function &F)
Get a graph node for a given function, scanning it to populate the graph data as necessary.
SCC * lookupSCC(Node &N) const
Lookup a function's SCC in the graph.
static std::enable_if_t< std::is_base_of< MDNode, T >::value, T * > replaceWithUniqued(std::unique_ptr< T, TempMDNodeDeleter > N)
Replace a temporary node with a uniqued one.
Definition Metadata.h:1301
A single uniqued string.
Definition Metadata.h:722
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
Definition Metadata.cpp:615
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
FunctionListType::iterator iterator
The Function iterators.
Definition Module.h:92
Diagnostic information for applied optimization remarks.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PrettyStackTraceEntry - This class is used to represent a frame of the "pretty" stack trace that is d...
Return a value (possibly void), from a function.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
A wrapper class to simplify modification of SwitchInst cases along with their prof branch_weights met...
LLVM_ABI SwitchInst::CaseIt removeCase(SwitchInst::CaseIt I)
Delegate the call to the underlying SwitchInst::removeCase() and remove correspondent branch weight.
Analysis pass providing the TargetTransformInfo.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
Value handle that tracks a Value across RAUW.
ValueTy * getValPtr() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:343
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
Definition Type.cpp:310
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:282
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:307
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
void setOperand(unsigned i, Value *Val)
Definition User.h:212
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:258
iterator_range< user_iterator > users()
Definition Value.h:426
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition Value.cpp:713
iterator_range< use_iterator > uses()
Definition Value.h:380
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
void splitCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones, TargetTransformInfo &TTI) override
void splitCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones, TargetTransformInfo &TTI) override
Function & F
Definition ABI.h:59
coro::Shape & Shape
Definition ABI.h:60
AnyCoroSuspendInst * ActiveSuspend
The active suspend instruction; meaningful only for continuation and async ABIs.
Definition CoroCloner.h:57
Value * deriveNewFramePointer()
Derive the value of the new frame pointer.
TargetTransformInfo & TTI
Definition CoroCloner.h:49
coro::Shape & Shape
Definition CoroCloner.h:46
static Function * createClone(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, Function *NewF, AnyCoroSuspendInst *ActiveSuspend, TargetTransformInfo &TTI)
Create a clone for a continuation lowering.
Definition CoroCloner.h:83
ValueToValueMapTy VMap
Definition CoroCloner.h:51
const Twine & Suffix
Definition CoroCloner.h:45
void replaceRetconOrAsyncSuspendUses()
Replace uses of the active llvm.coro.suspend.retcon/async call with the arguments to the continuation...
virtual void create()
Clone the body of the original function into a resume function of some sort.
void splitCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones, TargetTransformInfo &TTI) override
static Function * createClone(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, CloneKind FKind, TargetTransformInfo &TTI)
Create a clone for a switch lowering.
Definition CoroCloner.h:139
void create() override
Clone the body of the original function into a resume function of some sort.
const ParentTy * getParent() const
Definition ilist_node.h:34
self_iterator getIterator()
Definition ilist_node.h:123
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition ilist_node.h:348
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
CallInst * Call
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ Async
The "async continuation" lowering, where each suspend point creates a single continuation function.
Definition CoroShape.h:49
@ RetconOnce
The "unique returned-continuation" lowering, where each suspend point creates a single continuation f...
Definition CoroShape.h:44
@ Retcon
The "returned-continuation" lowering, where each suspend point creates a single continuation function...
Definition CoroShape.h:37
@ Switch
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
Definition CoroShape.h:32
void suppressCoroAllocs(CoroIdInst *CoroId)
Replaces all @llvm.coro.alloc intrinsics calls associated with a given call @llvm....
void normalizeCoroutine(Function &F, coro::Shape &Shape, TargetTransformInfo &TTI)
CallInst * createMustTailCall(DebugLoc Loc, Function *MustTailCallFn, TargetTransformInfo &TTI, ArrayRef< Value * > Arguments, IRBuilder<> &)
LLVM_ABI bool isTriviallyMaterializable(Instruction &I)
@ SwitchCleanup
The shared cleanup function for a switch lowering.
Definition CoroCloner.h:33
@ SwitchResume
The shared resume function for a switch lowering.
Definition CoroCloner.h:27
@ Continuation
An individual continuation function.
Definition CoroCloner.h:36
void elideCoroFree(Value *FramePtr)
void salvageDebugInfo(SmallDenseMap< Argument *, AllocaInst *, 4 > &ArgToAllocaMap, DbgVariableRecord &DVR, bool UseEntryValue)
Attempts to rewrite the location operand of debug records in terms of the coroutine frame pointer,...
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
@ Offset
Definition DWP.cpp:578
auto cast_if_present(const Y &Val)
cast_if_present<X> - Functionally identical to cast, except that a null value is accepted.
Definition Casting.h:683
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1732
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
Definition STLExtras.h:840
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
LLVM_ABI void setExplicitlyUnknownBranchWeightsIfProfiled(Instruction &I, StringRef PassName, const Function *F=nullptr)
Like setExplicitlyUnknownBranchWeights(...), but only sets unknown branch weights in the new instruct...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
@ Load
The value being inserted comes from a load (InsertElement only).
LLVM_ABI LazyCallGraph::SCC & updateCGAndAnalysisManagerForFunctionPass(LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM)
Helper to update the call graph after running a function pass.
LLVM_ABI LazyCallGraph::SCC & updateCGAndAnalysisManagerForCGSCCPass(LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM)
Helper to update the call graph after running a CGSCC pass.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
LLVM_ABI void applyProfMetadataIfEnabled(Value *V, llvm::function_ref< void(Instruction *)> setMetadataCallback)
bool isa_and_nonnull(const Y &Val)
Definition Casting.h:676
LLVM_ABI InlineResult InlineFunction(CallBase &CB, InlineFunctionInfo &IFI, bool MergeAttributes=false, AAResults *CalleeAAR=nullptr, bool InsertLifetime=true, bool TrackInlineHistory=false, Function *ForwardVarArgsTo=nullptr, OptimizationRemarkEmitter *ORE=nullptr)
This function inlines the called function into the basic block of the caller.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
AnalysisManager< LazyCallGraph::SCC, LazyCallGraph & > CGSCCAnalysisManager
The CGSCC analysis manager.
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:2912
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
LLVM_ABI BasicBlock::iterator skipDebugIntrinsics(BasicBlock::iterator It)
Advance It while it points to a debug instruction and return the result.
LLVM_ABI SmallVector< uint32_t > fitWeights(ArrayRef< uint64_t > Weights)
Push the weights right to fit in uint32_t.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
iterator_range< SplittingIterator > split(StringRef Str, StringRef Separator)
Split the specified string over a separator and return a range-compatible iterable over its partition...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI unsigned changeToUnreachable(Instruction *I, bool PreserveLCSSA=false, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Insert an unreachable instruction before the specified instruction, making it and the rest of the cod...
Definition Local.cpp:2543
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
TargetTransformInfo TTI
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr, const CycleInfo *CI=nullptr)
Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...
Definition CFG.cpp:335
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
LLVM_ABI void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, CloneFunctionChangeType Changes, SmallVectorImpl< ReturnInst * > &Returns, const char *NameSuffix="", ClonedCodeInfo *CodeInfo=nullptr, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr)
Clone OldFunc into NewFunc, transforming the old arguments into references to VMap values.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto predecessors(const MachineBasicBlock *BB)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
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