1 //===- CoroCleanup.cpp - Coroutine Cleanup Pass ---------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // This pass lowers all remaining coroutine intrinsics. 10 //===----------------------------------------------------------------------===// 11 12 #include "CoroInternal.h" 13 #include "llvm/IR/InstIterator.h" 14 #include "llvm/IR/LegacyPassManager.h" 15 #include "llvm/Pass.h" 16 #include "llvm/Transforms/Scalar.h" 17 18 using namespace llvm; 19 20 #define DEBUG_TYPE "coro-cleanup" 21 22 namespace { 23 // Created on demand if CoroCleanup pass has work to do. 24 struct Lowerer : coro::LowererBase { 25 Lowerer(Module &M) : LowererBase(M) {} 26 bool lowerRemainingCoroIntrinsics(Function &F); 27 }; 28 } 29 30 static void simplifyCFG(Function &F) { 31 llvm::legacy::FunctionPassManager FPM(F.getParent()); 32 FPM.add(createCFGSimplificationPass()); 33 34 FPM.doInitialization(); 35 FPM.run(F); 36 FPM.doFinalization(); 37 } 38 39 bool Lowerer::lowerRemainingCoroIntrinsics(Function &F) { 40 bool Changed = false; 41 42 for (auto IB = inst_begin(F), E = inst_end(F); IB != E;) { 43 Instruction &I = *IB++; 44 if (auto *II = dyn_cast<IntrinsicInst>(&I)) { 45 switch (II->getIntrinsicID()) { 46 default: 47 continue; 48 case Intrinsic::coro_begin: 49 II->replaceAllUsesWith(II->getArgOperand(1)); 50 break; 51 case Intrinsic::coro_free: 52 II->replaceAllUsesWith(II->getArgOperand(1)); 53 break; 54 case Intrinsic::coro_alloc: 55 II->replaceAllUsesWith(ConstantInt::getTrue(Context)); 56 break; 57 case Intrinsic::coro_id: 58 II->replaceAllUsesWith(ConstantTokenNone::get(Context)); 59 break; 60 } 61 II->eraseFromParent(); 62 Changed = true; 63 } 64 } 65 66 if (Changed) { 67 // After replacement were made we can cleanup the function body a little. 68 simplifyCFG(F); 69 } 70 return Changed; 71 } 72 73 //===----------------------------------------------------------------------===// 74 // Top Level Driver 75 //===----------------------------------------------------------------------===// 76 77 namespace { 78 79 struct CoroCleanup : FunctionPass { 80 static char ID; // Pass identification, replacement for typeid 81 82 CoroCleanup() : FunctionPass(ID) {} 83 84 std::unique_ptr<Lowerer> L; 85 86 // This pass has work to do only if we find intrinsics we are going to lower 87 // in the module. 88 bool doInitialization(Module &M) override { 89 if (coro::declaresIntrinsics(M, {"llvm.coro.alloc", "llvm.coro.begin", 90 "llvm.coro.free", "llvm.coro.id"})) 91 L = llvm::make_unique<Lowerer>(M); 92 return false; 93 } 94 95 bool runOnFunction(Function &F) override { 96 if (L) 97 return L->lowerRemainingCoroIntrinsics(F); 98 return false; 99 } 100 void getAnalysisUsage(AnalysisUsage &AU) const override { 101 if (!L) 102 AU.setPreservesAll(); 103 } 104 }; 105 } 106 107 char CoroCleanup::ID = 0; 108 INITIALIZE_PASS(CoroCleanup, "coro-cleanup", 109 "Lower all coroutine related intrinsics", false, false) 110 111 Pass *llvm::createCoroCleanupPass() { return new CoroCleanup(); } 112