LLVM  13.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"
14 #include "llvm/IR/Dominators.h"
15 #include "llvm/IR/InstIterator.h"
16 #include "llvm/InitializePasses.h"
17 #include "llvm/Pass.h"
19 
20 using namespace llvm;
21 
22 #define DEBUG_TYPE "coro-elide"
23 
24 namespace {
25 // Created on demand if the coro-elide pass has work to do.
26 struct Lowerer : coro::LowererBase {
33  SmallPtrSet<const SwitchInst *, 4> CoroSuspendSwitches;
34 
35  Lowerer(Module &M) : LowererBase(M) {}
36 
37  void elideHeapAllocations(Function *F, uint64_t FrameSize, Align FrameAlign,
38  AAResults &AA);
39  bool shouldElide(Function *F, DominatorTree &DT) const;
40  void collectPostSplitCoroIds(Function *F);
41  bool processCoroId(CoroIdInst *, AAResults &AA, DominatorTree &DT);
42  bool hasEscapePath(const CoroBeginInst *,
43  const SmallPtrSetImpl<BasicBlock *> &) const;
44 };
45 } // end anonymous namespace
46 
47 // Go through the list of coro.subfn.addr intrinsics and replace them with the
48 // provided constant.
51  if (Users.empty())
52  return;
53 
54  // See if we need to bitcast the constant to match the type of the intrinsic
55  // being replaced. Note: All coro.subfn.addr intrinsics return the same type,
56  // so we only need to examine the type of the first one in the list.
57  Type *IntrTy = Users.front()->getType();
58  Type *ValueTy = Value->getType();
59  if (ValueTy != IntrTy) {
60  // May need to tweak the function type to match the type expected at the
61  // use site.
62  assert(ValueTy->isPointerTy() && IntrTy->isPointerTy());
64  }
65 
66  // Now the value type matches the type of the intrinsic. Replace them all!
67  for (CoroSubFnInst *I : Users)
69 }
70 
71 // See if any operand of the call instruction references the coroutine frame.
72 static bool operandReferences(CallInst *CI, AllocaInst *Frame, AAResults &AA) {
73  for (Value *Op : CI->operand_values())
74  if (!AA.isNoAlias(Op, Frame))
75  return true;
76  return false;
77 }
78 
79 // Look for any tail calls referencing the coroutine frame and remove tail
80 // attribute from them, since now coroutine frame resides on the stack and tail
81 // call implies that the function does not references anything on the stack.
82 // However if it's a musttail call, we cannot remove the tailcall attribute.
83 // It's safe to keep it there as the musttail call is for symmetric transfer,
84 // and by that point the frame should have been destroyed and hence not
85 // interfering with operands.
86 static void removeTailCallAttribute(AllocaInst *Frame, AAResults &AA) {
87  Function &F = *Frame->getFunction();
88  for (Instruction &I : instructions(F))
89  if (auto *Call = dyn_cast<CallInst>(&I))
90  if (Call->isTailCall() && operandReferences(Call, Frame, AA) &&
91  !Call->isMustTailCall())
92  Call->setTailCall(false);
93 }
94 
95 // Given a resume function @f.resume(%f.frame* %frame), returns the size
96 // and expected alignment of %f.frame type.
97 static std::pair<uint64_t, Align> getFrameLayout(Function *Resume) {
98  // Prefer to pull information from the function attributes.
99  auto Size = Resume->getParamDereferenceableBytes(0);
100  auto Align = Resume->getParamAlign(0);
101 
102  // If those aren't given, extract them from the type.
103  if (Size == 0 || !Align) {
104  auto *FrameTy = Resume->arg_begin()->getType()->getPointerElementType();
105 
106  const DataLayout &DL = Resume->getParent()->getDataLayout();
107  if (!Size) Size = DL.getTypeAllocSize(FrameTy);
108  if (!Align) Align = DL.getABITypeAlign(FrameTy);
109  }
110 
111  return std::make_pair(Size, *Align);
112 }
113 
114 // Finds first non alloca instruction in the entry block of a function.
116  for (Instruction &I : F->getEntryBlock())
117  if (!isa<AllocaInst>(&I))
118  return &I;
119  llvm_unreachable("no terminator in the entry block");
120 }
121 
122 // To elide heap allocations we need to suppress code blocks guarded by
123 // llvm.coro.alloc and llvm.coro.free instructions.
124 void Lowerer::elideHeapAllocations(Function *F, uint64_t FrameSize,
125  Align FrameAlign, AAResults &AA) {
126  LLVMContext &C = F->getContext();
127  auto *InsertPt =
128  getFirstNonAllocaInTheEntryBlock(CoroIds.front()->getFunction());
129 
130  // Replacing llvm.coro.alloc with false will suppress dynamic
131  // allocation as it is expected for the frontend to generate the code that
132  // looks like:
133  // id = coro.id(...)
134  // mem = coro.alloc(id) ? malloc(coro.size()) : 0;
135  // coro.begin(id, mem)
136  auto *False = ConstantInt::getFalse(C);
137  for (auto *CA : CoroAllocs) {
138  CA->replaceAllUsesWith(False);
139  CA->eraseFromParent();
140  }
141 
142  // FIXME: Design how to transmit alignment information for every alloca that
143  // is spilled into the coroutine frame and recreate the alignment information
144  // here. Possibly we will need to do a mini SROA here and break the coroutine
145  // frame into individual AllocaInst recreating the original alignment.
146  const DataLayout &DL = F->getParent()->getDataLayout();
147  auto FrameTy = ArrayType::get(Type::getInt8Ty(C), FrameSize);
148  auto *Frame = new AllocaInst(FrameTy, DL.getAllocaAddrSpace(), "", InsertPt);
149  Frame->setAlignment(FrameAlign);
150  auto *FrameVoidPtr =
151  new BitCastInst(Frame, Type::getInt8PtrTy(C), "vFrame", InsertPt);
152 
153  for (auto *CB : CoroBegins) {
154  CB->replaceAllUsesWith(FrameVoidPtr);
155  CB->eraseFromParent();
156  }
157 
158  // Since now coroutine frame lives on the stack we need to make sure that
159  // any tail call referencing it, must be made non-tail call.
160  removeTailCallAttribute(Frame, AA);
161 }
162 
163 bool Lowerer::hasEscapePath(const CoroBeginInst *CB,
164  const SmallPtrSetImpl<BasicBlock *> &TIs) const {
165  const auto &It = DestroyAddr.find(CB);
166  assert(It != DestroyAddr.end());
167 
168  // Limit the number of blocks we visit.
169  unsigned Limit = 32 * (1 + It->second.size());
170 
172  Worklist.push_back(CB->getParent());
173 
175  // Consider basicblock of coro.destroy as visited one, so that we
176  // skip the path pass through coro.destroy.
177  for (auto *DA : It->second)
178  Visited.insert(DA->getParent());
179 
180  do {
181  const auto *BB = Worklist.pop_back_val();
182  if (!Visited.insert(BB).second)
183  continue;
184  if (TIs.count(BB))
185  return true;
186 
187  // Conservatively say that there is potentially a path.
188  if (!--Limit)
189  return true;
190 
191  auto TI = BB->getTerminator();
192  // Although the default dest of coro.suspend switches is suspend pointer
193  // which means a escape path to normal terminator, it is reasonable to skip
194  // it since coroutine frame doesn't change outside the coroutine body.
195  if (isa<SwitchInst>(TI) &&
196  CoroSuspendSwitches.count(cast<SwitchInst>(TI))) {
197  Worklist.push_back(cast<SwitchInst>(TI)->getSuccessor(1));
198  Worklist.push_back(cast<SwitchInst>(TI)->getSuccessor(2));
199  } else
200  Worklist.append(succ_begin(BB), succ_end(BB));
201 
202  } while (!Worklist.empty());
203 
204  // We have exhausted all possible paths and are certain that coro.begin can
205  // not reach to any of terminators.
206  return false;
207 }
208 
209 bool Lowerer::shouldElide(Function *F, DominatorTree &DT) const {
210  // If no CoroAllocs, we cannot suppress allocation, so elision is not
211  // possible.
212  if (CoroAllocs.empty())
213  return false;
214 
215  // Check that for every coro.begin there is at least one coro.destroy directly
216  // referencing the SSA value of that coro.begin along each
217  // non-exceptional path.
218  // If the value escaped, then coro.destroy would have been referencing a
219  // memory location storing that value and not the virtual register.
220 
221  SmallPtrSet<BasicBlock *, 8> Terminators;
222  // First gather all of the non-exceptional terminators for the function.
223  // Consider the final coro.suspend as the real terminator when the current
224  // function is a coroutine.
225  for (BasicBlock &B : *F) {
226  auto *TI = B.getTerminator();
227  if (TI->getNumSuccessors() == 0 && !TI->isExceptionalTerminator() &&
228  !isa<UnreachableInst>(TI))
229  Terminators.insert(&B);
230  }
231 
232  // Filter out the coro.destroy that lie along exceptional paths.
233  SmallPtrSet<CoroBeginInst *, 8> ReferencedCoroBegins;
234  for (auto &It : DestroyAddr) {
235  for (Instruction *DA : It.second) {
236  for (BasicBlock *TI : Terminators) {
237  if (DT.dominates(DA, TI->getTerminator())) {
238  ReferencedCoroBegins.insert(It.first);
239  break;
240  }
241  }
242  }
243 
244  // Whether there is any paths from coro.begin to Terminators which not pass
245  // through any of the coro.destroys.
246  if (!ReferencedCoroBegins.count(It.first) &&
247  !hasEscapePath(It.first, Terminators))
248  ReferencedCoroBegins.insert(It.first);
249  }
250 
251  // If size of the set is the same as total number of coro.begin, that means we
252  // found a coro.free or coro.destroy referencing each coro.begin, so we can
253  // perform heap elision.
254  return ReferencedCoroBegins.size() == CoroBegins.size();
255 }
256 
257 void Lowerer::collectPostSplitCoroIds(Function *F) {
258  CoroIds.clear();
259  CoroSuspendSwitches.clear();
260  for (auto &I : instructions(F)) {
261  if (auto *CII = dyn_cast<CoroIdInst>(&I))
262  if (CII->getInfo().isPostSplit())
263  // If it is the coroutine itself, don't touch it.
264  if (CII->getCoroutine() != CII->getFunction())
265  CoroIds.push_back(CII);
266 
267  // Consider case like:
268  // %0 = call i8 @llvm.coro.suspend(...)
269  // switch i8 %0, label %suspend [i8 0, label %resume
270  // i8 1, label %cleanup]
271  // and collect the SwitchInsts which are used by escape analysis later.
272  if (auto *CSI = dyn_cast<CoroSuspendInst>(&I))
273  if (CSI->hasOneUse() && isa<SwitchInst>(CSI->use_begin()->getUser())) {
274  SwitchInst *SWI = cast<SwitchInst>(CSI->use_begin()->getUser());
275  if (SWI->getNumCases() == 2)
276  CoroSuspendSwitches.insert(SWI);
277  }
278  }
279 }
280 
281 bool Lowerer::processCoroId(CoroIdInst *CoroId, AAResults &AA,
282  DominatorTree &DT) {
283  CoroBegins.clear();
284  CoroAllocs.clear();
285  CoroFrees.clear();
286  ResumeAddr.clear();
287  DestroyAddr.clear();
288 
289  // Collect all coro.begin and coro.allocs associated with this coro.id.
290  for (User *U : CoroId->users()) {
291  if (auto *CB = dyn_cast<CoroBeginInst>(U))
292  CoroBegins.push_back(CB);
293  else if (auto *CA = dyn_cast<CoroAllocInst>(U))
294  CoroAllocs.push_back(CA);
295  else if (auto *CF = dyn_cast<CoroFreeInst>(U))
296  CoroFrees.push_back(CF);
297  }
298 
299  // Collect all coro.subfn.addrs associated with coro.begin.
300  // Note, we only devirtualize the calls if their coro.subfn.addr refers to
301  // coro.begin directly. If we run into cases where this check is too
302  // conservative, we can consider relaxing the check.
303  for (CoroBeginInst *CB : CoroBegins) {
304  for (User *U : CB->users())
305  if (auto *II = dyn_cast<CoroSubFnInst>(U))
306  switch (II->getIndex()) {
308  ResumeAddr.push_back(II);
309  break;
311  DestroyAddr[CB].push_back(II);
312  break;
313  default:
314  llvm_unreachable("unexpected coro.subfn.addr constant");
315  }
316  }
317 
318  // PostSplit coro.id refers to an array of subfunctions in its Info
319  // argument.
320  ConstantArray *Resumers = CoroId->getInfo().Resumers;
321  assert(Resumers && "PostSplit coro.id Info argument must refer to an array"
322  "of coroutine subfunctions");
323  auto *ResumeAddrConstant =
325 
326  replaceWithConstant(ResumeAddrConstant, ResumeAddr);
327 
328  bool ShouldElide = shouldElide(CoroId->getFunction(), DT);
329 
330  auto *DestroyAddrConstant = ConstantExpr::getExtractValue(
331  Resumers,
333 
334  for (auto &It : DestroyAddr)
335  replaceWithConstant(DestroyAddrConstant, It.second);
336 
337  if (ShouldElide) {
338  auto FrameSizeAndAlign = getFrameLayout(cast<Function>(ResumeAddrConstant));
339  elideHeapAllocations(CoroId->getFunction(), FrameSizeAndAlign.first,
340  FrameSizeAndAlign.second, AA);
341  coro::replaceCoroFree(CoroId, /*Elide=*/true);
342  }
343 
344  return true;
345 }
346 
347 // See if there are any coro.subfn.addr instructions referring to coro.devirt
348 // trigger, if so, replace them with a direct call to devirt trigger function.
351  for (auto &I : instructions(F))
352  if (auto *SubFn = dyn_cast<CoroSubFnInst>(&I))
353  if (SubFn->getIndex() == CoroSubFnInst::RestartTrigger)
354  DevirtAddr.push_back(SubFn);
355 
356  if (DevirtAddr.empty())
357  return false;
358 
359  Module &M = *F.getParent();
360  Function *DevirtFn = M.getFunction(CORO_DEVIRT_TRIGGER_FN);
361  assert(DevirtFn && "coro.devirt.fn not found");
362  replaceWithConstant(DevirtFn, DevirtAddr);
363 
364  return true;
365 }
366 
368  return coro::declaresIntrinsics(M, {"llvm.coro.id", "llvm.coro.id.async"});
369 }
370 
372  auto &M = *F.getParent();
374  return PreservedAnalyses::all();
375 
376  Lowerer L(M);
377  L.CoroIds.clear();
378  L.collectPostSplitCoroIds(&F);
379  // If we did not find any coro.id, there is nothing to do.
380  if (L.CoroIds.empty())
381  return PreservedAnalyses::all();
382 
383  AAResults &AA = AM.getResult<AAManager>(F);
385 
386  bool Changed = false;
387  for (auto *CII : L.CoroIds)
388  Changed |= L.processCoroId(CII, AA, DT);
389 
390  return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
391 }
392 
393 namespace {
394 struct CoroElideLegacy : FunctionPass {
395  static char ID;
396  CoroElideLegacy() : FunctionPass(ID) {
398  }
399 
400  std::unique_ptr<Lowerer> L;
401 
402  bool doInitialization(Module &M) override {
404  L = std::make_unique<Lowerer>(M);
405  return false;
406  }
407 
408  bool runOnFunction(Function &F) override {
409  if (!L)
410  return false;
411 
412  bool Changed = false;
413 
414  if (F.hasFnAttribute(CORO_PRESPLIT_ATTR))
415  Changed = replaceDevirtTrigger(F);
416 
417  L->CoroIds.clear();
418  L->collectPostSplitCoroIds(&F);
419  // If we did not find any coro.id, there is nothing to do.
420  if (L->CoroIds.empty())
421  return Changed;
422 
423  AAResults &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
424  DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
425 
426  for (auto *CII : L->CoroIds)
427  Changed |= L->processCoroId(CII, AA, DT);
428 
429  return Changed;
430  }
431  void getAnalysisUsage(AnalysisUsage &AU) const override {
434  }
435  StringRef getPassName() const override { return "Coroutine Elision"; }
436 };
437 }
438 
439 char CoroElideLegacy::ID = 0;
441  CoroElideLegacy, "coro-elide",
442  "Coroutine frame allocation elision and indirect calls replacement", false,
443  false)
446  CoroElideLegacy, "coro-elide",
447  "Coroutine frame allocation elision and indirect calls replacement", false,
448  false)
449 
450 Pass *llvm::createCoroElideLegacyPass() { return new CoroElideLegacy(); }
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:155
llvm::CoroSubFnInst::ResumeIndex
@ ResumeIndex
Definition: CoroInstr.h:41
llvm::CoroIdInst::getInfo
Info getInfo() const
Definition: CoroInstr.h:162
llvm::createCoroElideLegacyPass
Pass * createCoroElideLegacyPass()
Analyze coroutines use sites, devirtualize resume/destroy calls and elide heap allocation for corouti...
Definition: CoroElide.cpp:450
llvm::AAManager
A manager for alias analyses.
Definition: AliasAnalysis.h:1221
llvm
Definition: AllocatorList.h:23
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:112
llvm::M68kBeads::DA
@ DA
Definition: M68kBaseInfo.h:59
llvm::Type::getInt8PtrTy
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:256
elide
coro elide
Definition: CoroElide.cpp:446
replaceDevirtTrigger
static bool replaceDevirtTrigger(Function &F)
Definition: CoroElide.cpp:349
llvm::Type::isPointerTy
bool isPointerTy() const
True if this is an instance of PointerType.
Definition: Type.h:229
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:785
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:61
INITIALIZE_PASS_BEGIN
INITIALIZE_PASS_BEGIN(CoroElideLegacy, "coro-elide", "Coroutine frame allocation elision and indirect calls replacement", false, false) INITIALIZE_PASS_END(CoroElideLegacy
Pass.h
llvm::Function::getParamDereferenceableBytes
uint64_t getParamDereferenceableBytes(unsigned ArgNo) const
Extract the number of dereferenceable bytes for a parameter.
Definition: Function.h:519
llvm::BitCastInst
This class represents a no-op cast from one type to another.
Definition: Instructions.h:5136
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
ErrorHandling.h
llvm::AAResults::isNoAlias
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
A trivial helper function to check to see if the specified pointers are no-alias.
Definition: AliasAnalysis.h:510
llvm::ConstantExpr::getBitCast
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
Definition: Constants.cpp:2207
llvm::DominatorTree
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition: Dominators.h:151
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:158
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:46
DenseMap.h
llvm::coro::declaresIntrinsics
bool declaresIntrinsics(const Module &M, const std::initializer_list< StringRef >)
Definition: Coroutines.cpp:161
llvm::SmallPtrSet
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:449
llvm::SmallVectorImpl::pop_back_val
LLVM_NODISCARD T pop_back_val()
Definition: SmallVector.h:635
and
We currently generate a but we really shouldn eax ecx xorl edx divl ecx eax divl ecx movl eax ret A similar code sequence works for division We currently compile i32 v2 eax eax jo LBB1_2 and
Definition: README.txt:1271
llvm::Type::getInt8Ty
static IntegerType * getInt8Ty(LLVMContext &C)
Definition: Type.cpp:202
CoroElide.h
INITIALIZE_PASS_END
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
Definition: RegBankSelect.cpp:69
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
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:115
operandReferences
static bool operandReferences(CallInst *CI, AllocaInst *Frame, AAResults &AA)
Definition: CoroElide.cpp:72
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition: PassRegistry.cpp:31
llvm::AAResults
Definition: AliasAnalysis.h:456
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:648
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:49
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
false
Definition: StackSlotColoring.cpp:142
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::ConstantArray
ConstantArray - Constant Array Declarations.
Definition: Constants.h:407
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:174
llvm::Instruction
Definition: Instruction.h:45
llvm::DominatorTreeWrapperPass
Legacy analysis pass which computes a DominatorTree.
Definition: Dominators.h:281
llvm::Align
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
CoroInternal.h
allocation
Eliminate PHI nodes for register allocation
Definition: PHIElimination.cpp:136
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
llvm::GlobalValue::getParent
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:572
INITIALIZE_PASS_DEPENDENCY
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
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:115
llvm::DenseMap
Definition: DenseMap.h:714
CORO_DEVIRT_TRIGGER_FN
#define CORO_DEVIRT_TRIGGER_FN
Definition: CoroInternal.h:44
I
#define I(x, y, z)
Definition: MD5.cpp:59
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:371
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:6089
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:3367
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:605
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
llvm::initializeCoroElideLegacyPass
void initializeCoroElideLegacyPass(PassRegistry &)
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:382
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
llvm::Value::getType
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:256
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:70
llvm::Function::getParamAlign
MaybeAlign getParamAlign(unsigned ArgNo) const
Definition: Function.h:482
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition: AArch64SLSHardening.cpp:76
declaresCoroElideIntrinsics
static bool declaresCoroElideIntrinsics(Module &M)
Definition: CoroElide.cpp:367
llvm::CoroSubFnInst::RestartTrigger
@ RestartTrigger
Definition: CoroInstr.h:40
CORO_PRESPLIT_ATTR
#define CORO_PRESPLIT_ATTR
Definition: CoroInternal.h:39
llvm::ConstantInt::getFalse
static ConstantInt * getFalse(LLVMContext &Context)
Definition: Constants.cpp:840
llvm::SmallPtrSetImplBase::size
size_type size() const
Definition: SmallPtrSet.h:92
llvm::CoroIdInst::Info::Resumers
ConstantArray * Resumers
Definition: CoroInstr.h:156
runOnFunction
static bool runOnFunction(Function &F, bool PostInlining)
Definition: EntryExitInstrumenter.cpp:69
removeTailCallAttribute
static void removeTailCallAttribute(AllocaInst *Frame, AAResults &AA)
Definition: CoroElide.cpp:86
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:314
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:161
llvm::User::operand_values
iterator_range< value_op_iterator > operand_values()
Definition: User.h:266
llvm::Function::arg_begin
arg_iterator arg_begin()
Definition: Function.h:783
replacement
coro Coroutine frame allocation elision and indirect calls replacement
Definition: CoroElide.cpp:447
getFrameLayout
static std::pair< uint64_t, Align > getFrameLayout(Function *Resume)
Definition: CoroElide.cpp:97
llvm::DominatorTreeAnalysis
Analysis pass which computes a DominatorTree.
Definition: Dominators.h:252
llvm::Pass
Pass interface - Implemented by all 'passes'.
Definition: Pass.h:91
Dominators.h
llvm::Type::getPointerElementType
Type * getPointerElementType() const
Definition: Type.h:378
llvm::AAResultsWrapperPass
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
Definition: AliasAnalysis.h:1269
llvm::Instruction::getParent
const BasicBlock * getParent() const
Definition: Instruction.h:94
InstructionSimplify.h
Users
iv Induction Variable Users
Definition: IVUsers.cpp:52
llvm::coro::LowererBase
Definition: CoroInternal.h:60
llvm::CoroBeginInst
This class represents the llvm.coro.begin instruction.
Definition: CoroInstr.h:420
calls
amdgpu Simplify well known AMD library calls
Definition: AMDGPULibCalls.cpp:198
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:43
llvm::Module::getDataLayout
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Definition: Module.cpp:397
llvm::SmallPtrSetImpl
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
Definition: SmallPtrSet.h:343
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:43
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
llvm::CallInst
This class represents a function call, abstracting a target machine's calling convention.
Definition: Instructions.h:1450
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::AnalysisUsage::addRequired
AnalysisUsage & addRequired()
Definition: PassAnalysisSupport.h:75
llvm::SwitchInst
Multiway switch.
Definition: Instructions.h:3149
llvm::AllocaInst
an instruction to allocate memory on the stack
Definition: Instructions.h:61
InitializePasses.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::Value::users
iterator_range< user_iterator > users()
Definition: Value.h:434
llvm::ConstantExpr::getExtractValue
static Constant * getExtractValue(Constant *Agg, ArrayRef< unsigned > Idxs, Type *OnlyIfReducedTy=nullptr)
Definition: Constants.cpp:2621
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:364
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38