I'll commit this tomorrow unless there are objections. -Tom
On Thu, Jun 21, 2012 at 02:05:24PM -0400, Tom Stellard wrote: > The function internalizer pass marks non-kernel functions as internal, > which enables optimizations like function inlining and global dead-code > elimination. > --- > .../state_trackers/clover/llvm/invocation.cpp | 58 > ++++++++++++++++---- > 1 files changed, 48 insertions(+), 10 deletions(-) > > diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp > b/src/gallium/state_trackers/clover/llvm/invocation.cpp > index 27276bc..2d155d5 100644 > --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp > +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp > @@ -36,6 +36,7 @@ > #include <llvm/Support/MemoryBuffer.h> > #include <llvm/Support/PathV1.h> > #include <llvm/Target/TargetData.h> > +#include <llvm/Transforms/IPO.h> > #include <llvm/Transforms/IPO/PassManagerBuilder.h> > > #include "pipe/p_state.h" > @@ -134,7 +135,18 @@ namespace { > } > > void > - link(llvm::Module *mod, const std::string &triple) { > + find_kernels(llvm::Module *mod, std::vector<llvm::Function *> &kernels) { > + const llvm::NamedMDNode *kernel_node = > + mod->getNamedMetadata("opencl.kernels"); > + for (unsigned i = 0; i < kernel_node->getNumOperands(); ++i) { > + kernels.push_back(llvm::dyn_cast<llvm::Function>( > + > kernel_node->getOperand(i)->getOperand(0))); > + } > + } > + > + void > + link(llvm::Module *mod, const std::string &triple, > + std::vector<llvm::Function *> kernels) { > > llvm::PassManager PM; > llvm::PassManagerBuilder Builder; > @@ -145,14 +157,37 @@ namespace { > linker.LinkInFile(llvm::sys::Path(LIBCLC_PATH + triple + > "/lib/builtins.bc"), isNative); > mod = linker.releaseModule(); > > + // Add a function internalizer pass. > + // > + // By default, the function internalizer pass will look for a function > + // called "main" and then mark all other functions as internal. > Marking > + // functions as internal enables the optimizer to perform optimizations > + // like function inlining and global dead-code elimination. > + // > + // When there is no "main" function in a module, the internalize pass > will > + // treat the module like a library, and it won't internalize any > functions. > + // Since there is no "main" function in our kernels, we need to tell > + // the internalizer pass that this module is not a library by passing a > + // list of kernel functions to the internalizer. The internalizer will > + // treat the functions in the list as "main" functions and internalize > + // all of the other functions. > + std::vector<const char*> export_list; > + for (std::vector<llvm::Function *>::iterator I = kernels.begin(), > + E = kernels.end(); > + I != E; ++I) { > + llvm::Function *kernel = *I; > + export_list.push_back(kernel->getName().data()); > + } > + PM.add(llvm::createInternalizePass(export_list)); > + > // Run link time optimizations > - Builder.populateLTOPassManager(PM, false, true); > Builder.OptLevel = 2; > + Builder.populateLTOPassManager(PM, false, true); > PM.run(*mod); > } > > module > - build_module_llvm(llvm::Module *mod) { > + build_module_llvm(llvm::Module *mod, std::vector<llvm::Function *> > kernels) { > > module m; > struct pipe_llvm_program_header header; > @@ -163,15 +198,14 @@ namespace { > llvm::WriteBitcodeToFile(mod, bitcode_ostream); > bitcode_ostream.flush(); > > + llvm::Function * kernel_func; > std::string kernel_name; > compat::vector<module::argument> args; > - const llvm::NamedMDNode *kernel_node = > - mod->getNamedMetadata("opencl.kernels"); > + > // XXX: Support more than one kernel > - assert(kernel_node->getNumOperands() <= 1); > + assert(kernels.size() == 1); > > - llvm::Function *kernel_func = llvm::dyn_cast<llvm::Function>( > - > kernel_node->getOperand(0)->getOperand(0)); > + kernel_func = kernels[0]; > kernel_name = kernel_func->getName(); > > for (llvm::Function::arg_iterator I = kernel_func->arg_begin(), > @@ -219,9 +253,13 @@ clover::compile_program_llvm(const compat::string > &source, > enum pipe_shader_ir ir, > const compat::string &triple) { > > + std::vector<llvm::Function *> kernels; > + > llvm::Module *mod = compile(source, "cl_input", triple); > > - link(mod, triple); > + find_kernels(mod, kernels); > + > + link(mod, triple, kernels); > > // Build the clover::module > switch (ir) { > @@ -230,6 +268,6 @@ clover::compile_program_llvm(const compat::string &source, > assert(0); > return module(); > default: > - return build_module_llvm(mod); > + return build_module_llvm(mod, kernels); > } > } > -- > 1.7.7.6 > > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev