[Beignet] [PATCH 03/18] Add the bit code linker into the module pass.

junyan.he at inbox.com junyan.he at inbox.com
Tue Aug 12 00:31:22 PDT 2014


From: Junyan He <junyan.he at linux.intel.com>

The bit code linker will load the beignet.bc as a
lib module and link the module of the kernel together.
Then we will filter out all the dead bit code by create
an InternalizePass for the module.
After this stage, the ir will include the bitcode just
used by the cl kernel.

Signed-off-by: Junyan He <junyan.he at linux.intel.com>
---
 backend/src/CMakeLists.txt             |   1 +
 backend/src/llvm/llvm_bitcode_link.cpp | 123 +++++++++++++++++++++++++++++++++
 2 files changed, 124 insertions(+)
 create mode 100644 backend/src/llvm/llvm_bitcode_link.cpp

diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt
index 63eb0f0..262815c 100644
--- a/backend/src/CMakeLists.txt
+++ b/backend/src/CMakeLists.txt
@@ -154,6 +154,7 @@ else (GBE_USE_BLOB)
     backend/program.cpp
     backend/program.hpp
     backend/program.h
+    llvm/llvm_bitcode_link.cpp
     llvm/llvm_gen_backend.cpp
     llvm/llvm_passes.cpp
     llvm/llvm_scalarize.cpp
diff --git a/backend/src/llvm/llvm_bitcode_link.cpp b/backend/src/llvm/llvm_bitcode_link.cpp
new file mode 100644
index 0000000..90ab4e1
--- /dev/null
+++ b/backend/src/llvm/llvm_bitcode_link.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Pass.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+
+#include "sys/cvar.hpp"
+#include "src/GBEConfig.h"
+#include "llvm/llvm_gen_backend.hpp"
+#include "llvm/Linker.h"
+
+using namespace llvm;
+
+SVAR(OCL_BITCODE_LIB_PATH, OCL_BITCODE_BIN);
+
+namespace gbe
+{
+  static bool is_error(error_code ec)
+  {
+    if (ec) {
+      printf("Bitcode Link Error: %s\n", ec.message().c_str());
+      return true;
+    }
+    return false;
+  }
+
+  static Module* createOclBitCodeModule(LLVMContext& ctx)
+  {
+    error_code err;
+    std::string bitCodeFile = OCL_BITCODE_LIB_PATH;
+    Module* oclLib = NULL;
+
+    if (!sys::fs::exists(bitCodeFile)) {
+      printf("Fatal Error: can not open the bitcode ocl lib in %s\n",
+             bitCodeFile.c_str());
+      return NULL;
+    }
+
+    OwningPtr<MemoryBuffer> Buffer;
+    if (is_error(MemoryBuffer::getFile(bitCodeFile, Buffer))) {
+      return NULL;
+    }
+
+    sys::fs::file_magic magic = sys::fs::identify_magic(Buffer->getBuffer());
+    if (magic != sys::fs::file_magic::bitcode) {
+      printf("Fatal Error: ocl lib %s is not a bitcode file\n", bitCodeFile.c_str());
+      return NULL;
+    }
+
+    std::string errorMessage;
+    oclLib = ParseBitcodeFile(Buffer.get(), ctx, &errorMessage);
+    if (!oclLib) {
+      printf("Fatal Error: ocl lib %s can not be opened, because %s\n",
+             bitCodeFile.c_str(), errorMessage.c_str());
+      return NULL;
+    }
+
+    return oclLib;
+  }
+
+  Module* runBitCodeLinker(Module *mod)
+  {
+    LLVMContext& ctx = mod->getContext();
+
+    std::vector<const char *> kernels;
+    for (Module::iterator SF = mod->begin(), E = mod->end(); SF != E; ++SF) {
+      if (SF->isDeclaration()) continue;
+      if (!isKernelFunction(*SF)) continue;
+      kernels.push_back(SF->getName().data());
+    }
+
+    if (kernels.empty()) {
+      printf("One module without kernel function!\n");
+      return NULL;
+    }
+
+    Module* clonedLib = createOclBitCodeModule(ctx);
+    assert(clonedLib && "Can not create the beignet bitcode\n");
+
+    /* We use beignet's bitcode as dst because it will have a lot of
+       lazy functions which will not be loaded. */
+    if(Linker::LinkModules(clonedLib, mod, Linker::DestroySource, NULL)) {
+      delete clonedLib;
+      printf("Fatal Error: link the bitcode error\n");
+      return NULL;
+    }
+
+    llvm::PassManager passes;
+
+    passes.add(createInternalizePass(kernels));
+    passes.add(createGlobalDCEPass());
+
+    passes.run(*clonedLib);
+
+    return clonedLib;
+  }
+
+} // end namespace
-- 
1.8.3.2



More information about the Beignet mailing list