PageRenderTime 35ms CodeModel.GetById 16ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 1ms

/JIT/SingleFunctionInliner.cc

http://unladen-swallow.googlecode.com/
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}