[Mesa-dev] [PATCH] clover: Add a function internalizer pass before LTO
Francisco Jerez
currojerez at riseup.net
Thu Jun 28 06:45:37 PDT 2012
Tom Stellard <thomas.stellard at amd.com> writes:
> I'll commit this tomorrow unless there are objections.
>
Looks OK to me, aside from the std::vector's being passed around by
value instead of by const reference.
> -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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 229 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20120628/af342c15/attachment-0001.pgp>
More information about the mesa-dev
mailing list