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 
59  bool IsPrivateAndUnprocessed =
60  F.hasFnAttribute(CORO_PRESPLIT_ATTR) && F.hasLocalLinkage();
61 
63  if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
64  switch (II->getIntrinsicID()) {
65  default:
66  continue;
67  case Intrinsic::coro_begin:
68  II->replaceAllUsesWith(II->getArgOperand(1));
69  break;
70  case Intrinsic::coro_free:
71  II->replaceAllUsesWith(II->getArgOperand(1));
72  break;
73  case Intrinsic::coro_alloc:
74  II->replaceAllUsesWith(ConstantInt::getTrue(Context));
75  break;
76  case Intrinsic::coro_async_resume:
77  II->replaceAllUsesWith(
78  ConstantPointerNull::get(cast<PointerType>(I.getType())));
79  break;
80  case Intrinsic::coro_id:
81  case Intrinsic::coro_id_retcon:
82  case Intrinsic::coro_id_retcon_once:
83  case Intrinsic::coro_id_async:
84  II->replaceAllUsesWith(ConstantTokenNone::get(Context));
85  break;
86  case Intrinsic::coro_subfn_addr:
87  lowerSubFn(Builder, cast<CoroSubFnInst>(II));
88  break;
89  case Intrinsic::coro_end:
90  case Intrinsic::coro_suspend_retcon:
91  if (IsPrivateAndUnprocessed) {
92  II->replaceAllUsesWith(UndefValue::get(II->getType()));
93  } else
94  continue;
95  break;
96  case Intrinsic::coro_async_size_replace:
97  auto *Target = cast<ConstantStruct>(
98  cast<GlobalVariable>(II->getArgOperand(0)->stripPointerCasts())
99  ->getInitializer());
100  auto *Source = cast<ConstantStruct>(
101  cast<GlobalVariable>(II->getArgOperand(1)->stripPointerCasts())
102  ->getInitializer());
103  auto *TargetSize = Target->getOperand(1);
104  auto *SourceSize = Source->getOperand(1);
105  if (TargetSize->isElementWiseEqual(SourceSize)) {
106  break;
107  }
108  auto *TargetRelativeFunOffset = Target->getOperand(0);
109  auto *NewFuncPtrStruct = ConstantStruct::get(
110  Target->getType(), TargetRelativeFunOffset, SourceSize);
111  Target->replaceAllUsesWith(NewFuncPtrStruct);
112  break;
113  }
114  II->eraseFromParent();
115  Changed = true;
116  }
117  }
118 
119  if (Changed) {
120  // After replacement were made we can cleanup the function body a little.
121  simplifyCFG(F);
122  }
123 
124  return Changed;
125 }
126 
127 static bool declaresCoroCleanupIntrinsics(const Module &M) {
129  M, {"llvm.coro.alloc", "llvm.coro.begin", "llvm.coro.subfn.addr",
130  "llvm.coro.free", "llvm.coro.id", "llvm.coro.id.retcon",
131  "llvm.coro.id.retcon.once", "llvm.coro.async.size.replace",
132  "llvm.coro.async.resume"});
133 }
134 
137  auto &M = *F.getParent();
139  !Lowerer(M).lowerRemainingCoroIntrinsics(F))
140  return PreservedAnalyses::all();
141 
142  return PreservedAnalyses::none();
143 }
144 
145 namespace {
146 
147 struct CoroCleanupLegacy : FunctionPass {
148  static char ID; // Pass identification, replacement for typeid
149 
150  CoroCleanupLegacy() : FunctionPass(ID) {
152  }
153 
154  std::unique_ptr<Lowerer> L;
155 
156  // This pass has work to do only if we find intrinsics we are going to lower
157  // in the module.
158  bool doInitialization(Module &M) override {
160  L = std::make_unique<Lowerer>(M);
161  return false;
162  }
163 
164  bool runOnFunction(Function &F) override {
165  if (L)
166  return L->lowerRemainingCoroIntrinsics(F);
167  return false;
168  }
169  void getAnalysisUsage(AnalysisUsage &AU) const override {
170  if (!L)
171  AU.setPreservesAll();
172  }
173  StringRef getPassName() const override { return "Coroutine Cleanup"; }
174 };
175 }
176 
177 char CoroCleanupLegacy::ID = 0;
178 INITIALIZE_PASS(CoroCleanupLegacy, "coro-cleanup",
179  "Lower all coroutine related intrinsics", false, false)
180 
181 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
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:22
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:408
Scalar.h
InstIterator.h
llvm::Function
Definition: Function.h:62
llvm::ConstantStruct::get
static Constant * get(StructType *T, ArrayRef< Constant * > V)
Definition: Constants.cpp:1353
Pass.h
llvm::createCFGSimplificationPass
FunctionPass * createCFGSimplificationPass(SimplifyCFGOptions Options=SimplifyCFGOptions(), std::function< bool(const Function &)> Ftor=nullptr)
Definition: SimplifyCFGPass.cpp:426
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:162
LegacyPassManager.h
llvm::CoroCleanupPass::run
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Definition: CoroCleanup.cpp:135
F
#define F(x, y, z)
Definition: MD5.cpp:55
Context
ManagedStatic< detail::RecordContext > Context
Definition: Record.cpp:96
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:1364
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::UndefValue::get
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1775
CoroInternal.h
llvm::instructions
inst_range instructions(Function *F)
Definition: InstIterator.h:133
Index
uint32_t Index
Definition: ELFObjHandler.cpp:83
llvm::CoroSubFnInst::getIndex
ResumeKind getIndex() const
Definition: CoroInstr.h:49
llvm::ConstantPointerNull::get
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
Definition: Constants.cpp:1761
I
#define I(x, y, z)
Definition: MD5.cpp:58
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:585
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:1358
IRBuilder.h
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
llvm::legacy::FunctionPassManager::add
void add(Pass *P) override
Add a pass to the queue of passes to run.
Definition: LegacyPassManager.cpp:1340
llvm::simplifyCFG
bool simplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, DomTreeUpdater *DTU=nullptr, const SimplifyCFGOptions &Options={}, ArrayRef< WeakVH > LoopHeaders={})
Definition: SimplifyCFG.cpp:6789
Builder
assume Assume Builder
Definition: AssumeBundleBuilder.cpp:650
llvm::Sched::Source
@ Source
Definition: TargetLowering.h:99
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:178
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:991
CORO_PRESPLIT_ATTR
#define CORO_PRESPLIT_ATTR
Definition: CoroInternal.h:44
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:873
llvm::legacy::FunctionPassManager::run
bool run(Function &F)
run - Execute all of the passes scheduled for execution.
Definition: LegacyPassManager.cpp:1348
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:1468
declaresCoroCleanupIntrinsics
static bool declaresCoroCleanupIntrinsics(const Module &M)
Definition: CoroCleanup.cpp:127
llvm::Type::getPointerTo
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
Definition: Type.cpp:776
llvm::SPII::Load
@ Load
Definition: SparcInstrInfo.h:32
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:65
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:74
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38