LLVM  15.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"
13 #include "llvm/IR/PassManager.h"
14 #include "llvm/IR/Function.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 lower(Function &F);
27 };
28 }
29 
31  Builder.SetInsertPoint(SubFn);
32  Value *FrameRaw = SubFn->getFrame();
33  int Index = SubFn->getIndex();
34 
35  auto *FrameTy = StructType::get(
36  SubFn->getContext(), {Builder.getInt8PtrTy(), Builder.getInt8PtrTy()});
37  PointerType *FramePtrTy = FrameTy->getPointerTo();
38 
39  Builder.SetInsertPoint(SubFn);
40  auto *FramePtr = Builder.CreateBitCast(FrameRaw, FramePtrTy);
41  auto *Gep = Builder.CreateConstInBoundsGEP2_32(FrameTy, FramePtr, 0, Index);
42  auto *Load = Builder.CreateLoad(FrameTy->getElementType(Index), Gep);
43 
44  SubFn->replaceAllUsesWith(Load);
45 }
46 
47 bool Lowerer::lower(Function &F) {
48  bool IsPrivateAndUnprocessed = F.isPresplitCoroutine() && F.hasLocalLinkage();
49  bool Changed = false;
50 
52  if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
53  switch (II->getIntrinsicID()) {
54  default:
55  continue;
56  case Intrinsic::coro_begin:
57  II->replaceAllUsesWith(II->getArgOperand(1));
58  break;
59  case Intrinsic::coro_free:
60  II->replaceAllUsesWith(II->getArgOperand(1));
61  break;
62  case Intrinsic::coro_alloc:
63  II->replaceAllUsesWith(ConstantInt::getTrue(Context));
64  break;
65  case Intrinsic::coro_async_resume:
66  II->replaceAllUsesWith(
67  ConstantPointerNull::get(cast<PointerType>(I.getType())));
68  break;
69  case Intrinsic::coro_id:
70  case Intrinsic::coro_id_retcon:
71  case Intrinsic::coro_id_retcon_once:
72  case Intrinsic::coro_id_async:
73  II->replaceAllUsesWith(ConstantTokenNone::get(Context));
74  break;
75  case Intrinsic::coro_subfn_addr:
76  lowerSubFn(Builder, cast<CoroSubFnInst>(II));
77  break;
78  case Intrinsic::coro_end:
79  case Intrinsic::coro_suspend_retcon:
80  if (IsPrivateAndUnprocessed) {
81  II->replaceAllUsesWith(UndefValue::get(II->getType()));
82  } else
83  continue;
84  break;
85  case Intrinsic::coro_async_size_replace:
86  auto *Target = cast<ConstantStruct>(
87  cast<GlobalVariable>(II->getArgOperand(0)->stripPointerCasts())
88  ->getInitializer());
89  auto *Source = cast<ConstantStruct>(
90  cast<GlobalVariable>(II->getArgOperand(1)->stripPointerCasts())
91  ->getInitializer());
92  auto *TargetSize = Target->getOperand(1);
93  auto *SourceSize = Source->getOperand(1);
94  if (TargetSize->isElementWiseEqual(SourceSize)) {
95  break;
96  }
97  auto *TargetRelativeFunOffset = Target->getOperand(0);
98  auto *NewFuncPtrStruct = ConstantStruct::get(
99  Target->getType(), TargetRelativeFunOffset, SourceSize);
100  Target->replaceAllUsesWith(NewFuncPtrStruct);
101  break;
102  }
103  II->eraseFromParent();
104  Changed = true;
105  }
106  }
107 
108  return Changed;
109 }
110 
111 static bool declaresCoroCleanupIntrinsics(const Module &M) {
113  M, {"llvm.coro.alloc", "llvm.coro.begin", "llvm.coro.subfn.addr",
114  "llvm.coro.free", "llvm.coro.id", "llvm.coro.id.retcon",
115  "llvm.coro.id.retcon.once", "llvm.coro.async.size.replace",
116  "llvm.coro.async.resume"});
117 }
118 
122  return PreservedAnalyses::all();
123 
126 
128  FPM.addPass(SimplifyCFGPass());
129 
130  Lowerer L(M);
131  for (auto &F : M)
132  if (L.lower(F))
133  FPM.run(F, FAM);
134 
135  return PreservedAnalyses::none();
136 }
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:152
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
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:406
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:780
InstIterator.h
llvm::Function
Definition: Function.h:60
llvm::PassManager::addPass
LLVM_ATTRIBUTE_MINSIZE std::enable_if_t<!std::is_same< PassT, PassManager >::value > addPass(PassT &&Pass)
Definition: PassManager.h:550
llvm::ConstantStruct::get
static Constant * get(StructType *T, ArrayRef< Constant * > V)
Definition: Constants.cpp:1353
llvm::Target
Target - Wrapper for Target specific information.
Definition: TargetRegistry.h:145
llvm::IRBuilder<>
CoroCleanup.h
FAM
FunctionAnalysisManager FAM
Definition: PassBuilderBindings.cpp:59
llvm::PreservedAnalyses::none
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: PassManager.h:155
llvm::coro::declaresIntrinsics
bool declaresIntrinsics(const Module &M, const std::initializer_list< StringRef >)
Definition: Coroutines.cpp:117
F
#define F(x, y, z)
Definition: MD5.cpp:55
Context
LLVMContext & Context
Definition: NVVMIntrRange.cpp:66
llvm::SPII::Load
@ Load
Definition: SparcInstrInfo.h:32
MAM
ModuleAnalysisManager MAM
Definition: PassBuilderBindings.cpp:61
llvm::dwarf::Index
Index
Definition: Dwarf.h:472
llvm::CoroSubFnInst
This class represents the llvm.coro.subfn.addr instruction.
Definition: CoroInstr.h:35
llvm::Instruction
Definition: Instruction.h:42
llvm::UndefValue::get
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1768
CoroInternal.h
llvm::instructions
inst_range instructions(Function *F)
Definition: InstIterator.h:133
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:1754
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::CoroCleanupPass::run
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
Definition: CoroCleanup.cpp:119
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:618
llvm::PointerType
Class to represent pointers.
Definition: DerivedTypes.h:632
IRBuilder.h
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
Builder
assume Assume Builder
Definition: AssumeBundleBuilder.cpp:651
llvm::Sched::Source
@ Source
Definition: TargetLowering.h:99
llvm::Value::replaceAllUsesWith
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:529
llvm::Value::getContext
LLVMContext & getContext() const
All values hold a context through their type.
Definition: Value.cpp:991
llvm::PassManager< Function >
llvm::ConstantInt::getTrue
static ConstantInt * getTrue(LLVMContext &Context)
Definition: Constants.cpp:874
lowerSubFn
static void lowerSubFn(IRBuilder<> &Builder, CoroSubFnInst *SubFn)
Definition: CoroCleanup.cpp:30
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:158
llvm::ConstantTokenNone::get
static ConstantTokenNone * get(LLVMContext &Context)
Return the ConstantTokenNone.
Definition: Constants.cpp:1468
Function.h
declaresCoroCleanupIntrinsics
static bool declaresCoroCleanupIntrinsics(const Module &M)
Definition: CoroCleanup.cpp:111
PassManager.h
llvm::Type::getPointerTo
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
Definition: Type.cpp:774
llvm::PassManager::run
PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs)
Run all of the passes in this manager over the given unit of IR.
Definition: PassManager.h:498
llvm::CoroSubFnInst::getFrame
Value * getFrame() const
Definition: CoroInstr.h:48
llvm::coro::LowererBase
Definition: CoroInternal.h:37
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:42
llvm::InnerAnalysisManagerProxy
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
Definition: PassManager.h:937
SimplifyCFG.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::SimplifyCFGPass
A pass to simplify and canonicalize the CFG of a function.
Definition: SimplifyCFG.h:29