75 : TheModule(M),
Context(M.getContext()),
94 "makeSubFnCall: Index value out of range");
105 static const char *
const CoroIntrinsics[] = {
106 "llvm.coro.alloc",
"llvm.coro.begin",
"llvm.coro.destroy",
107 "llvm.coro.done",
"llvm.coro.end",
"llvm.coro.frame",
108 "llvm.coro.free",
"llvm.coro.id",
"llvm.coro.param",
109 "llvm.coro.promise",
"llvm.coro.resume",
"llvm.coro.save",
110 "llvm.coro.size",
"llvm.coro.subfn.addr",
"llvm.coro.suspend",
119 std::initializer_list<StringRef>
List) {
135 if (
auto CF = dyn_cast<CoroFreeInst>(U))
138 if (CoroFrees.
empty())
147 CF->eraseFromParent();
160 const Function *Callee = CS.getCalledFunction();
176 auto *ParentNode = CG[&ParentFunc];
177 ParentNode->removeAllCalledFunctions();
184 Nodes.push_back(Callee);
218 size_t FinalSuspendIndex = 0;
222 if (
auto II = dyn_cast<IntrinsicInst>(&
I)) {
223 switch (II->getIntrinsicID()) {
226 case Intrinsic::coro_size:
227 CoroSizes.
push_back(cast<CoroSizeInst>(II));
229 case Intrinsic::coro_frame:
230 CoroFrames.
push_back(cast<CoroFrameInst>(II));
232 case Intrinsic::coro_suspend:
233 CoroSuspends.push_back(cast<CoroSuspendInst>(II));
234 if (CoroSuspends.back()->isFinal()) {
237 "Only one suspend point can be marked as final");
238 HasFinalSuspend =
true;
239 FinalSuspendIndex = CoroSuspends.size() - 1;
242 case Intrinsic::coro_begin: {
243 auto CB = cast<CoroBeginInst>(II);
244 if (CB->getId()->getInfo().isPreSplit()) {
247 "coroutine should have exactly one defining @llvm.coro.begin");
251 Attribute::NoDuplicate);
256 case Intrinsic::coro_end:
257 CoroEnds.push_back(cast<CoroEndInst>(II));
258 if (CoroEnds.back()->isFallthrough()) {
261 if (CoroEnds.size() > 1) {
262 if (CoroEnds.front()->isFallthrough())
264 "Only one coro.end can be marked as fallthrough");
265 std::swap(CoroEnds.front(), CoroEnds.back());
279 CF->replaceAllUsesWith(
Undef);
280 CF->eraseFromParent();
287 CS->eraseFromParent();
288 if (
auto *CoroSave = CS->getCoroSave())
289 CoroSave->eraseFromParent();
301 CF->replaceAllUsesWith(CoroBegin);
302 CF->eraseFromParent();
307 if (!CS->getCoroSave())
311 if (HasFinalSuspend &&
312 FinalSuspendIndex != CoroSuspends.size() - 1)
313 std::swap(CoroSuspends[FinalSuspendIndex], CoroSuspends.back());
void push_back(const T &Elt)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
PassManagerBuilder - This class is used to set up a standard optimization sequence for languages like...
CoroBeginInst * CoroBegin
This represents the llvm.coro.alloc instruction.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
void initializeCoroEarlyPass(PassRegistry &)
A Module instance is used to store all the information related to an LLVM module. ...
void initializeCoroElidePass(PassRegistry &)
Pass * createCoroSplitPass()
Split up coroutines into multiple functions driving their state machines.
A global registry used in conjunction with static constructors to make pluggable components (like tar...
static void buildCGN(CallGraph &CG, CallGraphNode *Node)
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
EP_ScalarOptimizerLate - This extension point allows adding optimization passes after most of the mai...
static void addCoroutineSCCPasses(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM)
virtual void add(Pass *P)=0
Add a pass to the queue of passes to run.
The two locations do not alias at all.
Pass * createCoroEarlyPass()
Lower coroutine intrinsics that are not needed by later passes.
void initialize(ArrayRef< CallGraphNode * > NewNodes)
unsigned changeToUnreachable(Instruction *I, bool UseLLVMTrap, bool PreserveLCSSA=false)
Insert an unreachable instruction before the specified instruction, making it and the rest of the cod...
A node in the call graph for a module.
Function * getFunction() const
Returns the function that this call graph node represents.
static bool isCoroutineIntrinsicName(StringRef Name)
void addCalledFunction(CallSite CS, CallGraphNode *M)
Adds a function to the list of functions called by this one.
This represents the llvm.coro.suspend instruction.
void buildFrom(Function &F)
LLVM_NODISCARD bool empty() const
void updateCallGraph(Function &Caller, ArrayRef< Function * > Funcs, CallGraph &CG, CallGraphSCC &SCC)
Class to represent function types.
void initializeCoroSplitPass(PassRegistry &)
EP_EnabledOnOptLevel0 - This extension point allows adding passes that should not be disabled by O0 o...
SmallVector< CoroSizeInst *, 2 > CoroSizes
Function Alias Analysis false
static void addCoroutineOptimizerLastPasses(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM)
This class represents a no-op cast from one type to another.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=None)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
CoroSaveInst * getCoroSave() const
SmallVector< CoroSuspendInst *, 4 > CoroSuspends
static void addCoroutineScalarOptimizerPasses(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM)
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
bool isLeaf(ID id)
Returns true if the intrinsic is a leaf, i.e.
The instances of the Type class are immutable: once they are created, they are never changed...
Pass * createCoroCleanupPass()
Lower all remaining coroutine intrinsics.
Pass * createCoroElidePass()
Analyze coroutines use sites, devirtualize resume/destroy calls and elide heap allocation for corouti...
This represents the llvm.coro.end instruction.
ModulePass * createBarrierNoopPass()
createBarrierNoopPass - This pass is purely a module pass barrier in a pass manager.
This represents the llvm.coro.save instruction.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
LLVMContext & getContext() const
All values hold a context through their type.
EP_OptimizerLast – This extension point allows adding passes that run after everything else...
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
EP_EarlyAsPossible - This extension point allows adding passes before any other transformations, allowing them to see the code as it is coming out of the frontend.
This represents the llvm.coro.free instruction.
EP_CGSCCOptimizerLate - This extension point allows adding CallGraphSCC passes at the end of the main...
static void addCoroutineOpt0Passes(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM)
PassManagerBase - An abstract interface to allow code to add passes to a pass manager without having ...
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
void initializeCoroutines(PassRegistry &)
Initialize all passes linked into the Coroutines library.
static CoroSaveInst * createCoroSave(CoroBeginInst *CoroBegin, CoroSuspendInst *SuspendInst)
static CallInst * Create(Value *Func, ArrayRef< Value * > Args, ArrayRef< OperandBundleDef > Bundles=None, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
A constant pointer value that points to null.
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 void addCoroutineEarlyPasses(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM)
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
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)
iterator_range< user_iterator > users()
static void clear(coro::Shape &Shape)
void initializeCoroCleanupPass(PassRegistry &)
The basic data container for the call graph of a Module of IR.
SwitchInst * ResumeSwitch
void setArgOperand(unsigned i, Value *v)
void replaceCoroFree(CoroIdInst *CoroId, bool Elide)
int lookupLLVMIntrinsicByName(ArrayRef< const char * > NameTable, StringRef Name)
Looks up Name in NameTable via binary search.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SmallVector< CoroEndInst *, 4 > CoroEnds
AllocaInst * PromiseAlloca
This represents the llvm.coro.frame instruction.
LLVM Value Representation.
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...
void addCoroutinePassesToExtensionPoints(PassManagerBuilder &Builder)
Add all coroutine passes to appropriate extension points.
bool declaresIntrinsics(Module &M, std::initializer_list< StringRef >)
StringRef - Represent a constant reference to a string, i.e.
inst_range instructions(Function *F)
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
BasicBlock * AllocaSpillBlock
void addExtension(ExtensionPointTy Ty, ExtensionFn Fn)
static IntegerType * getInt8Ty(LLVMContext &C)
GlobalValue * getNamedValue(StringRef Name) const
Return the global value in the module with the specified name, of arbitrary type. ...
CallGraphNode * getCallsExternalNode() const