Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2012, 2013 Advanced Micro Devices, Inc.
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21.  * SOFTWARE.
  22.  *
  23.  * Authors: Tom Stellard <thomas.stellard@amd.com>
  24.  *
  25.  */
  26.  
  27. #include "radeon_llvm_util.h"
  28. #include "util/u_memory.h"
  29.  
  30. #include <llvm-c/BitReader.h>
  31. #include <llvm-c/Core.h>
  32. #include <llvm-c/Target.h>
  33. #include <llvm-c/Transforms/IPO.h>
  34. #include <llvm-c/Transforms/PassManagerBuilder.h>
  35.  
  36. LLVMModuleRef radeon_llvm_parse_bitcode(LLVMContextRef ctx,
  37.                                                         const char * bitcode, unsigned bitcode_len)
  38. {
  39.         LLVMMemoryBufferRef buf;
  40.         LLVMModuleRef module;
  41.  
  42.         buf = LLVMCreateMemoryBufferWithMemoryRangeCopy((const char*)bitcode,
  43.                                                         bitcode_len, "radeon");
  44.         LLVMParseBitcodeInContext(ctx, buf, &module, NULL);
  45.         LLVMDisposeMemoryBuffer(buf);
  46.         return module;
  47. }
  48.  
  49. unsigned radeon_llvm_get_num_kernels(LLVMContextRef ctx,
  50.                                 const char *bitcode, unsigned bitcode_len)
  51. {
  52.         LLVMModuleRef mod = radeon_llvm_parse_bitcode(ctx, bitcode, bitcode_len);
  53.         return LLVMGetNamedMetadataNumOperands(mod, "opencl.kernels");
  54. }
  55.  
  56. static void radeon_llvm_optimize(LLVMModuleRef mod)
  57. {
  58.         const char *data_layout = LLVMGetDataLayout(mod);
  59.         LLVMTargetDataRef TD = LLVMCreateTargetData(data_layout);
  60.         LLVMPassManagerBuilderRef builder = LLVMPassManagerBuilderCreate();
  61.         LLVMPassManagerRef pass_manager = LLVMCreatePassManager();
  62.  
  63.         /* Functions calls are not supported yet, so we need to inline
  64.          * everything.  The most efficient way to do this is to add
  65.          * the always_inline attribute to all non-kernel functions
  66.          * and then run the Always Inline pass.  The Always Inline
  67.          * pass will automaically inline functions with this attribute
  68.          * and does not perform the expensive cost analysis that the normal
  69.          * inliner does.
  70.          */
  71.  
  72.         LLVMValueRef fn;
  73.         for (fn = LLVMGetFirstFunction(mod); fn; fn = LLVMGetNextFunction(fn)) {
  74.                 /* All the non-kernel functions have internal linkage */
  75.                 if (LLVMGetLinkage(fn) == LLVMInternalLinkage) {
  76.                         LLVMAddFunctionAttr(fn, LLVMAlwaysInlineAttribute);
  77.                 }
  78.         }
  79.  
  80.         LLVMAddTargetData(TD, pass_manager);
  81.         LLVMAddAlwaysInlinerPass(pass_manager);
  82.         LLVMPassManagerBuilderPopulateModulePassManager(builder, pass_manager);
  83.  
  84.         LLVMRunPassManager(pass_manager, mod);
  85.         LLVMPassManagerBuilderDispose(builder);
  86.         LLVMDisposePassManager(pass_manager);
  87.         LLVMDisposeTargetData(TD);
  88. }
  89.  
  90. LLVMModuleRef radeon_llvm_get_kernel_module(LLVMContextRef ctx, unsigned index,
  91.                 const char *bitcode, unsigned bitcode_len)
  92. {
  93.         LLVMModuleRef mod;
  94.         unsigned num_kernels;
  95.         LLVMValueRef *kernel_metadata;
  96.         unsigned i;
  97.  
  98.         mod = radeon_llvm_parse_bitcode(ctx, bitcode, bitcode_len);
  99.         num_kernels = LLVMGetNamedMetadataNumOperands(mod, "opencl.kernels");
  100.         kernel_metadata = MALLOC(num_kernels * sizeof(LLVMValueRef));
  101.         LLVMGetNamedMetadataOperands(mod, "opencl.kernels", kernel_metadata);
  102.         for (i = 0; i < num_kernels; i++) {
  103.                 LLVMValueRef kernel_signature, *kernel_function;
  104.                 unsigned num_kernel_md_operands;
  105.                 if (i == index) {
  106.                         continue;
  107.                 }
  108.                 kernel_signature = kernel_metadata[i];
  109.                 num_kernel_md_operands = LLVMGetMDNodeNumOperands(kernel_signature);
  110.                 kernel_function = MALLOC(num_kernel_md_operands * sizeof (LLVMValueRef));
  111.                 LLVMGetMDNodeOperands(kernel_signature, kernel_function);
  112.                 LLVMDeleteFunction(*kernel_function);
  113.                 FREE(kernel_function);
  114.         }
  115.         FREE(kernel_metadata);
  116.         radeon_llvm_optimize(mod);
  117.         return mod;
  118. }
  119.