1 //===- CoroCleanup.cpp - Coroutine Cleanup Pass ---------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
9 // This pass lowers all remaining coroutine intrinsics.
10 //===----------------------------------------------------------------------===//
12 #include "CoroInternal.h"
13 #include "llvm/IR/IRBuilder.h"
14 #include "llvm/IR/InstIterator.h"
15 #include "llvm/IR/LegacyPassManager.h"
16 #include "llvm/Pass.h"
17 #include "llvm/Transforms/Scalar.h"
21 #define DEBUG_TYPE "coro-cleanup"
24 // Created on demand if CoroCleanup pass has work to do.
25 struct Lowerer : coro::LowererBase {
27 Lowerer(Module &M) : LowererBase(M), Builder(Context) {}
28 bool lowerRemainingCoroIntrinsics(Function &F);
32 static void simplifyCFG(Function &F) {
33 llvm::legacy::FunctionPassManager FPM(F.getParent());
34 FPM.add(createCFGSimplificationPass());
36 FPM.doInitialization();
41 static void lowerSubFn(IRBuilder<> &Builder, CoroSubFnInst *SubFn) {
42 Builder.SetInsertPoint(SubFn);
43 Value *FrameRaw = SubFn->getFrame();
44 int Index = SubFn->getIndex();
46 auto *FrameTy = StructType::get(
47 SubFn->getContext(), {Builder.getInt8PtrTy(), Builder.getInt8PtrTy()});
48 PointerType *FramePtrTy = FrameTy->getPointerTo();
50 Builder.SetInsertPoint(SubFn);
51 auto *FramePtr = Builder.CreateBitCast(FrameRaw, FramePtrTy);
52 auto *Gep = Builder.CreateConstInBoundsGEP2_32(FrameTy, FramePtr, 0, Index);
53 auto *Load = Builder.CreateLoad(Gep);
55 SubFn->replaceAllUsesWith(Load);
58 bool Lowerer::lowerRemainingCoroIntrinsics(Function &F) {
61 for (auto IB = inst_begin(F), E = inst_end(F); IB != E;) {
62 Instruction &I = *IB++;
63 if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
64 switch (II->getIntrinsicID()) {
67 case Intrinsic::coro_begin:
68 II->replaceAllUsesWith(II->getArgOperand(1));
70 case Intrinsic::coro_free:
71 II->replaceAllUsesWith(II->getArgOperand(1));
73 case Intrinsic::coro_alloc:
74 II->replaceAllUsesWith(ConstantInt::getTrue(Context));
76 case Intrinsic::coro_id:
77 II->replaceAllUsesWith(ConstantTokenNone::get(Context));
79 case Intrinsic::coro_subfn_addr:
80 lowerSubFn(Builder, cast<CoroSubFnInst>(II));
83 II->eraseFromParent();
89 // After replacement were made we can cleanup the function body a little.
95 //===----------------------------------------------------------------------===//
97 //===----------------------------------------------------------------------===//
101 struct CoroCleanup : FunctionPass {
102 static char ID; // Pass identification, replacement for typeid
104 CoroCleanup() : FunctionPass(ID) {}
106 std::unique_ptr<Lowerer> L;
108 // This pass has work to do only if we find intrinsics we are going to lower
110 bool doInitialization(Module &M) override {
111 if (coro::declaresIntrinsics(M, {"llvm.coro.alloc", "llvm.coro.begin",
112 "llvm.coro.subfn.addr", "llvm.coro.free",
114 L = llvm::make_unique<Lowerer>(M);
118 bool runOnFunction(Function &F) override {
120 return L->lowerRemainingCoroIntrinsics(F);
123 void getAnalysisUsage(AnalysisUsage &AU) const override {
125 AU.setPreservesAll();
130 char CoroCleanup::ID = 0;
131 INITIALIZE_PASS(CoroCleanup, "coro-cleanup",
132 "Lower all coroutine related intrinsics", false, false)
134 Pass *llvm::createCoroCleanupPass() { return new CoroCleanup(); }