[Beignet] [PATCH V2] remove the code of saving the llvm bitcode to file, replace it with llvm::Module

Luo, Xionghu xionghu.luo at intel.com
Fri Jun 6 02:17:46 PDT 2014


I would move some common code outside from function programNewFromSource, so please pend for the V3 update.

Luo Xionghu
Best Regards


-----Original Message-----
From: Song, Ruiling 
Sent: Friday, June 06, 2014 4:28 PM
To: Luo, Xionghu; beignet at lists.freedesktop.org
Cc: Luo, Xionghu
Subject: RE: [Beignet] [PATCH V2] remove the code of saving the llvm bitcode to file, replace it with llvm::Module

The patch looks good to me. Thanks!

-----Original Message-----
From: Beignet [mailto:beignet-bounces at lists.freedesktop.org] On Behalf Of xionghu.luo at intel.com
Sent: Thursday, June 05, 2014 8:01 AM
To: beignet at lists.freedesktop.org
Cc: Luo, Xionghu
Subject: [Beignet] [PATCH V2] remove the code of saving the llvm bitcode to file, replace it with llvm::Module

From: Luo <xionghu.luo at intel.com>

Save the global LLVMContext and module pointer to GenProgram, delete the module pointer in the destructor.

Signed-off-by: Luo <xionghu.luo at intel.com>
---
 backend/src/backend/gen_program.cpp | 33 +++++++++++++++++++--  backend/src/backend/gen_program.hpp |  4 ++-
 backend/src/backend/program.cpp     | 59 ++++++++++++++++---------------------
 backend/src/backend/program.h       |  3 +-
 backend/src/backend/program.hpp     |  2 +-
 backend/src/llvm/llvm_to_gen.cpp    | 16 ++++++----
 backend/src/llvm/llvm_to_gen.hpp    |  2 +-
 src/cl_program.c                    |  2 +-
 8 files changed, 73 insertions(+), 48 deletions(-)

diff --git a/backend/src/backend/gen_program.cpp b/backend/src/backend/gen_program.cpp
index d2e95d4..33f2ed6 100644
--- a/backend/src/backend/gen_program.cpp
+++ b/backend/src/backend/gen_program.cpp
@@ -22,6 +22,17 @@
  * \author Benjamin Segovia <benjamin.segovia at intel.com>
  */
 
+#include "llvm/Config/config.h"
+#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR <= 2 #include 
+"llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/DataLayout.h"
+#else
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/DataLayout.h"
+#endif  /* LLVM_VERSION_MINOR <= 2 */
+
 #include "backend/program.h"
 #include "backend/gen_program.h"
 #include "backend/gen_program.hpp"
@@ -33,6 +44,8 @@
 #include "ir/unit.hpp"
 #include "llvm/llvm_to_gen.hpp"
 
+#include <clang/CodeGen/CodeGenAction.h>
+
 #include <cstring>
 #include <sstream>
 #include <memory>
@@ -74,7 +87,19 @@ namespace gbe {
 #endif
   }
 
-  GenProgram::~GenProgram(void) {}
+  GenProgram::~GenProgram(void){
+#ifdef GBE_COMPILER_AVAILABLE
+    if(module){
+      delete (llvm::Module*)module;
+      module = NULL;
+    }
+
+    if(llvm_ctx){
+      delete (llvm::LLVMContext*)llvm_ctx;
+      llvm_ctx = NULL;
+    }
+#endif
+  }
 
   /*! We must avoid spilling at all cost with Gen */
   static const struct CodeGenStrategy { @@ -182,17 +207,19 @@ namespace gbe {
 
   static gbe_program genProgramNewFromLLVM(uint32_t deviceID,
                                            const char *fileName,
+                                           const void* module,
+                                           const void* llvm_ctx,
                                            size_t stringSize,
                                            char *err,
                                            size_t *errSize,
                                            int optLevel)
   {
     using namespace gbe;
-    GenProgram *program = GBE_NEW(GenProgram, deviceID);
+    GenProgram *program = GBE_NEW(GenProgram, deviceID, module, 
+ llvm_ctx);
 #ifdef GBE_COMPILER_AVAILABLE
     std::string error;
     // Try to compile the program
-    if (program->buildFromLLVMFile(fileName, error, optLevel) == false) {
+    if (program->buildFromLLVMFile(fileName, module, error, optLevel) 
+ == false) {
       if (err != NULL && errSize != NULL && stringSize > 0u) {
         const size_t msgSize = std::min(error.size(), stringSize-1u);
         std::memcpy(err, error.c_str(), msgSize); diff --git a/backend/src/backend/gen_program.hpp b/backend/src/backend/gen_program.hpp
index ea54b49..70794c9 100644
--- a/backend/src/backend/gen_program.hpp
+++ b/backend/src/backend/gen_program.hpp
@@ -58,7 +58,7 @@ namespace gbe
   {
   public:
     /*! Create an empty program */
-    GenProgram(uint32_t deviceID) : deviceID(deviceID) {}
+    GenProgram(uint32_t deviceID, const void* mod = NULL, const void* 
+ ctx = NULL) : deviceID(deviceID),module((void*)mod),
+ llvm_ctx((void*)ctx) {}
     /*! Current device ID*/
     uint32_t deviceID;
     /*! Destroy the program */
@@ -69,6 +69,8 @@ namespace gbe
     virtual Kernel *allocateKernel(const std::string &name) {
       return GBE_NEW(GenKernel, name);
     }
+    void* module;
+    void* llvm_ctx;
     /*! Use custom allocators */
     GBE_CLASS(GenProgram);
   };
diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp index 949aeb4..26d9454 100644
--- a/backend/src/backend/program.cpp
+++ b/backend/src/backend/program.cpp
@@ -34,6 +34,8 @@
 #include "llvm/Config/config.h"
 #include "llvm/Support/Threading.h"
 #include "llvm/Support/ManagedStatic.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/IR/LLVMContext.h"
 #include <cstring>
 #include <algorithm>
 #include <fstream>
@@ -103,9 +105,13 @@ namespace gbe {
 #ifdef GBE_COMPILER_AVAILABLE
   BVAR(OCL_OUTPUT_GEN_IR, false);
 
-  bool Program::buildFromLLVMFile(const char *fileName, std::string &error, int optLevel) {
+  bool Program::buildFromLLVMFile(const char *fileName, const void* 
+ module, std::string &error, int optLevel) {
     ir::Unit *unit = new ir::Unit();
-    if (llvmToGen(*unit, fileName, optLevel) == false) {
+    llvm::Module * cloned_module = NULL;
+    if(module){
+      cloned_module = llvm::CloneModule((llvm::Module*)module);
+    }
+    if (llvmToGen(*unit, fileName, module, optLevel) == false) {
       error = std::string(fileName) + " not found";
       return false;
     }
@@ -114,11 +120,18 @@ namespace gbe {
     if(!unit->getValid()) {
       delete unit;   //clear unit
       unit = new ir::Unit();
-      llvmToGen(*unit, fileName, 0);  //suppose file exists and llvmToGen will not return false.
+      if(cloned_module){
+        llvmToGen(*unit, fileName, cloned_module, 0);  //suppose file exists and llvmToGen will not return false.
+      }else{
+        llvmToGen(*unit, fileName, module, 0);  //suppose file exists and llvmToGen will not return false.
+      }
     }
     assert(unit->getValid());
     this->buildFromUnit(*unit, error);
     delete unit;
+    if(cloned_module){
+      delete (llvm::Module*) cloned_module;
+    }
     return true;
   }
 
@@ -518,7 +531,7 @@ namespace gbe {
   SVAR(OCL_PCH_PATH, PCH_OBJECT_DIR);
   SVAR(OCL_PCM_PATH, PCM_OBJECT_DIR);
 
-  static bool buildModuleFromSource(const char* input, const char* output, std::string options,
+  static bool buildModuleFromSource(const char* input, llvm::Module** 
+ out_module, llvm::LLVMContext* llvm_ctx, std::string options,
                                     size_t stringSize, char *err, size_t *errSize) {
     // Arguments to pass to the clang frontend
     vector<const char *> args;
@@ -634,7 +647,7 @@ namespace gbe {
     }
 
     // Create an action and make the compiler instance carry it out
-    llvm::OwningPtr<clang::CodeGenAction> Act(new clang::EmitLLVMOnlyAction());
+    llvm::OwningPtr<clang::CodeGenAction> Act(new 
+ clang::EmitLLVMOnlyAction(llvm_ctx));
 
     std::string dirs = OCL_PCM_PATH;
     std::string pcmFileName;
@@ -669,28 +682,7 @@ namespace gbe {
 
     llvm::Module *module = Act->takeModule();
 
-#if (LLVM_VERSION_MAJOR == 3) && (LLVM_VERSION_MINOR > 3)
-    auto mode = llvm::sys::fs::F_Binary;
-#else
-    auto mode = llvm::raw_fd_ostream::F_Binary;
-#endif
-    llvm::raw_fd_ostream OS(output, ErrorString, mode);
-    //still write to temp file for code simply, otherwise need add another function.
-    //because gbe_program_new_from_llvm also be used by cl_program_create_from_llvm, can't be removed
-    //TODO: Pass module to llvmToGen, if use module, should return Act and use OwningPtr out of this funciton
-    llvm::WriteBitcodeToFile(module, OS);
-    if (err != NULL && *errSize < stringSize - 1 && ErrorString.size() > 0) {
-      size_t errLen;
-      errLen = ErrorString.copy(err + *errSize, stringSize - *errSize - 1, 0);
-      *errSize += errLen;
-    }
-
-    if (err == NULL || OCL_OUTPUT_BUILD_LOG) {
-      // flush the error messages to the errs() if there is no
-      // error string buffer.
-      llvm::errs() << ErrorString;
-    }
-    OS.close();
+    *out_module = module;
     return true;
   }
 
@@ -705,12 +697,8 @@ namespace gbe {
                                           size_t *errSize)
   {
     char clStr[] = "/tmp/XXXXXX.cl";
-    char llStr[] = "/tmp/XXXXXX.ll";
     int clFd = mkstemps(clStr, 3);
-    int llFd = mkstemps(llStr, 3);
-    close(llFd);
     const std::string clName = std::string(clStr);
-    const std::string llName = std::string(llStr);
     std::string clOpt;
     int optLevel = 1;
 
@@ -825,7 +813,10 @@ namespace gbe {
     fclose(clFile);
 
     gbe_program p;
-    if (buildModuleFromSource(clName.c_str(), llName.c_str(), clOpt.c_str(),
+    // will delete the module and act in the destructor of GenProgram.
+    llvm::Module * out_module;
+    llvm::LLVMContext* llvm_ctx = new llvm::LLVMContext;
+    if (buildModuleFromSource(clName.c_str(), &out_module, llvm_ctx, 
+ clOpt.c_str(),
                               stringSize, err, errSize)) {
     // Now build the program from llvm
       static std::mutex gbe_mutex;
@@ -837,14 +828,14 @@ namespace gbe {
         err += *errSize;
         clangErrSize = *errSize;
       }
-      p = gbe_program_new_from_llvm(deviceID, llName.c_str(), stringSize,
+
+      p = gbe_program_new_from_llvm(deviceID, NULL, out_module, 
+ llvm_ctx, stringSize,
                                     err, errSize, optLevel);
       if (err != NULL)
         *errSize += clangErrSize;
       gbe_mutex.unlock();
       if (OCL_OUTPUT_BUILD_LOG && options)
         llvm::errs() << options;
-      remove(llName.c_str());
     } else
       p = NULL;
     remove(clName.c_str());
diff --git a/backend/src/backend/program.h b/backend/src/backend/program.h index 8727966..5c72964 100644
--- a/backend/src/backend/program.h
+++ b/backend/src/backend/program.h
@@ -120,7 +120,6 @@ typedef gbe_program (gbe_program_new_from_source_cb)(uint32_t deviceID,
                                                      char *err,
                                                      size_t *err_size);  extern gbe_program_new_from_source_cb *gbe_program_new_from_source;
-
 /*! Create a new program from the given blob */  typedef gbe_program (gbe_program_new_from_binary_cb)(uint32_t deviceID, const char *binary, size_t size);  extern gbe_program_new_from_binary_cb *gbe_program_new_from_binary; @@ -132,6 +131,8 @@ extern gbe_program_serialize_to_binary_cb *gbe_program_serialize_to_binary;  /*! Create a new program from the given LLVM file */  typedef gbe_program (gbe_program_new_from_llvm_cb)(uint32_t deviceID,
                                                    const char *fileName,
+                                                   const void *module,
+                                                   const void 
+ *llvm_ctx,
                                                    size_t string_size,
                                                    char *err,
                                                    size_t *err_size, diff --git a/backend/src/backend/program.hpp b/backend/src/backend/program.hpp index 6bb1529..1235d51 100644
--- a/backend/src/backend/program.hpp
+++ b/backend/src/backend/program.hpp
@@ -234,7 +234,7 @@ namespace gbe {
     /*! Build a program from a ir::Unit */
     bool buildFromUnit(const ir::Unit &unit, std::string &error);
     /*! Buils a program from a LLVM source code */
-    bool buildFromLLVMFile(const char *fileName, std::string &error, int optLevel);
+    bool buildFromLLVMFile(const char *fileName, const void* module, 
+ std::string &error, int optLevel);
     /*! Buils a program from a OCL string */
     bool buildFromSource(const char *source, std::string &error);
     /*! Get size of the global constant arrays */ diff --git a/backend/src/llvm/llvm_to_gen.cpp b/backend/src/llvm/llvm_to_gen.cpp
index 9282b3f..2bb9da1 100644
--- a/backend/src/llvm/llvm_to_gen.cpp
+++ b/backend/src/llvm/llvm_to_gen.cpp
@@ -61,6 +61,8 @@
 #include "sys/cvar.hpp"
 #include "sys/platform.hpp"
 
+#include <clang/CodeGen/CodeGenAction.h>
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -163,10 +165,8 @@ namespace gbe
     MPM.run(mod);
   }
 
-  bool llvmToGen(ir::Unit &unit, const char *fileName, int optLevel)
+  bool llvmToGen(ir::Unit &unit, const char *fileName,const void* 
+ module, int optLevel)
   {
-    // Get the global LLVM context
-    llvm::LLVMContext& c = llvm::getGlobalContext();
     std::string errInfo;
     std::unique_ptr<llvm::raw_fd_ostream> o = NULL;
     if (OCL_OUTPUT_LLVM_BEFORE_EXTRA_PASS || OCL_OUTPUT_LLVM) @@ -175,9 +175,13 @@ namespace gbe
     // Get the module from its file
     llvm::SMDiagnostic Err;
     std::auto_ptr<Module> M;
-    M.reset(ParseIRFile(fileName, Err, c));
-    if (M.get() == 0) return false;
-    Module &mod = *M.get();
+    if(fileName){
+      // only when module is null, Get the global LLVM context
+      llvm::LLVMContext& c = llvm::getGlobalContext();
+      M.reset(ParseIRFile(fileName, Err, c));
+      if (M.get() == 0) return false;
+    }
+    Module &mod = (module!=NULL)?*(llvm::Module*)module:*M.get();
 
     Triple TargetTriple(mod.getTargetTriple());
     TargetLibraryInfo *libraryInfo = new TargetLibraryInfo(TargetTriple); diff --git a/backend/src/llvm/llvm_to_gen.hpp b/backend/src/llvm/llvm_to_gen.hpp
index 50ea267..41e3477 100644
--- a/backend/src/llvm/llvm_to_gen.hpp
+++ b/backend/src/llvm/llvm_to_gen.hpp
@@ -32,7 +32,7 @@ namespace gbe {
 
   /*! Convert the LLVM IR code to a GEN IR code,
 		  optLevel 0 equal to clang -O1 and 1 equal to clang -O2*/
-  bool llvmToGen(ir::Unit &unit, const char *fileName, int optLevel);
+  bool llvmToGen(ir::Unit &unit, const char *fileName, const void* 
+ module, int optLevel);
 
 } /* namespace gbe */
 
diff --git a/src/cl_program.c b/src/cl_program.c index af9d21e..42058e8 100644
--- a/src/cl_program.c
+++ b/src/cl_program.c
@@ -226,7 +226,7 @@ cl_program_create_from_llvm(cl_context ctx,
   INVALID_VALUE_IF (file_name == NULL);
 
   program = cl_program_new(ctx);
-  program->opaque = compiler_program_new_from_llvm(ctx->device->vendor_id, file_name, program->build_log_max_sz, program->build_log, &program->build_log_sz, 1);
+  program->opaque =
+ compiler_program_new_from_llvm(ctx->device->vendor_id, file_name, 
+ NULL, NULL, program->build_log_max_sz, program->build_log, 
+ &program->build_log_sz, 1);
   if (UNLIKELY(program->opaque == NULL)) {
     err = CL_INVALID_PROGRAM;
     goto error;
--
1.8.1.2

_______________________________________________
Beignet mailing list
Beignet at lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/beignet


More information about the Beignet mailing list