[Beignet] [PATCH V3] remove the code of saving the llvm bitcode to file, replace it with llvm::Module
Song, Ruiling
ruiling.song at intel.com
Mon Jun 9 01:26:56 PDT 2014
This version looks good to me.
-----Original Message-----
From: Beignet [mailto:beignet-bounces at lists.freedesktop.org] On Behalf Of xionghu.luo at intel.com
Sent: Friday, June 06, 2014 2:18 PM
To: beignet at lists.freedesktop.org
Cc: Luo, Xionghu
Subject: [Beignet] [PATCH V3] 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 | 95 ++++++++++++++++++++-----------------
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, 100 insertions(+), 57 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..6e50761 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,50 +682,23 @@ 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;
}
extern std::string ocl_stdlib_str;
BVAR(OCL_USE_PCH, true);
- static gbe_program programNewFromSource(uint32_t deviceID,
- const char *source,
- size_t stringSize,
- const char *options,
- char *err,
- size_t *errSize)
+ static void processSourceAndOption(const char *source,
+ const char *options,
+ const char *temp_header_path,
+ std::string& clOpt,
+ std::string& clName,
+ int& optLevel)
{
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;
+ clName = std::string(clStr);
FILE *clFile = fdopen(clFd, "w");
FATAL_IF(clFile == NULL, "Failed to open temporary file"); @@ -812,6 +798,13 @@ namespace gbe {
} else
fwrite(ocl_stdlib_str.c_str(), strlen(ocl_stdlib_str.c_str()), 1, clFile);
+ //for clCompilerProgram usage.
+ if(temp_header_path){
+ clOpt += " -I ";
+ clOpt += temp_header_path;
+ clOpt += " ";
+ }
+
if (!OCL_STRICT_CONFORMANCE) {
fwrite(ocl_mathfunc_fastpath_str.c_str(), strlen(ocl_mathfunc_fastpath_str.c_str()), 1, clFile);
}
@@ -823,9 +816,25 @@ namespace gbe {
// Write the source to the cl file
fwrite(source, strlen(source), 1, clFile);
fclose(clFile);
+ }
+
+ static gbe_program programNewFromSource(uint32_t deviceID,
+ const char *source,
+ size_t stringSize,
+ const char *options,
+ char *err,
+ size_t *errSize) {
+ int optLevel = 1;
+ std::string clOpt;
+ std::string clName;
+ processSourceAndOption(source, options, NULL, clOpt, clName,
+ optLevel);
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 +846,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