LLVM  13.0.0git
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 
10 #include "CoroInternal.h"
11 #include "llvm/IR/IRBuilder.h"
12 #include "llvm/IR/InstIterator.h"
14 #include "llvm/Pass.h"
15 #include "llvm/Transforms/Scalar.h"
16 
17 using namespace llvm;
18 
19 #define DEBUG_TYPE "coro-cleanup"
20 
21 namespace {
22 // Created on demand if CoroCleanup pass has work to do.
23 struct Lowerer : coro::LowererBase {
25  Lowerer(Module &M) : LowererBase(M), Builder(Context) {}
26  bool lowerRemainingCoroIntrinsics(Function &F);
27 };
28 }
29 
30 static void simplifyCFG(Function &F) {
31  llvm::legacy::FunctionPassManager FPM(F.getParent());
33 
34  FPM.doInitialization();
35  FPM.run(F);
36  FPM.doFinalization();
37 }
38 
40  Builder.SetInsertPoint(SubFn);
41  Value *FrameRaw = SubFn->getFrame();
42  int Index = SubFn->getIndex();
43 
44  auto *FrameTy = StructType::get(
45  SubFn->getContext(), {Builder.getInt8PtrTy(), Builder.getInt8PtrTy()});
46  PointerType *FramePtrTy = FrameTy->getPointerTo();
47 
48  Builder.SetInsertPoint(SubFn);
49  auto *FramePtr = Builder.CreateBitCast(FrameRaw, FramePtrTy);
50  auto *Gep = Builder.CreateConstInBoundsGEP2_32(FrameTy, FramePtr, 0, Index);
51  auto *Load = Builder.CreateLoad(FrameTy->getElementType(Index), Gep);
52 
53  SubFn->replaceAllUsesWith(Load);
54 }
55 
56 bool Lowerer::lowerRemainingCoroIntrinsics(Function &F) {
57  bool Changed = false;
58 
59  for (auto IB = inst_begin(F), E = inst_end(F); IB != E;) {
60  Instruction &I = *IB++;
61  if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
62  switch (II->getIntrinsicID()) {
63  default:
64  continue;
65  case Intrinsic::coro_begin:
66  II->replaceAllUsesWith(II->getArgOperand(1));
67  break;
68  case Intrinsic::coro_free:
69  II->replaceAllUsesWith(II->getArgOperand(1));
70  break;
71  case Intrinsic::coro_alloc:
72  II->replaceAllUsesWith(ConstantInt::getTrue(Context));
73  break;
74  case Intrinsic::coro_id:
75  case Intrinsic::coro_id_retcon:
76  case Intrinsic::coro_id_retcon_once:
77  case Intrinsic::coro_id_async:
78  II->replaceAllUsesWith(ConstantTokenNone::get(Context));
79  break;
80  case Intrinsic::coro_subfn_addr:
81  lowerSubFn(Builder, cast<CoroSubFnInst>(II));
82  break;
83  case Intrinsic::coro_async_size_replace:
84  auto *Target = cast<ConstantStruct>(
85  cast<GlobalVariable>(II->getArgOperand(0)->stripPointerCasts())
86  ->getInitializer());
87  auto *Source = cast<ConstantStruct>(
88  cast<GlobalVariable>(II->getArgOperand(1)->stripPointerCasts())
89  ->getInitializer());
90  auto *TargetSize = Target->getOperand(1);
91  auto *SourceSize = Source->getOperand(1);
92  if (TargetSize->isElementWiseEqual(SourceSize)) {
93  break;
94  }
95  auto *TargetRelativeFunOffset = Target->getOperand(0);
96  auto *NewFuncPtrStruct = ConstantStruct::get(
97  Target->getType(), TargetRelativeFunOffset, SourceSize);
98  Target->replaceAllUsesWith(NewFuncPtrStruct);
99  break;
100  }
101  II->eraseFromParent();
102  Changed = true;
103  }
104  }
105 
106  if (Changed) {
107  // After replacement were made we can cleanup the function body a little.
108  simplifyCFG(F);
109  }
110 
111  return Changed;
112 }
113 
114 static bool declaresCoroCleanupIntrinsics(const Module &M) {
116  M, {"llvm.coro.alloc", "llvm.coro.begin", "llvm.coro.subfn.addr",
117  "llvm.coro.free", "llvm.coro.id", "llvm.coro.id.retcon",
118  "llvm.coro.id.retcon.once", "llvm.coro.async.size.replace"});
119 }
120 
123  auto &M = *F.getParent();
125  !Lowerer(M).lowerRemainingCoroIntrinsics(F))
126  return PreservedAnalyses::all();
127 
128  return PreservedAnalyses::none();
129 }
130 
131 namespace {
132 
133 struct CoroCleanupLegacy : FunctionPass {
134  static char ID; // Pass identification, replacement for typeid
135 
136  CoroCleanupLegacy() : FunctionPass(ID) {
138  }
139 
140  std::unique_ptr<Lowerer> L;
141 
142  // This pass has work to do only if we find intrinsics we are going to lower
143  // in the module.
144  bool doInitialization(Module &M) override {
146  L = std::make_unique<Lowerer>(M);
147  return false;
148  }
149 
150  bool runOnFunction(Function &F) override {
151  if (L)
152  return L->lowerRemainingCoroIntrinsics(F);
153  return false;
154  }
155  void getAnalysisUsage(AnalysisUsage &AU) const override {
156  if (!L)
157  AU.setPreservesAll();
158  }
159  StringRef getPassName() const override { return "Coroutine Cleanup"; }
160 };
161 }
162 
163 char CoroCleanupLegacy::ID = 0;
164 INITIALIZE_PASS(CoroCleanupLegacy, "coro-cleanup",
165  "Lower all coroutine related intrinsics", false, false)
166 
167 Pass *llvm::createCoroCleanupLegacyPass() { return new CoroCleanupLegacy(); }
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:155
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::StructType::get
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:373
Scalar.h
InstIterator.h
llvm::Function
Definition: Function.h:61
llvm::ConstantStruct::get
static Constant * get(StructType *T, ArrayRef< Constant * > V)
Definition: Constants.cpp:1312
Pass.h
llvm::createCFGSimplificationPass
FunctionPass * createCFGSimplificationPass(SimplifyCFGOptions Options=SimplifyCFGOptions(), std::function< bool(const Function &)> Ftor=nullptr)
Definition: SimplifyCFGPass.cpp:388
llvm::Target
Target - Wrapper for Target specific information.
Definition: TargetRegistry.h:124
llvm::IRBuilder<>
CoroCleanup.h
llvm::PreservedAnalyses::none
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: PassManager.h:158
llvm::coro::declaresIntrinsics
bool declaresIntrinsics(const Module &M, const std::initializer_list< StringRef >)
Definition: Coroutines.cpp:161
LegacyPassManager.h
llvm::CoroCleanupPass::run
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Definition: CoroCleanup.cpp:121
F
#define F(x, y, z)
Definition: MD5.cpp:56
Context
LLVMContext & Context
Definition: NVVMIntrRange.cpp:66
llvm::initializeCoroCleanupLegacyPass
void initializeCoroCleanupLegacyPass(PassRegistry &)
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition: PassRegistry.cpp:31
llvm::legacy::FunctionPassManager::doFinalization
bool doFinalization()
doFinalization - Run all of the finalizers for the function passes.
Definition: LegacyPassManager.cpp:1368
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
llvm::CoroSubFnInst
This class represents the llvm.coro.subfn.addr instruction.
Definition: CoroInstr.h:35
llvm::Instruction
Definition: Instruction.h:45
CoroInternal.h
Index
uint32_t Index
Definition: ELFObjHandler.cpp:84
llvm::CoroSubFnInst::getIndex
ResumeKind getIndex() const
Definition: CoroInstr.h:49
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::PointerType
Class to represent pointers.
Definition: DerivedTypes.h:634
llvm::legacy::FunctionPassManager::doInitialization
bool doInitialization()
doInitialization - Run all of the initializers for the function passes.
Definition: LegacyPassManager.cpp:1362
IRBuilder.h
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
llvm::legacy::FunctionPassManager::add
void add(Pass *P) override
Add a pass to the queue of passes to run.
Definition: LegacyPassManager.cpp:1344
llvm::simplifyCFG
bool simplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, DomTreeUpdater *DTU=nullptr, const SimplifyCFGOptions &Options={}, ArrayRef< WeakVH > LoopHeaders={})
Definition: SimplifyCFG.cpp:6716
Builder
assume Assume Builder
Definition: AssumeBundleBuilder.cpp:649
llvm::Sched::Source
@ Source
Definition: TargetLowering.h:98
llvm::SPII::Load
@ Load
Definition: SparcInstrInfo.h:32
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
INITIALIZE_PASS
INITIALIZE_PASS(CoroCleanupLegacy, "coro-cleanup", "Lower all coroutine related intrinsics", false, false) Pass *llvm
Definition: CoroCleanup.cpp:164
llvm::Value::replaceAllUsesWith
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:527
llvm::Value::getContext
LLVMContext & getContext() const
All values hold a context through their type.
Definition: Value.cpp:953
llvm::createCoroCleanupLegacyPass
Pass * createCoroCleanupLegacyPass()
Lower all remaining coroutine intrinsics.
runOnFunction
static bool runOnFunction(Function &F, bool PostInlining)
Definition: EntryExitInstrumenter.cpp:69
llvm::ConstantInt::getTrue
static ConstantInt * getTrue(LLVMContext &Context)
Definition: Constants.cpp:833
llvm::legacy::FunctionPassManager::run
bool run(Function &F)
run - Execute all of the passes scheduled for execution.
Definition: LegacyPassManager.cpp:1352
llvm::AnalysisUsage::setPreservesAll
void setPreservesAll()
Set by analyses that do not transform their input at all.
Definition: PassAnalysisSupport.h:130
lowerSubFn
static void lowerSubFn(IRBuilder<> &Builder, CoroSubFnInst *SubFn)
Definition: CoroCleanup.cpp:39
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:161
llvm::ConstantTokenNone::get
static ConstantTokenNone * get(LLVMContext &Context)
Return the ConstantTokenNone.
Definition: Constants.cpp:1427
llvm::inst_end
inst_iterator inst_end(Function *F)
Definition: InstIterator.h:132
declaresCoroCleanupIntrinsics
static bool declaresCoroCleanupIntrinsics(const Module &M)
Definition: CoroCleanup.cpp:114
llvm::Type::getPointerTo
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
Definition: Type.cpp:715
llvm::CoroSubFnInst::getFrame
Value * getFrame() const
Definition: CoroInstr.h:48
llvm::Pass
Pass interface - Implemented by all 'passes'.
Definition: Pass.h:91
llvm::legacy::FunctionPassManager
FunctionPassManager manages FunctionPasses.
Definition: LegacyPassManager.h:71
llvm::coro::LowererBase
Definition: CoroInternal.h:60
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:44
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
llvm::inst_begin
inst_iterator inst_begin(Function *F)
Definition: InstIterator.h:131
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38