67 #include <initializer_list> 72 #define DEBUG_TYPE "coro-split" 102 size_t SuspendIndex = 0;
116 cast<PointerType>(GepIndex->getType())->getElementType()));
124 Save->eraseFromParent();
154 Switch->addCase(IndexVal, ResumeBB);
156 cast<BranchInst>(SuspendBB->getTerminator())->setSuccessor(0, LandingBB);
159 PN->addIncoming(Builder.
getInt8(-1), SuspendBB);
160 PN->addIncoming(S, ResumeBB);
175 auto *NewE = cast<IntrinsicInst>(VMap[End]);
196 auto *NewCE = cast<IntrinsicInst>(VMap[CE]);
200 Value *FromPad = Bundle->Inputs[0];
202 NewCE->getParent()->splitBasicBlock(NewCE);
203 CleanupRet->getParent()->getTerminator()->eraseFromParent();
206 NewCE->replaceAllUsesWith(True);
207 NewCE->eraseFromParent();
224 auto FinalCaseIt = std::prev(Switch->
case_end());
225 BasicBlock *ResumeBB = FinalCaseIt->getCaseSuccessor();
232 0, 0,
"ResumeFn.addr");
249 auto *FnPtrTy = cast<PointerType>(FrameTy->getElementType(0));
250 auto *FnTy = cast<FunctionType>(FnPtrTy->getElementType());
268 NewF->setLinkage(GlobalValue::LinkageTypes::InternalLinkage);
275 NewF->removeAttributes(
280 auto *SwitchBB = cast<BasicBlock>(VMap[ResumeEntry]);
282 Entry->moveBefore(&NewF->getEntryBlock());
283 Entry->getTerminator()->eraseFromParent();
285 Entry->setName(
"entry" + Suffix);
288 auto *Switch = cast<SwitchInst>(VMap[Shape.
ResumeSwitch]);
289 Entry->replaceAllUsesWith(Switch->getDefaultDest());
291 IRBuilder<> Builder(&NewF->getEntryBlock().front());
294 Argument *NewFramePtr = &*NewF->arg_begin();
296 NewFramePtr->takeName(OldFramePtr);
300 auto *NewVFrame = Builder.CreateBitCast(
309 auto *Switch = cast<SwitchInst>(VMap[Shape.
ResumeSwitch]);
310 bool IsDestroy = FnIndex != 0;
319 auto *NewValue = Builder.getInt8(FnIndex ? 1 : 0);
321 auto *MappedCS = cast<CoroSuspendInst>(VMap[CS]);
322 MappedCS->replaceAllUsesWith(NewValue);
323 MappedCS->eraseFromParent();
357 auto *SizeIntrin = Shape.
CoroSizes.back();
358 Module *M = SizeIntrin->getModule();
381 std::initializer_list<Function *> Fns) {
385 Module *M = Part->getParent();
406 Builder.CreateStore(ResumeFn, ResumeAddr);
408 Value *DestroyOrCleanupFn = DestroyFn;
414 DestroyOrCleanupFn = Builder.CreateSelect(CA, DestroyFn, CleanupFn);
417 auto *DestroyAddr = Builder.CreateConstInBoundsGEP2_32(
420 Builder.CreateStore(DestroyOrCleanupFn, DestroyAddr);
433 FPM.doInitialization();
435 FPM.doFinalization();
445 auto V = PN.getIncomingValueForBlock(PrevBB);
447 auto VI = ResolvedValues.
find(V);
448 if (
VI != ResolvedValues.
end())
451 ResolvedValues[&PN] = V;
463 if (isa<ReturnInst>(I)) {
464 if (I != InitialInst)
468 if (
auto *
BR = dyn_cast<BranchInst>(I)) {
469 if (
BR->isUnconditional()) {
475 }
else if (
auto *
SI = dyn_cast<SwitchInst>(I)) {
477 auto it = ResolvedValues.
find(V);
478 if (it != ResolvedValues.
end())
481 BasicBlock *BB =
SI->findCaseValue(Cond)->getCaseSuccessor();
498 bool changed =
false;
503 if (
auto *Call = dyn_cast<CallInst>(&
I))
504 if (
auto *CalledValue = Call->getCalledValue())
507 if (isa<CoroSubFnInst>(CalledValue->stripPointerCasts()))
524 auto *CoroId = CoroBegin->
getId();
533 AllocInst->eraseFromParent();
547 if (isa<IntrinsicInst>(
I))
566 while (!Worklist.
empty()) {
570 if (Set.
count(Pred) == 0)
587 auto *ResumeOrDestroyBB = ResumeOrDestroy->
getParent();
589 if (SaveBB == ResumeOrDestroyBB)
617 Prev = Pred->getTerminator();
624 auto *CallInstr = CS.getInstruction();
634 if (SubFn->getFrame() != CoroBegin)
648 Save->eraseFromParent();
651 if (
auto *Invoke = dyn_cast<InvokeInst>(CallInstr)) {
656 auto *CalledValue = CS.getCalledValue();
660 if (CalledValue != SubFn && CalledValue->user_empty())
661 if (
auto *
I = dyn_cast<Instruction>(CalledValue))
662 I->eraseFromParent();
665 if (SubFn->user_empty())
666 SubFn->eraseFromParent();
674 size_t I = 0,
N = S.size();
699 if (RelocBlocks.
count(BB) == 0) {
703 }
while (!Work.
empty());
718 if (BB != CoroBeginBB)
725 LLVM_DEBUG(
dbgs() <<
"CoroSplit: Will not relocate: " << *Current <<
"\n");
726 DoNotRelocate.
insert(Current);
732 if (
auto *A = dyn_cast<AllocaInst>(
I)) {
737 for (
const auto &
User : A->users())
738 if (
auto *
SI = dyn_cast<llvm::StoreInst>(
User))
739 if (RelocBlocks.count(
SI->getParent()) != 0 &&
740 DoNotRelocate.
count(
SI) == 0) {
747 if (DoNotRelocate.
count(
I) == 0) {
752 }
while (!Work.
empty());
753 return DoNotRelocate;
769 if (isa<AllocaInst>(&I))
773 if (DoNotRelocateSet.count(&I))
800 auto ResumeClone =
createClone(F,
".resume", Shape, ResumeEntry, 0);
801 auto DestroyClone =
createClone(F,
".destroy", Shape, ResumeEntry, 1);
802 auto CleanupClone =
createClone(F,
".cleanup", Shape, ResumeEntry, 2);
833 assert(DevirtFn &&
"coro.devirt.trigger function not found");
896 bool doInitialization(
CallGraph &CG)
override {
908 if (
auto *
F = CGN->getFunction())
912 if (Coroutines.
empty())
915 CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
921 LLVM_DEBUG(
dbgs() <<
"CoroSplit: Processing coroutine '" <<
F->getName()
922 <<
"' state: " << Value <<
"\n");
937 StringRef getPassName()
const override {
return "Coroutine Splitting"; }
945 CoroSplit,
"coro-split",
946 "Split coroutine into a set of functions driving its state machine",
false,
Pass interface - Implemented by all 'passes'.
Return a value (possibly void), from a function.
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
A parsed version of the target data layout string in and methods for querying it. ...
static ConstantInt * getFalse(LLVMContext &Context)
static void createDevirtTriggerFunc(CallGraph &CG, CallGraphSCC &SCC)
BranchInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
CaseIt case_end()
Returns a read/write iterator that points one past the last in the SwitchInst.
void ReplaceInstWithInst(BasicBlock::InstListType &BIL, BasicBlock::iterator &BI, Instruction *I)
Replace the instruction specified by BI with the instruction specified by I.
static void setCoroInfo(Function &F, CoroBeginInst *CoroBegin, std::initializer_list< Function *> Fns)
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
This class represents an incoming formal argument to a Function.
AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")
CoroBeginInst * CoroBegin
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
This represents the llvm.coro.alloc instruction.
This class represents lattice values for constants.
static void addMustTailToCoroResumes(Function &F)
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
adds the attribute to the list of attributes for the given arg.
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
A Module instance is used to store all the information related to an LLVM module. ...
static void splitCoroutine(Function &F, CallGraph &CG, CallGraphSCC &SCC)
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
void push_back(const T &Elt)
bool removeUnreachableBlocks(Function &F, LazyValueInfo *LVI=nullptr, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
Pass * createCoroSplitPass()
Split up coroutines into multiple functions driving their state machines.
static void relocateInstructionBefore(CoroBeginInst *CoroBegin, Function &F)
This class represents a function call, abstracting a target machine's calling convention.
virtual bool doInitialization(CallGraph &CG)
doInitialization - This method is called before the SCC's of the program has been processed...
FunctionPass * createVerifierPass(bool FatalErrors=true)
Like Internal, but omit from symbol table.
bool isTerminator() const
static void replaceFrameSize(coro::Shape &Shape)
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...
A node in the call graph for a module.
void getAnalysisUsage(AnalysisUsage &Info) const override
getAnalysisUsage - For this class, we declare that we require and preserve the call graph...
Module & getModule() const
Returns the module the call graph corresponds to.
static Constant * get(ArrayType *T, ArrayRef< Constant *> V)
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
iterator begin()
Instruction iterator methods.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, Instruction *InsertBefore=nullptr)
FunctionPass * createCFGSimplificationPass(unsigned Threshold=1, bool ForwardSwitchCond=false, bool ConvertSwitch=false, bool KeepLoops=true, bool SinkCommon=false, std::function< bool(const Function &)> Ftor=nullptr)
static bool simplifySuspendPoint(CoroSuspendInst *Suspend, CoroBeginInst *CoroBegin)
void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, bool ModuleLevelChanges, 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...
unsigned changeToUnreachable(Instruction *I, bool UseLLVMTrap, bool PreserveLCSSA=false, DomTreeUpdater *DTU=nullptr)
Insert an unreachable instruction before the specified instruction, making it and the rest of the cod...
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static void handleNoSuspendCoroutine(CoroBeginInst *CoroBegin, Type *FrameTy)
LLVMContext & getContext() const
Get the global data context.
This represents the llvm.coro.suspend instruction.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
This file contains the simple types necessary to represent the attributes associated with functions a...
static void scanPHIsAndUpdateValueMap(Instruction *Prev, BasicBlock *NewBlock, DenseMap< Value *, Value *> &ResolvedValues)
FunctionPass * createSCCPPass()
This class represents the llvm.coro.subfn.addr instruction.
#define PREPARED_FOR_SPLIT
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following: ...
const Instruction * getFirstNonPHIOrDbgOrLifetime() const
Returns a pointer to the first instruction in this block that is not a PHINode, a debug intrinsic...
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
Fast - This calling convention attempts to make calls as fast as possible (e.g.
ConstantInt * getIndex(uint64_t Value) const
void initializeCoroSplitPass(PassRegistry &)
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
static void replaceFallthroughCoroEnd(IntrinsicInst *End, ValueToValueMapTy &VMap)
This represents the llvm.coro.alloc instruction.
SmallVector< CoroSizeInst *, 2 > CoroSizes
void add(Pass *P) override
Add a pass to the queue of passes to run.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
static void simplifySuspendPoints(coro::Shape &Shape)
SmallVector< CoroSuspendInst *, 4 > CoroSuspends
amdgpu Simplify well known AMD library false Value * Callee
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block...
iterator find(const_arg_type_t< KeyT > Val)
const BasicBlock & getEntryBlock() const
This represents the llvm.coro.size instruction.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
static void postSplitCleanup(Function &F)
Control flow instructions. These all have token chains.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
CallGraphNode * getCallsExternalNode() const
LLVM Basic Block Representation.
#define CORO_PRESPLIT_ATTR
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
UnreachableInst * CreateUnreachable()
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
static void prepareForSplit(Function &F, CallGraph &CG)
Represent the analysis usage information of a pass.
static Type * getVoidTy(LLVMContext &C)
This represents the llvm.coro.end instruction.
static bool hasCallsBetween(Instruction *Save, Instruction *ResumeOrDestroy)
static FunctionType * get(Type *Result, ArrayRef< Type *> Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
void initialize(ArrayRef< CallGraphNode *> NewNodes)
static bool hasCallsInBlocksBetween(BasicBlock *SaveBB, BasicBlock *ResDesBB)
CaseIt removeCase(CaseIt I)
This method removes the specified case and its successor from the switch instruction.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
static void replaceUnwindCoroEnds(coro::Shape &Shape, ValueToValueMapTy &VMap)
FunctionPassManager manages FunctionPasses and BasicBlockPassManagers.
static Function * createClone(Function &F, Twine Suffix, coro::Shape &Shape, BasicBlock *ResumeEntry, int8_t FnIndex)
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs, and aliases.
PointerType * getInt8PtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer to an 8-bit integer value.
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
static SmallPtrSet< BasicBlock *, 4 > getCoroBeginPredBlocks(CoroBeginInst *CB)
static bool hasCallsInBlockBetween(Instruction *From, Instruction *To)
static Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
This is the shared class of boolean and integer constants.
BlockVerifier::State From
bool erase(PtrType Ptr)
erase - If the set contains the specified pointer, remove it and return true, otherwise return false...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
LLVM_NODISCARD T pop_back_val()
void buildCoroutineFrame(Function &F, Shape &Shape)
#define UNPREPARED_FOR_SPLIT
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=nullptr)
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
pred_range predecessors(BasicBlock *BB)
static ConstantInt * getTrue(LLVMContext &Context)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Function * getFunction(StringRef Name) const
Look up the specified function in the module symbol table.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This class represents the llvm.coro.begin instruction.
Value * makeSubFnCall(Value *Arg, int Index, Instruction *InsertPt)
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
static void updateCoroFrame(coro::Shape &Shape, Function *ResumeFn, Function *DestroyFn, Function *CleanupFn)
static BasicBlock * createResumeEntryBlock(Function &F, coro::Shape &Shape)
ConstantInt * getFalse()
Get the constant value for i1 false.
SwitchInst * CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases=10, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a switch instruction with the specified value, default dest, and with a hint for the number of...
uint64_t getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
The basic data container for the call graph of a Module of IR.
INITIALIZE_PASS(CoroSplit, "coro-split", "Split coroutine into a set of functions driving its state machine", false, false) Pass *llvm
LLVM_NODISCARD bool empty() const
StringRef getValueAsString() const
Return the attribute's value as a string.
SwitchInst * ResumeSwitch
StringRef getName() const
Return a constant reference to the value's name.
static void handleFinalSuspend(IRBuilder<> &Builder, Value *FramePtr, coro::Shape &Shape, SwitchInst *Switch, bool IsDestroy)
Value * CreateConstInBoundsGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1, const Twine &Name="")
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
#define CORO_DEVIRT_TRIGGER_FN
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
static ConstantTokenNone * get(LLVMContext &Context)
Return the ConstantTokenNone.
BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
CoroIdInst * getId() const
void replaceCoroFree(CoroIdInst *CoroId, bool Elide)
static SmallPtrSet< Instruction *, 8 > getNotRelocatableInstructions(CoroBeginInst *CoroBegin, SmallPtrSetImpl< BasicBlock *> &RelocBlocks)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SmallVector< CoroEndInst *, 4 > CoroEnds
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
void setInfo(Constant *C)
CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on.
CallGraphNode * getOrInsertFunction(const Function *F)
Similar to operator[], but this will insert a new CallGraphNode for F if one does not already exist...
static CleanupReturnInst * Create(Value *CleanupPad, BasicBlock *UnwindBB=nullptr, Instruction *InsertBefore=nullptr)
AttrBuilder typeIncompatible(Type *Ty)
Which attributes cannot be applied to a type.
void moveBefore(Instruction *MovePos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
static bool simplifyTerminatorLeadingToRet(Instruction *InitialInst)
bool declaresIntrinsics(Module &M, std::initializer_list< StringRef >)
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
FunctionPass * createEarlyCSEPass(bool UseMemorySSA=false)
ConstantInt * getInt8(uint8_t C)
Get a constant 8-bit value.
static void removeCoroEnds(coro::Shape &Shape)
StringRef - Represent a constant reference to a string, i.e.
inst_range instructions(Function *F)
CoroAllocInst * getCoroAlloc()
BasicBlock * AllocaSpillBlock
CoroSaveInst * getCoroSave() const
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
void updateCallGraph(Function &Caller, ArrayRef< Function *> Funcs, CallGraph &CG, CallGraphSCC &SCC)
iterator_range< arg_iterator > args()
A wrapper class for inspecting calls to intrinsic functions.
const BasicBlock * getParent() const