LLVM  9.0.0svn
CoroCleanup.cpp
Go to the documentation of this file.
1 //===- CoroCleanup.cpp - Coroutine Cleanup 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 // This pass lowers all remaining coroutine intrinsics.
9 //===----------------------------------------------------------------------===//
10 
11 #include "CoroInternal.h"
12 #include "llvm/IR/IRBuilder.h"
13 #include "llvm/IR/InstIterator.h"
15 #include "llvm/Pass.h"
16 #include "llvm/Transforms/Scalar.h"
17 
18 using namespace llvm;
19 
20 #define DEBUG_TYPE "coro-cleanup"
21 
22 namespace {
23 // Created on demand if CoroCleanup pass has work to do.
24 struct Lowerer : coro::LowererBase {
25  IRBuilder<> Builder;
26  Lowerer(Module &M) : LowererBase(M), Builder(Context) {}
27  bool lowerRemainingCoroIntrinsics(Function &F);
28 };
29 }
30 
31 static void simplifyCFG(Function &F) {
34 
35  FPM.doInitialization();
36  FPM.run(F);
37  FPM.doFinalization();
38 }
39 
40 static void lowerSubFn(IRBuilder<> &Builder, CoroSubFnInst *SubFn) {
41  Builder.SetInsertPoint(SubFn);
42  Value *FrameRaw = SubFn->getFrame();
43  int Index = SubFn->getIndex();
44 
45  auto *FrameTy = StructType::get(
46  SubFn->getContext(), {Builder.getInt8PtrTy(), Builder.getInt8PtrTy()});
47  PointerType *FramePtrTy = FrameTy->getPointerTo();
48 
49  Builder.SetInsertPoint(SubFn);
50  auto *FramePtr = Builder.CreateBitCast(FrameRaw, FramePtrTy);
51  auto *Gep = Builder.CreateConstInBoundsGEP2_32(FrameTy, FramePtr, 0, Index);
52  auto *Load = Builder.CreateLoad(FrameTy->getElementType(Index), Gep);
53 
54  SubFn->replaceAllUsesWith(Load);
55 }
56 
57 bool Lowerer::lowerRemainingCoroIntrinsics(Function &F) {
58  bool Changed = false;
59 
60  for (auto IB = inst_begin(F), E = inst_end(F); IB != E;) {
61  Instruction &I = *IB++;
62  if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
63  switch (II->getIntrinsicID()) {
64  default:
65  continue;
66  case Intrinsic::coro_begin:
67  II->replaceAllUsesWith(II->getArgOperand(1));
68  break;
69  case Intrinsic::coro_free:
70  II->replaceAllUsesWith(II->getArgOperand(1));
71  break;
72  case Intrinsic::coro_alloc:
73  II->replaceAllUsesWith(ConstantInt::getTrue(Context));
74  break;
75  case Intrinsic::coro_id:
76  II->replaceAllUsesWith(ConstantTokenNone::get(Context));
77  break;
78  case Intrinsic::coro_subfn_addr:
79  lowerSubFn(Builder, cast<CoroSubFnInst>(II));
80  break;
81  }
82  II->eraseFromParent();
83  Changed = true;
84  }
85  }
86 
87  if (Changed) {
88  // After replacement were made we can cleanup the function body a little.
89  simplifyCFG(F);
90  }
91  return Changed;
92 }
93 
94 //===----------------------------------------------------------------------===//
95 // Top Level Driver
96 //===----------------------------------------------------------------------===//
97 
98 namespace {
99 
100 struct CoroCleanup : FunctionPass {
101  static char ID; // Pass identification, replacement for typeid
102 
103  CoroCleanup() : FunctionPass(ID) {
105  }
106 
107  std::unique_ptr<Lowerer> L;
108 
109  // This pass has work to do only if we find intrinsics we are going to lower
110  // in the module.
111  bool doInitialization(Module &M) override {
112  if (coro::declaresIntrinsics(M, {"llvm.coro.alloc", "llvm.coro.begin",
113  "llvm.coro.subfn.addr", "llvm.coro.free",
114  "llvm.coro.id"}))
115  L = llvm::make_unique<Lowerer>(M);
116  return false;
117  }
118 
119  bool runOnFunction(Function &F) override {
120  if (L)
121  return L->lowerRemainingCoroIntrinsics(F);
122  return false;
123  }
124  void getAnalysisUsage(AnalysisUsage &AU) const override {
125  if (!L)
126  AU.setPreservesAll();
127  }
128  StringRef getPassName() const override { return "Coroutine Cleanup"; }
129 };
130 }
131 
132 char CoroCleanup::ID = 0;
133 INITIALIZE_PASS(CoroCleanup, "coro-cleanup",
134  "Lower all coroutine related intrinsics", false, false)
135 
136 Pass *llvm::createCoroCleanupPass() { return new CoroCleanup(); }
Pass interface - Implemented by all &#39;passes&#39;.
Definition: Pass.h:80
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
LLVMContext & Context
This class represents lattice values for constants.
Definition: AllocatorList.h:23
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve &#39;CreateLoad(Ty, Ptr, "...")&#39; correctly, instead of converting the string to &#39;bool...
Definition: IRBuilder.h:1434
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
LLVMContext & getContext() const
All values hold a context through their type.
Definition: Value.cpp:720
INITIALIZE_PASS(CoroCleanup, "coro-cleanup", "Lower all coroutine related intrinsics", false, false) Pass *llvm
F(f)
FunctionPass * createCFGSimplificationPass(unsigned Threshold=1, bool ForwardSwitchCond=false, bool ConvertSwitch=false, bool KeepLoops=true, bool SinkCommon=false, std::function< bool(const Function &)> Ftor=nullptr)
inst_iterator inst_begin(Function *F)
Definition: InstIterator.h:131
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
Definition: Type.cpp:651
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:742
static StructType * get(LLVMContext &Context, ArrayRef< Type *> Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Definition: Type.cpp:341
This class represents the llvm.coro.subfn.addr instruction.
Definition: CoroInstr.h:34
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:1809
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.
Definition: Value.cpp:429
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block...
Definition: IRBuilder.h:126
Class to represent pointers.
Definition: DerivedTypes.h:498
static bool runOnFunction(Function &F, bool PostInlining)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Pass * createCoroCleanupPass()
Lower all remaining coroutine intrinsics.
ResumeKind getIndex() const
Definition: CoroInstr.h:48
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:284
FunctionPassManager manages FunctionPasses and BasicBlockPassManagers.
PointerType * getInt8PtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer to an 8-bit integer value.
Definition: IRBuilder.h:384
static ConstantInt * getTrue(LLVMContext &Context)
Definition: Constants.cpp:587
void setPreservesAll()
Set by analyses that do not transform their input at all.
void initializeCoroCleanupPass(PassRegistry &)
#define I(x, y, z)
Definition: MD5.cpp:58
Value * CreateConstInBoundsGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1, const Twine &Name="")
Definition: IRBuilder.h:1630
static ConstantTokenNone * get(LLVMContext &Context)
Return the ConstantTokenNone.
Definition: Constants.cpp:1139
Value * getFrame() const
Definition: CoroInstr.h:47
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:575
LLVM Value Representation.
Definition: Value.h:72
static void lowerSubFn(IRBuilder<> &Builder, CoroSubFnInst *SubFn)
Definition: CoroCleanup.cpp:40
bool declaresIntrinsics(Module &M, std::initializer_list< StringRef >)
Definition: Coroutines.cpp:139
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
inst_iterator inst_end(Function *F)
Definition: InstIterator.h:132
bool simplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, const SimplifyCFGOptions &Options={}, SmallPtrSetImpl< BasicBlock *> *LoopHeaders=nullptr)
This function is used to do simplification of a CFG.