Movatterモバイル変換


[0]ホーム

URL:


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

Generated on Sun Jul 20 2025 13:18:37 for LLVM by doxygen 1.9.6
[8]ページ先頭

©2009-2025 Movatter.jp