LLVM  15.0.0git
CoroElide.cpp
Go to the documentation of this file.
1 //===- CoroElide.cpp - Coroutine Frame Allocation Elision Pass ------------===//
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 
10 #include "CoroInternal.h"
11 #include "llvm/ADT/DenseMap.h"
12 #include "llvm/ADT/Statistic.h"
15 #include "llvm/IR/Dominators.h"
16 #include "llvm/IR/InstIterator.h"
19 
20 using namespace llvm;
21 
22 #define DEBUG_TYPE "coro-elide"
23 
24 STATISTIC(NumOfCoroElided, "The # of coroutine get elided.");
25 
26 #ifndef NDEBUG
28  "coro-elide-info-output-file", cl::value_desc("filename"),
29  cl::desc("File to record the coroutines got elided"), cl::Hidden);
30 #endif
31 
32 namespace {
33 // Created on demand if the coro-elide pass has work to do.
34 struct Lowerer : coro::LowererBase {
40  SmallPtrSet<const SwitchInst *, 4> CoroSuspendSwitches;
41 
42  Lowerer(Module &M) : LowererBase(M) {}
43 
44  void elideHeapAllocations(Function *F, uint64_t FrameSize, Align FrameAlign,
45  AAResults &AA);
46  bool shouldElide(Function *F, DominatorTree &DT) const;
47  void collectPostSplitCoroIds(Function *F);
48  bool processCoroId(CoroIdInst *, AAResults &AA, DominatorTree &DT);
49  bool hasEscapePath(const CoroBeginInst *,
50  const SmallPtrSetImpl<BasicBlock *> &) const;
51 };
52 } // end anonymous namespace
53 
54 // Go through the list of coro.subfn.addr intrinsics and replace them with the
55 // provided constant.
58  if (Users.empty())
59  return;
60 
61  // See if we need to bitcast the constant to match the type of the intrinsic
62  // being replaced. Note: All coro.subfn.addr intrinsics return the same type,
63  // so we only need to examine the type of the first one in the list.
64  Type *IntrTy = Users.front()->getType();
65  Type *ValueTy = Value->getType();
66  if (ValueTy != IntrTy) {
67  // May need to tweak the function type to match the type expected at the
68  // use site.
69  assert(ValueTy->isPointerTy() && IntrTy->isPointerTy());
71  }
72 
73  // Now the value type matches the type of the intrinsic. Replace them all!
74  for (CoroSubFnInst *I : Users)
76 }
77 
78 // See if any operand of the call instruction references the coroutine frame.
79 static bool operandReferences(CallInst *CI, AllocaInst *Frame, AAResults &AA) {
80  for (Value *Op : CI->operand_values())
81  if (!AA.isNoAlias(Op, Frame))
82  return true;
83  return false;
84 }
85 
86 // Look for any tail calls referencing the coroutine frame and remove tail
87 // attribute from them, since now coroutine frame resides on the stack and tail
88 // call implies that the function does not references anything on the stack.
89 // However if it's a musttail call, we cannot remove the tailcall attribute.
90 // It's safe to keep it there as the musttail call is for symmetric transfer,
91 // and by that point the frame should have been destroyed and hence not
92 // interfering with operands.
94  Function &F = *Frame->getFunction();
95  for (Instruction &I : instructions(F))
96  if (auto *Call = dyn_cast<CallInst>(&I))
97  if (Call->isTailCall() && operandReferences(Call, Frame, AA) &&
98  !Call->isMustTailCall())
99  Call->setTailCall(false);
100 }
101 
102 // Given a resume function @f.resume(%f.frame* %frame), returns the size
103 // and expected alignment of %f.frame type.
105  // Pull information from the function attributes.
106  auto Size = Resume->getParamDereferenceableBytes(0);
107  if (!Size)
108  return None;
109  return std::make_pair(Size, Resume->getParamAlign(0).valueOrOne());
110 }
111 
112 // Finds first non alloca instruction in the entry block of a function.
114  for (Instruction &I : F->getEntryBlock())
115  if (!isa<AllocaInst>(&I))
116  return &I;
117  llvm_unreachable("no terminator in the entry block");
118 }
119 
120 #ifndef NDEBUG
121 static std::unique_ptr<raw_fd_ostream> getOrCreateLogFile() {
123  "coro-elide-info-output-file shouldn't be empty");
124  std::error_code EC;
125  auto Result = std::make_unique<raw_fd_ostream>(CoroElideInfoOutputFilename,
126  EC, sys::fs::OF_Append);
127  if (!EC)
128  return Result;
129  llvm::errs() << "Error opening coro-elide-info-output-file '"
130  << CoroElideInfoOutputFilename << " for appending!\n";
131  return std::make_unique<raw_fd_ostream>(2, false); // stderr.
132 }
133 #endif
134 
135 // To elide heap allocations we need to suppress code blocks guarded by
136 // llvm.coro.alloc and llvm.coro.free instructions.
137 void Lowerer::elideHeapAllocations(Function *F, uint64_t FrameSize,
138  Align FrameAlign, AAResults &AA) {
139  LLVMContext &C = F->getContext();
140  auto *InsertPt =
141  getFirstNonAllocaInTheEntryBlock(CoroIds.front()->getFunction());
142 
143  // Replacing llvm.coro.alloc with false will suppress dynamic
144  // allocation as it is expected for the frontend to generate the code that
145  // looks like:
146  // id = coro.id(...)
147  // mem = coro.alloc(id) ? malloc(coro.size()) : 0;
148  // coro.begin(id, mem)
149  auto *False = ConstantInt::getFalse(C);
150  for (auto *CA : CoroAllocs) {
151  CA->replaceAllUsesWith(False);
152  CA->eraseFromParent();
153  }
154 
155  // FIXME: Design how to transmit alignment information for every alloca that
156  // is spilled into the coroutine frame and recreate the alignment information
157  // here. Possibly we will need to do a mini SROA here and break the coroutine
158  // frame into individual AllocaInst recreating the original alignment.
159  const DataLayout &DL = F->getParent()->getDataLayout();
160  auto FrameTy = ArrayType::get(Type::getInt8Ty(C), FrameSize);
161  auto *Frame = new AllocaInst(FrameTy, DL.getAllocaAddrSpace(), "", InsertPt);
162  Frame->setAlignment(FrameAlign);
163  auto *FrameVoidPtr =
164  new BitCastInst(Frame, Type::getInt8PtrTy(C), "vFrame", InsertPt);
165 
166  for (auto *CB : CoroBegins) {
167  CB->replaceAllUsesWith(FrameVoidPtr);
168  CB->eraseFromParent();
169  }
170 
171  // Since now coroutine frame lives on the stack we need to make sure that
172  // any tail call referencing it, must be made non-tail call.
173  removeTailCallAttribute(Frame, AA);
174 }
175 
176 bool Lowerer::hasEscapePath(const CoroBeginInst *CB,
177  const SmallPtrSetImpl<BasicBlock *> &TIs) const {
178  const auto &It = DestroyAddr.find(CB);
179  assert(It != DestroyAddr.end());
180 
181  // Limit the number of blocks we visit.
182  unsigned Limit = 32 * (1 + It->second.size());
183 
185  Worklist.push_back(CB->getParent());
186 
188  // Consider basicblock of coro.destroy as visited one, so that we
189  // skip the path pass through coro.destroy.
190  for (auto *DA : It->second)
191  Visited.insert(DA->getParent());
192 
193  do {
194  const auto *BB = Worklist.pop_back_val();
195  if (!Visited.insert(BB).second)
196  continue;
197  if (TIs.count(BB))
198  return true;
199 
200  // Conservatively say that there is potentially a path.
201  if (!--Limit)
202  return true;
203 
204  auto TI = BB->getTerminator();
205  // Although the default dest of coro.suspend switches is suspend pointer
206  // which means a escape path to normal terminator, it is reasonable to skip
207  // it since coroutine frame doesn't change outside the coroutine body.
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));
212  } else
213  Worklist.append(succ_begin(BB), succ_end(BB));
214 
215  } while (!Worklist.empty());
216 
217  // We have exhausted all possible paths and are certain that coro.begin can
218  // not reach to any of terminators.
219  return false;
220 }
221 
222 bool Lowerer::shouldElide(Function *F, DominatorTree &DT) const {
223  // If no CoroAllocs, we cannot suppress allocation, so elision is not
224  // possible.
225  if (CoroAllocs.empty())
226  return false;
227 
228  // Check that for every coro.begin there is at least one coro.destroy directly
229  // referencing the SSA value of that coro.begin along each
230  // non-exceptional path.
231  // If the value escaped, then coro.destroy would have been referencing a
232  // memory location storing that value and not the virtual register.
233 
234  SmallPtrSet<BasicBlock *, 8> Terminators;
235  // First gather all of the non-exceptional terminators for the function.
236  // Consider the final coro.suspend as the real terminator when the current
237  // function is a coroutine.
238  for (BasicBlock &B : *F) {
239  auto *TI = B.getTerminator();
240  if (TI->getNumSuccessors() == 0 && !TI->isExceptionalTerminator() &&
241  !isa<UnreachableInst>(TI))
242  Terminators.insert(&B);
243  }
244 
245  // Filter out the coro.destroy that lie along exceptional paths.
246  SmallPtrSet<CoroBeginInst *, 8> ReferencedCoroBegins;
247  for (auto &It : DestroyAddr) {
248  // If there is any coro.destroy dominates all of the terminators for the
249  // coro.begin, we could know the corresponding coro.begin wouldn't escape.
250  for (Instruction *DA : It.second) {
251  if (llvm::all_of(Terminators, [&](auto *TI) {
252  return DT.dominates(DA, TI->getTerminator());
253  })) {
254  ReferencedCoroBegins.insert(It.first);
255  break;
256  }
257  }
258 
259  // Whether there is any paths from coro.begin to Terminators which not pass
260  // through any of the coro.destroys.
261  //
262  // hasEscapePath is relatively slow, so we avoid to run it as much as
263  // possible.
264  if (!ReferencedCoroBegins.count(It.first) &&
265  !hasEscapePath(It.first, Terminators))
266  ReferencedCoroBegins.insert(It.first);
267  }
268 
269  // If size of the set is the same as total number of coro.begin, that means we
270  // found a coro.free or coro.destroy referencing each coro.begin, so we can
271  // perform heap elision.
272  return ReferencedCoroBegins.size() == CoroBegins.size();
273 }
274 
275 void Lowerer::collectPostSplitCoroIds(Function *F) {
276  CoroIds.clear();
277  CoroSuspendSwitches.clear();
278  for (auto &I : instructions(F)) {
279  if (auto *CII = dyn_cast<CoroIdInst>(&I))
280  if (CII->getInfo().isPostSplit())
281  // If it is the coroutine itself, don't touch it.
282  if (CII->getCoroutine() != CII->getFunction())
283  CoroIds.push_back(CII);
284 
285  // Consider case like:
286  // %0 = call i8 @llvm.coro.suspend(...)
287  // switch i8 %0, label %suspend [i8 0, label %resume
288  // i8 1, label %cleanup]
289  // and collect the SwitchInsts which are used by escape analysis later.
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());
293  if (SWI->getNumCases() == 2)
294  CoroSuspendSwitches.insert(SWI);
295  }
296  }
297 }
298 
299 bool Lowerer::processCoroId(CoroIdInst *CoroId, AAResults &AA,
300  DominatorTree &DT) {
301  CoroBegins.clear();
302  CoroAllocs.clear();
303  ResumeAddr.clear();
304  DestroyAddr.clear();
305 
306  // Collect all coro.begin and coro.allocs associated with this coro.id.
307  for (User *U : CoroId->users()) {
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);
312  }
313 
314  // Collect all coro.subfn.addrs associated with coro.begin.
315  // Note, we only devirtualize the calls if their coro.subfn.addr refers to
316  // coro.begin directly. If we run into cases where this check is too
317  // conservative, we can consider relaxing the check.
318  for (CoroBeginInst *CB : CoroBegins) {
319  for (User *U : CB->users())
320  if (auto *II = dyn_cast<CoroSubFnInst>(U))
321  switch (II->getIndex()) {
323  ResumeAddr.push_back(II);
324  break;
326  DestroyAddr[CB].push_back(II);
327  break;
328  default:
329  llvm_unreachable("unexpected coro.subfn.addr constant");
330  }
331  }
332 
333  // PostSplit coro.id refers to an array of subfunctions in its Info
334  // argument.
335  ConstantArray *Resumers = CoroId->getInfo().Resumers;
336  assert(Resumers && "PostSplit coro.id Info argument must refer to an array"
337  "of coroutine subfunctions");
338  auto *ResumeAddrConstant =
340 
341  replaceWithConstant(ResumeAddrConstant, ResumeAddr);
342 
343  bool ShouldElide = shouldElide(CoroId->getFunction(), DT);
344 
345  auto *DestroyAddrConstant = ConstantExpr::getExtractValue(
346  Resumers,
348 
349  for (auto &It : DestroyAddr)
350  replaceWithConstant(DestroyAddrConstant, It.second);
351 
352  if (ShouldElide) {
353  if (auto FrameSizeAndAlign =
354  getFrameLayout(cast<Function>(ResumeAddrConstant))) {
355  elideHeapAllocations(CoroId->getFunction(), FrameSizeAndAlign->first,
356  FrameSizeAndAlign->second, AA);
357  coro::replaceCoroFree(CoroId, /*Elide=*/true);
358  NumOfCoroElided++;
359 #ifndef NDEBUG
360  if (!CoroElideInfoOutputFilename.empty())
362  << "Elide " << CoroId->getCoroutine()->getName() << " in "
363  << CoroId->getFunction()->getName() << "\n";
364 #endif
365  }
366  }
367 
368  return true;
369 }
370 
372  return coro::declaresIntrinsics(M, {"llvm.coro.id", "llvm.coro.id.async"});
373 }
374 
376  auto &M = *F.getParent();
378  return PreservedAnalyses::all();
379 
380  Lowerer L(M);
381  L.CoroIds.clear();
382  L.collectPostSplitCoroIds(&F);
383  // If we did not find any coro.id, there is nothing to do.
384  if (L.CoroIds.empty())
385  return PreservedAnalyses::all();
386 
387  AAResults &AA = AM.getResult<AAManager>(F);
389 
390  bool Changed = false;
391  for (auto *CII : L.CoroIds)
392  Changed |= L.processCoroId(CII, AA, DT);
393 
394  return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
395 }
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:152
llvm::CoroSubFnInst::ResumeIndex
@ ResumeIndex
Definition: CoroInstr.h:41
llvm::CoroIdInst::getInfo
Info getInfo() const
Definition: CoroInstr.h:162
llvm::AAManager
A manager for alias analyses.
Definition: AliasAnalysis.h:1303
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
M
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
Definition: README.txt:252
llvm::DataLayout
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:113
FileSystem.h
llvm::Type::getInt8PtrTy
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:291
llvm::Type::isPointerTy
bool isPointerTy() const
True if this is an instance of PointerType.
Definition: Type.h:218
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:780
llvm::CoroSubFnInst::DestroyIndex
@ DestroyIndex
Definition: CoroInstr.h:42
llvm::succ_end
Interval::succ_iterator succ_end(Interval *I)
Definition: Interval.h:102
InstIterator.h
llvm::Function
Definition: Function.h:60
llvm::Function::getParamDereferenceableBytes
uint64_t getParamDereferenceableBytes(unsigned ArgNo) const
Extract the number of dereferenceable bytes for a parameter.
Definition: Function.h:476
llvm::CoroIdInst::getCoroutine
Function * getCoroutine() const
Definition: CoroInstr.h:182
llvm::BitCastInst
This class represents a no-op cast from one type to another.
Definition: Instructions.h:5212
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1185
Statistic.h
ErrorHandling.h
getOrCreateLogFile
static std::unique_ptr< raw_fd_ostream > getOrCreateLogFile()
Definition: CoroElide.cpp:121
llvm::ConstantExpr::getBitCast
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
Definition: Constants.cpp:2266
llvm::DominatorTree
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition: Dominators.h:166
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:139
llvm::CoroSubFnInst::CleanupIndex
@ CleanupIndex
Definition: CoroInstr.h:43
llvm::PreservedAnalyses::none
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: PassManager.h:155
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
DenseMap.h
llvm::MaybeAlign::valueOrOne
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
Definition: Alignment.h:142
llvm::coro::declaresIntrinsics
bool declaresIntrinsics(const Module &M, const std::initializer_list< StringRef >)
Definition: Coroutines.cpp:117
llvm::Optional
Definition: APInt.h:33
llvm::SmallPtrSet
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:450
getFrameLayout
static Optional< std::pair< uint64_t, Align > > getFrameLayout(Function *Resume)
Definition: CoroElide.cpp:104
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:893
llvm::SmallVectorImpl::pop_back_val
LLVM_NODISCARD T pop_back_val()
Definition: SmallVector.h:654
llvm::Type::getInt8Ty
static IntegerType * getInt8Ty(LLVMContext &C)
Definition: Type.cpp:237
CoroElide.h
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:55
AliasAnalysis.h
llvm::DominatorTree::dominates
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Definition: Dominators.cpp:122
operandReferences
static bool operandReferences(CallInst *CI, AllocaInst *Frame, AAResults &AA)
Definition: CoroElide.cpp:79
llvm::all_of
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1617
llvm::AAResults
Definition: AliasAnalysis.h:511
llvm::SmallVectorImpl::append
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:667
llvm::User
Definition: User.h:44
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
replaceWithConstant
static void replaceWithConstant(Constant *Value, SmallVectorImpl< CoroSubFnInst * > &Users)
Definition: CoroElide.cpp:56
llvm::M68kBeads::DA
@ DA
Definition: M68kBaseInfo.h:59
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::ConstantArray
ConstantArray - Constant Array Declarations.
Definition: Constants.h:410
llvm::CoroSubFnInst
This class represents the llvm.coro.subfn.addr instruction.
Definition: CoroInstr.h:35
llvm::coro::replaceCoroFree
void replaceCoroFree(CoroIdInst *CoroId, bool Elide)
Definition: Coroutines.cpp:130
llvm::Instruction
Definition: Instruction.h:42
llvm::STATISTIC
STATISTIC(NumFunctions, "Total number of functions")
llvm::Align
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
llvm::None
const NoneType None
Definition: None.h:24
CoroInternal.h
llvm::cl::opt
Definition: CommandLine.h:1392
llvm::instructions
inst_range instructions(Function *F)
Definition: InstIterator.h:133
llvm::Constant
This is an important base class in LLVM.
Definition: Constant.h:41
uint64_t
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
getFirstNonAllocaInTheEntryBlock
static Instruction * getFirstNonAllocaInTheEntryBlock(Function *F)
Definition: CoroElide.cpp:113
llvm::DenseMap
Definition: DenseMap.h:716
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::succ_begin
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...
Definition: Interval.h:99
llvm::CoroElidePass::run
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Definition: CoroElide.cpp:375
llvm::replaceAndRecursivelySimplify
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.
Definition: InstructionSimplify.cpp:6564
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::SwitchInst::getNumCases
unsigned getNumCases() const
Return the number of 'cases' in this switch instruction, excluding the default case.
Definition: Instructions.h:3447
llvm::ArrayType::get
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Definition: Type.cpp:638
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
llvm::SmallPtrSetImpl::count
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
Definition: SmallPtrSet.h:383
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
llvm::Value::getType
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
llvm::CoroIdInst
This represents the llvm.coro.id instruction.
Definition: CoroInstr.h:113
llvm::Instruction::getFunction
const Function * getFunction() const
Return the function this instruction belongs to.
Definition: Instruction.cpp:69
llvm::Function::getParamAlign
MaybeAlign getParamAlign(unsigned ArgNo) const
Definition: Function.h:441
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition: AArch64SLSHardening.cpp:76
declaresCoroElideIntrinsics
static bool declaresCoroElideIntrinsics(Module &M)
Definition: CoroElide.cpp:371
llvm::Value::getName
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:305
llvm::ConstantInt::getFalse
static ConstantInt * getFalse(LLVMContext &Context)
Definition: Constants.cpp:883
llvm::SmallPtrSetImplBase::size
size_type size() const
Definition: SmallPtrSet.h:93
llvm::CoroIdInst::Info::Resumers
ConstantArray * Resumers
Definition: CoroInstr.h:156
removeTailCallAttribute
static void removeTailCallAttribute(AllocaInst *Frame, AAResults &AA)
Definition: CoroElide.cpp:93
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:345
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:158
llvm::User::operand_values
iterator_range< value_op_iterator > operand_values()
Definition: User.h:266
llvm::cl::value_desc
Definition: CommandLine.h:414
AA
llvm::DominatorTreeAnalysis
Analysis pass which computes a DominatorTree.
Definition: Dominators.h:267
CoroElideInfoOutputFilename
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)
Dominators.h
llvm::Instruction::getParent
const BasicBlock * getParent() const
Definition: Instruction.h:91
llvm::sys::fs::OF_Append
@ OF_Append
The file should be opened in append mode.
Definition: FileSystem.h:773
InstructionSimplify.h
Users
iv Induction Variable Users
Definition: IVUsers.cpp:48
llvm::coro::LowererBase
Definition: CoroInternal.h:37
llvm::CoroBeginInst
This class represents the llvm.coro.begin instruction.
Definition: CoroInstr.h:420
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:42
llvm::SmallPtrSetImpl
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
Definition: SmallPtrSet.h:344
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:42
llvm::CallInst
This class represents a function call, abstracting a target machine's calling convention.
Definition: Instructions.h:1461
BB
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
Definition: README.txt:39
llvm::SwitchInst
Multiway switch.
Definition: Instructions.h:3230
llvm::AllocaInst
an instruction to allocate memory on the stack
Definition: Instructions.h:58
llvm::cl::desc
Definition: CommandLine.h:405
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::Value::users
iterator_range< user_iterator > users()
Definition: Value.h:421
llvm::ConstantExpr::getExtractValue
static Constant * getExtractValue(Constant *Agg, ArrayRef< unsigned > Idxs, Type *OnlyIfReducedTy=nullptr)
Definition: Constants.cpp:2680
llvm::SmallPtrSetImpl::insert
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:365