Go to the documentation of this file.
22 #define DEBUG_TYPE "coro-elide"
24 STATISTIC(NumOfCoroElided,
"The # of coroutine get elided.");
42 Lowerer(
Module &M) : LowererBase(
M) {}
47 void collectPostSplitCoroIds(
Function *
F);
66 if (ValueTy != IntrTy) {
81 if (!
AA.isNoAlias(
Op, Frame))
96 if (
auto *Call = dyn_cast<CallInst>(&
I))
98 !Call->isMustTailCall())
99 Call->setTailCall(
false);
115 if (!isa<AllocaInst>(&
I))
123 "coro-elide-info-output-file shouldn't be empty");
129 llvm::errs() <<
"Error opening coro-elide-info-output-file '"
131 return std::make_unique<raw_fd_ostream>(2,
false);
150 for (
auto *CA : CoroAllocs) {
151 CA->replaceAllUsesWith(False);
152 CA->eraseFromParent();
161 auto *Frame =
new AllocaInst(FrameTy,
DL.getAllocaAddrSpace(),
"", InsertPt);
162 Frame->setAlignment(FrameAlign);
166 for (
auto *CB : CoroBegins) {
167 CB->replaceAllUsesWith(FrameVoidPtr);
168 CB->eraseFromParent();
178 const auto &It = DestroyAddr.find(CB);
179 assert(It != DestroyAddr.end());
182 unsigned Limit = 32 * (1 + It->second.size());
190 for (
auto *
DA : It->second)
204 auto TI =
BB->getTerminator();
208 if (isa<SwitchInst>(TI) &&
209 CoroSuspendSwitches.count(cast<SwitchInst>(TI))) {
210 Worklist.push_back(cast<SwitchInst>(TI)->getSuccessor(1));
211 Worklist.push_back(cast<SwitchInst>(TI)->getSuccessor(2));
215 }
while (!Worklist.empty());
225 if (CoroAllocs.empty())
239 auto *TI =
B.getTerminator();
240 if (TI->getNumSuccessors() == 0 && !TI->isExceptionalTerminator() &&
241 !isa<UnreachableInst>(TI))
247 for (
auto &It : DestroyAddr) {
254 ReferencedCoroBegins.
insert(It.first);
264 if (!ReferencedCoroBegins.
count(It.first) &&
265 !hasEscapePath(It.first, Terminators))
266 ReferencedCoroBegins.
insert(It.first);
272 return ReferencedCoroBegins.
size() == CoroBegins.size();
275 void Lowerer::collectPostSplitCoroIds(
Function *
F) {
277 CoroSuspendSwitches.clear();
279 if (
auto *CII = dyn_cast<CoroIdInst>(&
I))
280 if (CII->getInfo().isPostSplit())
282 if (CII->getCoroutine() != CII->getFunction())
283 CoroIds.push_back(CII);
290 if (
auto *CSI = dyn_cast<CoroSuspendInst>(&
I))
291 if (CSI->hasOneUse() && isa<SwitchInst>(CSI->use_begin()->getUser())) {
292 SwitchInst *SWI = cast<SwitchInst>(CSI->use_begin()->getUser());
294 CoroSuspendSwitches.insert(SWI);
308 if (
auto *CB = dyn_cast<CoroBeginInst>(U))
309 CoroBegins.push_back(CB);
310 else if (
auto *CA = dyn_cast<CoroAllocInst>(U))
311 CoroAllocs.push_back(CA);
320 if (
auto *II = dyn_cast<CoroSubFnInst>(U))
321 switch (II->getIndex()) {
323 ResumeAddr.push_back(II);
326 DestroyAddr[CB].push_back(II);
336 assert(Resumers &&
"PostSplit coro.id Info argument must refer to an array"
337 "of coroutine subfunctions");
338 auto *ResumeAddrConstant =
343 bool ShouldElide = shouldElide(CoroId->
getFunction(), DT);
349 for (
auto &It : DestroyAddr)
353 if (
auto FrameSizeAndAlign =
355 elideHeapAllocations(CoroId->
getFunction(), FrameSizeAndAlign->first,
356 FrameSizeAndAlign->second,
AA);
376 auto &
M = *
F.getParent();
382 L.collectPostSplitCoroIds(&
F);
384 if (L.CoroIds.empty())
390 bool Changed =
false;
391 for (
auto *CII : L.CoroIds)
392 Changed |= L.processCoroId(CII,
AA, DT);
A set of analyses that are preserved following a run of a transformation pass.
A manager for alias analyses.
This is an optimization pass for GlobalISel generic memory operations.
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
A parsed version of the target data layout string in and methods for querying it.
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
bool isPointerTy() const
True if this is an instance of PointerType.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Interval::succ_iterator succ_end(Interval *I)
uint64_t getParamDereferenceableBytes(unsigned ArgNo) const
Extract the number of dereferenceable bytes for a parameter.
Function * getCoroutine() const
This class represents a no-op cast from one type to another.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static std::unique_ptr< raw_fd_ostream > getOrCreateLogFile()
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
The instances of the Type class are immutable: once they are created, they are never changed.
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
bool declaresIntrinsics(const Module &M, const std::initializer_list< StringRef >)
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
static Optional< std::pair< uint64_t, Align > > getFrameLayout(Function *Resume)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_NODISCARD T pop_back_val()
static IntegerType * getInt8Ty(LLVMContext &C)
LLVM Basic Block Representation.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
static bool operandReferences(CallInst *CI, AllocaInst *Frame, AAResults &AA)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
(vector float) vec_cmpeq(*A, *B) C
static void replaceWithConstant(Constant *Value, SmallVectorImpl< CoroSubFnInst * > &Users)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
ConstantArray - Constant Array Declarations.
This class represents the llvm.coro.subfn.addr instruction.
void replaceCoroFree(CoroIdInst *CoroId, bool Elide)
STATISTIC(NumFunctions, "Total number of functions")
This struct is a compact representation of a valid (non-zero power of two) alignment.
inst_range instructions(Function *F)
This is an important base class in LLVM.
This is an important class for using LLVM in a threaded context.
static Instruction * getFirstNonAllocaInTheEntryBlock(Function *F)
Interval::succ_iterator succ_begin(Interval *I)
succ_begin/succ_end - define methods so that Intervals may be used just like BasicBlocks can with the...
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV, const TargetLibraryInfo *TLI=nullptr, const DominatorTree *DT=nullptr, AssumptionCache *AC=nullptr, SmallSetVector< Instruction *, 8 > *UnsimplifiedUsers=nullptr)
Replace all uses of 'I' with 'SimpleV' and simplify the uses recursively.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
unsigned getNumCases() const
Return the number of 'cases' in this switch instruction, excluding the default case.
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
A Module instance is used to store all the information related to an LLVM module.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Type * getType() const
All values are typed, get the type of this value.
This represents the llvm.coro.id instruction.
const Function * getFunction() const
Return the function this instruction belongs to.
MaybeAlign getParamAlign(unsigned ArgNo) const
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static bool declaresCoroElideIntrinsics(Module &M)
StringRef getName() const
Return a constant reference to the value's name.
static ConstantInt * getFalse(LLVMContext &Context)
static void removeTailCallAttribute(AllocaInst *Frame, AAResults &AA)
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
iterator_range< value_op_iterator > operand_values()
Analysis pass which computes a DominatorTree.
static cl::opt< std::string > CoroElideInfoOutputFilename("coro-elide-info-output-file", cl::value_desc("filename"), cl::desc("File to record the coroutines got elided"), cl::Hidden)
const BasicBlock * getParent() const
@ OF_Append
The file should be opened in append mode.
iv Induction Variable Users
This class represents the llvm.coro.begin instruction.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
A container for analyses that lazily runs them and caches their results.
This class represents a function call, abstracting a target machine's calling convention.
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
an instruction to allocate memory on the stack
LLVM Value Representation.
iterator_range< user_iterator > users()
static Constant * getExtractValue(Constant *Agg, ArrayRef< unsigned > Idxs, Type *OnlyIfReducedTy=nullptr)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.