[Mesa-dev] [PATCH] clover: Add a function internalizer pass before LTO
Tom Stellard
thomas.stellard at amd.com
Wed Jun 27 13:24:07 PDT 2012
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
>
>
More information about the mesa-dev
mailing list