LLVM  14.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 
60  if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
61  switch (II->getIntrinsicID()) {
62  default:
63  continue;
64  case Intrinsic::coro_begin:
65  II->replaceAllUsesWith(II->getArgOperand(1));
66  break;
67  case Intrinsic::coro_free:
68  II->replaceAllUsesWith(II->getArgOperand(1));
69  break;
70  case Intrinsic::coro_alloc:
71  II->replaceAllUsesWith(ConstantInt::getTrue(Context));
72  break;
73  case Intrinsic::coro_id:
74  case Intrinsic::coro_id_retcon:
75  case Intrinsic::coro_id_retcon_once:
76  case Intrinsic::coro_id_async:
77  II->replaceAllUsesWith(ConstantTokenNone::get(Context));
78  break;
79  case Intrinsic::coro_subfn_addr:
80  lowerSubFn(Builder, cast<CoroSubFnInst>(II));
81  break;
82  case Intrinsic::coro_async_size_replace:
83  auto *Target = cast<ConstantStruct>(
84  cast<GlobalVariable>(II->getArgOperand(0)->stripPointerCasts())
85  ->getInitializer());
86  auto *Source = cast<ConstantStruct>(
87  cast<GlobalVariable>(II->getArgOperand(1)->stripPointerCasts())
88  ->getInitializer());
89  auto *TargetSize = Target->getOperand(1);
90  auto *SourceSize = Source->getOperand(1);
91  if (TargetSize->isElementWiseEqual(SourceSize)) {
92  break;
93  }
94  auto *TargetRelativeFunOffset = Target->getOperand(0);
95  auto *NewFuncPtrStruct = ConstantStruct::get(
96  Target->getType(), TargetRelativeFunOffset, SourceSize);
97  Target->replaceAllUsesWith(NewFuncPtrStruct);
98  break;
99  }
100  II->eraseFromParent();
101  Changed = true;
102  }
103  }
104 
105  if (Changed) {
106  // After replacement were made we can cleanup the function body a little.
107  simplifyCFG(F);
108  }
109 
110  return Changed;
111 }
112 
113 static bool declaresCoroCleanupIntrinsics(const Module &M) {
115  M, {"llvm.coro.alloc", "llvm.coro.begin", "llvm.coro.subfn.addr",
116  "llvm.coro.free", "llvm.coro.id", "llvm.coro.id.retcon",
117  "llvm.coro.id.retcon.once", "llvm.coro.async.size.replace"});
118 }
119 
122  auto &M = *F.getParent();
124  !Lowerer(M).lowerRemainingCoroIntrinsics(F))
125  return PreservedAnalyses::all();
126 
127  return PreservedAnalyses::none();
128 }
129 
130 namespace {
131 
132 struct CoroCleanupLegacy : FunctionPass {
133  static char ID; // Pass identification, replacement for typeid
134 
135  CoroCleanupLegacy() : FunctionPass(ID) {
137  }
138 
139  std::unique_ptr<Lowerer> L;
140 
141  // This pass has work to do only if we find intrinsics we are going to lower
142  // in the module.
143  bool doInitialization(Module &M) override {
145  L = std::make_unique<Lowerer>(M);
146  return false;
147  }
148 
149  bool runOnFunction(Function &F) override {
150  if (L)
151  return L->lowerRemainingCoroIntrinsics(F);
152  return false;
153  }
154  void getAnalysisUsage(AnalysisUsage &AU) const override {
155  if (!L)
156  AU.setPreservesAll();
157  }
158  StringRef getPassName() const override { return "Coroutine Cleanup"; }
159 };
160 }
161 
162 char CoroCleanupLegacy::ID = 0;
163 INITIALIZE_PASS(CoroCleanupLegacy, "coro-cleanup",
164  "Lower all coroutine related intrinsics", false, false)
165 
166 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
---------------------— PointerInfo ------------------------------------—
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:370
Scalar.h
InstIterator.h
llvm::Function
Definition: Function.h:61
llvm::ConstantStruct::get
static Constant * get(StructType *T, ArrayRef< Constant * > V)
Definition: Constants.cpp:1327
Pass.h
llvm::createCFGSimplificationPass
FunctionPass * createCFGSimplificationPass(SimplifyCFGOptions Options=SimplifyCFGOptions(), std::function< bool(const Function &)> Ftor=nullptr)
Definition: SimplifyCFGPass.cpp:415
llvm::Target
Target - Wrapper for Target specific information.
Definition: TargetRegistry.h:137
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:120
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
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
llvm::SPII::Load
@ Load
Definition: SparcInstrInfo.h:32
CoroInternal.h
llvm::instructions
inst_range instructions(Function *F)
Definition: InstIterator.h:133
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::make_early_inc_range
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition: STLExtras.h:576
llvm::PointerType
Class to represent pointers.
Definition: DerivedTypes.h:632
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:6765
Builder
assume Assume Builder
Definition: AssumeBundleBuilder.cpp:650
llvm::Sched::Source
@ Source
Definition: TargetLowering.h:100
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
INITIALIZE_PASS
INITIALIZE_PASS(CoroCleanupLegacy, "coro-cleanup", "Lower all coroutine related intrinsics", false, false) Pass *llvm
Definition: CoroCleanup.cpp:163
llvm::Value::replaceAllUsesWith
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:532
llvm::Value::getContext
LLVMContext & getContext() const
All values hold a context through their type.
Definition: Value.cpp:990
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:848
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:1442
declaresCoroCleanupIntrinsics
static bool declaresCoroCleanupIntrinsics(const Module &M)
Definition: CoroCleanup.cpp:113
llvm::Type::getPointerTo
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
Definition: Type.cpp:738
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::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:37