LLVM 19.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"
13#include "llvm/IR/PassManager.h"
14#include "llvm/IR/Function.h"
16
17using namespace llvm;
18
19#define DEBUG_TYPE "coro-cleanup"
20
21namespace {
22// Created on demand if CoroCleanup pass has work to do.
23struct Lowerer : coro::LowererBase {
24 IRBuilder<> Builder;
25 Lowerer(Module &M) : LowererBase(M), Builder(Context) {}
26 bool lower(Function &F);
27};
28}
29
30static void lowerSubFn(IRBuilder<> &Builder, CoroSubFnInst *SubFn) {
31 Builder.SetInsertPoint(SubFn);
32 Value *FramePtr = SubFn->getFrame();
33 int Index = SubFn->getIndex();
34
35 auto *FrameTy = StructType::get(SubFn->getContext(),
36 {Builder.getPtrTy(), Builder.getPtrTy()});
37
38 Builder.SetInsertPoint(SubFn);
39 auto *Gep = Builder.CreateConstInBoundsGEP2_32(FrameTy, FramePtr, 0, Index);
40 auto *Load = Builder.CreateLoad(FrameTy->getElementType(Index), Gep);
41
42 SubFn->replaceAllUsesWith(Load);
43}
44
45bool Lowerer::lower(Function &F) {
46 bool IsPrivateAndUnprocessed = F.isPresplitCoroutine() && F.hasLocalLinkage();
47 bool Changed = false;
48
50 if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
51 switch (II->getIntrinsicID()) {
52 default:
53 continue;
54 case Intrinsic::coro_begin:
55 II->replaceAllUsesWith(II->getArgOperand(1));
56 break;
57 case Intrinsic::coro_free:
58 II->replaceAllUsesWith(II->getArgOperand(1));
59 break;
60 case Intrinsic::coro_alloc:
61 II->replaceAllUsesWith(ConstantInt::getTrue(Context));
62 break;
63 case Intrinsic::coro_async_resume:
64 II->replaceAllUsesWith(
65 ConstantPointerNull::get(cast<PointerType>(I.getType())));
66 break;
67 case Intrinsic::coro_id:
68 case Intrinsic::coro_id_retcon:
69 case Intrinsic::coro_id_retcon_once:
70 case Intrinsic::coro_id_async:
71 II->replaceAllUsesWith(ConstantTokenNone::get(Context));
72 break;
73 case Intrinsic::coro_subfn_addr:
74 lowerSubFn(Builder, cast<CoroSubFnInst>(II));
75 break;
76 case Intrinsic::coro_end:
77 case Intrinsic::coro_suspend_retcon:
78 if (IsPrivateAndUnprocessed) {
79 II->replaceAllUsesWith(UndefValue::get(II->getType()));
80 } else
81 continue;
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 return Changed;
107}
108
111 M, {"llvm.coro.alloc", "llvm.coro.begin", "llvm.coro.subfn.addr",
112 "llvm.coro.free", "llvm.coro.id", "llvm.coro.id.retcon",
113 "llvm.coro.id.async", "llvm.coro.id.retcon.once",
114 "llvm.coro.async.size.replace", "llvm.coro.async.resume"});
115}
116
120 return PreservedAnalyses::all();
121
124
127
128 PreservedAnalyses FuncPA;
129 FuncPA.preserveSet<CFGAnalyses>();
130
131 Lowerer L(M);
132 for (auto &F : M) {
133 if (L.lower(F)) {
134 FAM.invalidate(F, FuncPA);
135 FPM.run(F, FAM);
136 }
137 }
138
140}
static bool declaresCoroCleanupIntrinsics(const Module &M)
static void lowerSubFn(IRBuilder<> &Builder, CoroSubFnInst *SubFn)
Definition: CoroCleanup.cpp:30
Select target instructions out of generic instructions
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
LLVMContext & Context
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
This header defines various interfaces for pass management in LLVM.
This file provides the interface for the pass responsible for both simplifying and canonicalizing the...
static const unsigned FramePtr
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:348
void invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Invalidate cached analyses for an IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:500
Represents analyses that only rely on functions' control flow.
Definition: Analysis.h:70
static ConstantInt * getTrue(LLVMContext &Context)
Definition: Constants.cpp:833
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
Definition: Constants.cpp:1691
static Constant * get(StructType *T, ArrayRef< Constant * > V)
Definition: Constants.cpp:1300
static ConstantTokenNone * get(LLVMContext &Context)
Return the ConstantTokenNone.
Definition: Constants.cpp:1415
This class represents the llvm.coro.subfn.addr instruction.
Definition: CoroInstr.h:35
Value * getFrame() const
Definition: CoroInstr.h:48
ResumeKind getIndex() const
Definition: CoroInstr.h:49
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Definition: IRBuilder.h:1789
Value * CreateConstInBoundsGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1, const Twine &Name="")
Definition: IRBuilder.h:1913
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition: IRBuilder.h:180
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2649
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
Definition: PassManager.h:658
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
LLVM_ATTRIBUTE_MINSIZE std::enable_if_t<!std::is_same< PassT, PassManager >::value > addPass(PassT &&Pass)
Definition: PassManager.h:273
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:218
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:109
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:115
void preserveSet()
Mark an analysis set as preserved.
Definition: Analysis.h:144
A pass to simplify and canonicalize the CFG of a function.
Definition: SimplifyCFG.h:29
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
Target - Wrapper for Target specific information.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1724
LLVM Value Representation.
Definition: Value.h:74
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:534
LLVMContext & getContext() const
All values hold a context through their type.
Definition: Value.cpp:1074
bool declaresIntrinsics(const Module &M, const std::initializer_list< StringRef >)
Definition: Coroutines.cpp:112
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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:665
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)