LLVM 20.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/Function.h"
12#include "llvm/IR/IRBuilder.h"
14#include "llvm/IR/Module.h"
15#include "llvm/IR/PassManager.h"
17
18using namespace llvm;
19
20#define DEBUG_TYPE "coro-cleanup"
21
22namespace {
23// Created on demand if CoroCleanup pass has work to do.
24struct Lowerer : coro::LowererBase {
25 IRBuilder<> Builder;
26 Lowerer(Module &M) : LowererBase(M), Builder(Context) {}
27 bool lower(Function &F);
28};
29}
30
31static void lowerSubFn(IRBuilder<> &Builder, CoroSubFnInst *SubFn) {
32 Builder.SetInsertPoint(SubFn);
33 Value *FramePtr = SubFn->getFrame();
34 int Index = SubFn->getIndex();
35
36 auto *FrameTy = StructType::get(SubFn->getContext(),
37 {Builder.getPtrTy(), Builder.getPtrTy()});
38
39 Builder.SetInsertPoint(SubFn);
40 auto *Gep = Builder.CreateConstInBoundsGEP2_32(FrameTy, FramePtr, 0, Index);
41 auto *Load = Builder.CreateLoad(FrameTy->getElementType(Index), Gep);
42
43 SubFn->replaceAllUsesWith(Load);
44}
45
46bool Lowerer::lower(Function &F) {
47 bool IsPrivateAndUnprocessed = F.isPresplitCoroutine() && F.hasLocalLinkage();
48 bool Changed = false;
49
51 if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
52 switch (II->getIntrinsicID()) {
53 default:
54 continue;
55 case Intrinsic::coro_begin:
56 case Intrinsic::coro_begin_custom_abi:
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(PoisonValue::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
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.async", "llvm.coro.id.retcon.once",
116 "llvm.coro.async.size.replace", "llvm.coro.async.resume",
117 "llvm.coro.begin.custom.abi"});
118}
119
123 return PreservedAnalyses::all();
124
127
130
131 PreservedAnalyses FuncPA;
132 FuncPA.preserveSet<CFGAnalyses>();
133
134 Lowerer L(M);
135 for (auto &F : M) {
136 if (L.lower(F)) {
137 FAM.invalidate(F, FuncPA);
138 FPM.run(F, FAM);
139 }
140 }
141
143}
Expand Atomic instructions
static bool declaresCoroCleanupIntrinsics(const Module &M)
static void lowerSubFn(IRBuilder<> &Builder, CoroSubFnInst *SubFn)
Definition: CoroCleanup.cpp:31
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
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:253
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:410
Represents analyses that only rely on functions' control flow.
Definition: Analysis.h:72
static ConstantInt * getTrue(LLVMContext &Context)
Definition: Constants.cpp:866
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
Definition: Constants.cpp:1826
static Constant * get(StructType *T, ArrayRef< Constant * > V)
Definition: Constants.cpp:1378
static ConstantTokenNone * get(LLVMContext &Context)
Return the ConstantTokenNone.
Definition: Constants.cpp:1522
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:1813
Value * CreateConstInBoundsGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1, const Twine &Name="")
Definition: IRBuilder.h:1936
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition: IRBuilder.h:177
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2697
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
Definition: PassManager.h:567
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_v< PassT, PassManager > > addPass(PassT &&Pass)
Definition: PassManager.h:195
PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs)
Run all of the passes in this manager over the given unit of IR.
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition: Constants.cpp:1878
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:111
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: Analysis.h:114
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:117
void preserveSet()
Mark an analysis set as preserved.
Definition: Analysis.h:146
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:406
Target - Wrapper for Target specific information.
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:1075
bool declaresIntrinsics(const Module &M, const std::initializer_list< StringRef >)
Definition: Coroutines.cpp:122
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:657
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)