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/Pass.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 =
49  F.hasFnAttribute(CORO_PRESPLIT_ATTR) && F.hasLocalLinkage();
50  bool Changed = false;
51 
53  if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
54  switch (II->getIntrinsicID()) {
55  default:
56  continue;
57  case Intrinsic::coro_begin:
58  II->replaceAllUsesWith(II->getArgOperand(1));
59  break;
60  case Intrinsic::coro_free:
61  II->replaceAllUsesWith(II->getArgOperand(1));
62  break;
63  case Intrinsic::coro_alloc:
64  II->replaceAllUsesWith(ConstantInt::getTrue(Context));
65  break;
66  case Intrinsic::coro_async_resume:
67  II->replaceAllUsesWith(
68  ConstantPointerNull::get(cast<PointerType>(I.getType())));
69  break;
70  case Intrinsic::coro_id:
71  case Intrinsic::coro_id_retcon:
72  case Intrinsic::coro_id_retcon_once:
73  case Intrinsic::coro_id_async:
74  II->replaceAllUsesWith(ConstantTokenNone::get(Context));
75  break;
76  case Intrinsic::coro_subfn_addr:
77  lowerSubFn(Builder, cast<CoroSubFnInst>(II));
78  break;
79  case Intrinsic::coro_end:
80  case Intrinsic::coro_suspend_retcon:
81  if (IsPrivateAndUnprocessed) {
82  II->replaceAllUsesWith(UndefValue::get(II->getType()));
83  } else
84  continue;
85  break;
86  case Intrinsic::coro_async_size_replace:
87  auto *Target = cast<ConstantStruct>(
88  cast<GlobalVariable>(II->getArgOperand(0)->stripPointerCasts())
89  ->getInitializer());
90  auto *Source = cast<ConstantStruct>(
91  cast<GlobalVariable>(II->getArgOperand(1)->stripPointerCasts())
92  ->getInitializer());
93  auto *TargetSize = Target->getOperand(1);
94  auto *SourceSize = Source->getOperand(1);
95  if (TargetSize->isElementWiseEqual(SourceSize)) {
96  break;
97  }
98  auto *TargetRelativeFunOffset = Target->getOperand(0);
99  auto *NewFuncPtrStruct = ConstantStruct::get(
100  Target->getType(), TargetRelativeFunOffset, SourceSize);
101  Target->replaceAllUsesWith(NewFuncPtrStruct);
102  break;
103  }
104  II->eraseFromParent();
105  Changed = true;
106  }
107  }
108 
109  return Changed;
110 }
111 
112 static bool declaresCoroCleanupIntrinsics(const Module &M) {
114  M, {"llvm.coro.alloc", "llvm.coro.begin", "llvm.coro.subfn.addr",
115  "llvm.coro.free", "llvm.coro.id", "llvm.coro.id.retcon",
116  "llvm.coro.id.retcon.once", "llvm.coro.async.size.replace",
117  "llvm.coro.async.resume"});
118 }
119 
123  return PreservedAnalyses::all();
124 
127 
129  FPM.addPass(SimplifyCFGPass());
130 
131  Lowerer L(M);
132  for (auto &F : M)
133  if (L.lower(F))
134  FPM.run(F, FAM);
135 
136  return PreservedAnalyses::none();
137 }
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:1347
Pass.h
llvm::Target
Target - Wrapper for Target specific information.
Definition: TargetRegistry.h:140
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
llvm::SPII::Load
@ Load
Definition: SparcInstrInfo.h:32
F
#define F(x, y, z)
Definition: MD5.cpp:55
Context
LLVMContext & Context
Definition: NVVMIntrRange.cpp:66
MAM
ModuleAnalysisManager MAM
Definition: PassBuilderBindings.cpp:61
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:1769
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:1755
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::CoroCleanupPass::run
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
Definition: CoroCleanup.cpp:120
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:608
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
CORO_PRESPLIT_ATTR
#define CORO_PRESPLIT_ATTR
Definition: CoroInternal.h:30
llvm::PassManager< Function >
llvm::ConstantInt::getTrue
static ConstantInt * getTrue(LLVMContext &Context)
Definition: Constants.cpp:867
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:1462
declaresCoroCleanupIntrinsics
static bool declaresCoroCleanupIntrinsics(const Module &M)
Definition: CoroCleanup.cpp:112
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:46
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