/JIT/SingleFunctionInliner.cc
C++ | 80 lines | 60 code | 9 blank | 11 comment | 13 complexity | 54031e5196471d773a7315b8e37a0cb7 MD5 | raw file
1#include "JIT/SingleFunctionInliner.h" 2 3#include "llvm/Attributes.h" 4#include "llvm/BasicBlock.h" 5#include "llvm/Function.h" 6#include "llvm/Instructions.h" 7#include "llvm/Module.h" 8#include "llvm/Pass.h" 9#include "llvm/Transforms/Utils/Cloning.h" 10 11namespace { 12 13namespace Attribute = llvm::Attribute; 14using llvm::BasicBlock; 15using llvm::CallInst; 16using llvm::Function; 17using llvm::FunctionPass; 18using llvm::InvokeInst; 19using llvm::Module; 20using llvm::dyn_cast; 21using llvm::isa; 22 23// This class is derived from llvm's Inliner pass, but is tweaked to 24// work one function at a time and to inline things according to 25// Python-specific rules. 26class SingleFunctionInliner : public FunctionPass { 27public: 28 static char ID; 29 SingleFunctionInliner() 30 : FunctionPass(&ID) {} 31 32 virtual bool runOnFunction(Function &f) 33 { 34 bool changed = false; 35 // Scan through and identify all call sites ahead of time so 36 // that we only inline call sites in the original functions, 37 // not call sites that result from inlining other functions. 38 std::vector<CallInst*> call_sites; 39 for (Function::iterator bb = f.begin(), e = f.end(); bb != e; ++bb) { 40 for (BasicBlock::iterator inst = bb->begin(); inst != bb->end(); 41 ++inst) { 42 assert(!isa<InvokeInst>(inst) && 43 "We don't expect any invoke instructions in Python."); 44 CallInst *call = dyn_cast<CallInst>(inst); 45 if (call == NULL) 46 continue; 47 // This may miss inlining indirect calls that become 48 // direct after inlining something else. 49 Function *called_function = call->getCalledFunction(); 50 if (called_function == NULL) 51 continue; 52 if (called_function->isMaterializable()) { 53 if (called_function->Materialize()) 54 continue; 55 } 56 if (!called_function->isDeclaration() && 57 called_function->hasFnAttr(Attribute::AlwaysInline)) { 58 call_sites.push_back(call); 59 } 60 } 61 } 62 63 // Actually inline the calls we found. 64 for (size_t i = 0; i != call_sites.size(); ++i) { 65 changed |= InlineFunction(call_sites[i]); 66 } 67 return changed; 68 } 69}; 70 71// The address of this variable identifies the pass. See 72// http://llvm.org/docs/WritingAnLLVMPass.html#basiccode. 73char SingleFunctionInliner::ID = 0; 74 75} // anonymous namespace 76 77FunctionPass *PyCreateSingleFunctionInliningPass() 78{ 79 return new SingleFunctionInliner(); 80}