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