Jeffrey Yasskin
2009-May-26 22:15 UTC
[LLVMdev] Wondering how best to run inlining on a single function.
In Unladen Swallow we (intend to) compile each function as we determine it's hot. To "compile" a function means to translate it from CPython bytecode to LLVM IR, optimize the IR using a FunctionPassManager, and JIT the IR to machine code. We'd like to include inlining among our optimizations. Currently the Inliner is a CallGraphSCCPass, which can only be run by the (Module)PassManager and which will try to inline calls into every function in the module, including functions we've already optimized. This seems like it will waste time. I think that, because we optimize every Python function as we generate it, it makes sense to write a SingleFunctionInliner (is there a better name?) that acts as a FunctionPass and add that to our normal FunctionPassManager. Can you guys see anything that will go wrong if I do that? Is there a better way, or an option that doesn't involve writing new code? Thanks, Jeffrey
Chris Lattner
2009-May-27 01:05 UTC
[LLVMdev] Wondering how best to run inlining on a single function.
On May 26, 2009, at 3:15 PM, Jeffrey Yasskin wrote:> In Unladen Swallow we (intend to) compile each function as we > determine it's hot. To "compile" a function means to translate it from > CPython bytecode to LLVM IR, optimize the IR using a > FunctionPassManager, and JIT the IR to machine code. We'd like to > include inlining among our optimizations. Currently the Inliner is a > CallGraphSCCPass, which can only be run by the (Module)PassManager and > which will try to inline calls into every function in the module, > including functions we've already optimized. This seems like it will > waste time. > > I think that, because we optimize every Python function as we generate > it, it makes sense to write a SingleFunctionInliner (is there a better > name?) that acts as a FunctionPass and add that to our normal > FunctionPassManager. Can you guys see anything that will go wrong if I > do that? Is there a better way, or an option that doesn't involve > writing new code?Hi Jeffrey, Does this need to be an actual pass? You can just call the InlineFunction API to inline individual call sites as needed, check out llvm/Transforms/Utils/Cloning.h. CloneAndPruneFunctionInto is a particularly useful function if you're doing argument specialization, because it is very efficient at handling this (better than inlining a bunch of code and then deleting it as dead later). -Chris
Jeffrey Yasskin
2009-May-27 17:59 UTC
[LLVMdev] Wondering how best to run inlining on a single function.
On Tue, May 26, 2009 at 6:05 PM, Chris Lattner <clattner at apple.com> wrote:> > On May 26, 2009, at 3:15 PM, Jeffrey Yasskin wrote: > >> In Unladen Swallow we (intend to) compile each function as we >> determine it's hot. To "compile" a function means to translate it from >> CPython bytecode to LLVM IR, optimize the IR using a >> FunctionPassManager, and JIT the IR to machine code. We'd like to >> include inlining among our optimizations. Currently the Inliner is a >> CallGraphSCCPass, which can only be run by the (Module)PassManager and >> which will try to inline calls into every function in the module, >> including functions we've already optimized. This seems like it will >> waste time. >> >> I think that, because we optimize every Python function as we generate >> it, it makes sense to write a SingleFunctionInliner (is there a better >> name?) that acts as a FunctionPass and add that to our normal >> FunctionPassManager. Can you guys see anything that will go wrong if I >> do that? Is there a better way, or an option that doesn't involve >> writing new code? > > Hi Jeffrey, > > Does this need to be an actual pass? You can just call the > InlineFunction API to inline individual call sites as needed, check > out llvm/Transforms/Utils/Cloning.h. CloneAndPruneFunctionInto is a > particularly useful function if you're doing argument specialization, > because it is very efficient at handling this (better than inlining a > bunch of code and then deleting it as dead later).It would be more convenient as a pass since the other optimizations I'm running are arranged as passes, but it's not absolutely necessary. It'd be relatively easy to wrap InlineFunction() into a pass, of course. On the other hand, the functions I'm currently worried about inlining are all known when we translate the bytecode into IR, so I could replace the IRBuilder::CreateCall() calls with appropriate uses of CloneAndPruneFunctionInto(). I also just discovered `llc -cppgen=inline`, which does something similar. Once I have the call or invoke instruction in a function, it looks like InlineFunction() does everything CloneAndPruneFunctionInto does, along with all the necessary bookkeeping around it. The only reason to call CloneAndPrune directly would be to avoid creating the call instruction in the first place, right? It looks easiest to wrap InlineFunction() into a pass, but I'll keep the other things in mind for when we add more interesting inlining. Thanks, Jeffrey
Devang Patel
2009-Jun-01 17:19 UTC
[LLVMdev] Wondering how best to run inlining on a single function.
Hi Jeffrey, On Tue, May 26, 2009 at 3:15 PM, Jeffrey Yasskin <jyasskin at google.com> wrote:> In Unladen Swallow we (intend to) compile each function as we > determine it's hot. To "compile" a function means to translate it from > CPython bytecode to LLVM IR, optimize the IR using a > FunctionPassManager, and JIT the IR to machine code. We'd like to > include inlining among our optimizations. Currently the Inliner is a > CallGraphSCCPass, which can only be run by the (Module)PassManager and > which will try to inline calls into every function in the module, > including functions we've already optimized. This seems like it will > waste time. > > I think that, because we optimize every Python function as we generate > it, it makes sense to write a SingleFunctionInliner (is there a better > name?) that acts as a FunctionPass and add that to our normal > FunctionPassManager. Can you guys see anything that will go wrong if I > do that? Is there a better way, or an option that doesn't involve > writing new code?Try BasicInliner from lib/Transforms/Utils/BasicInliner.cpp - Devang