[Beignet] [PATCH 20/22 V3] Enable libocl and disable the usage of the old huge header.

junyan.he at inbox.com junyan.he at inbox.com
Mon Sep 1 00:28:02 PDT 2014


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

The llvm ir print out is modified.
>From the OCL_OUTPUT_LLVM_BEFORE_EXTRA_PASS and
OCL_OUTPUT_LLVM, we change to
OCL_OUTPUT_LLVM_BEFORE_LINK
OCL_OUTPUT_LLVM_AFTER_LINK
OCL_OUTPUT_LLVM_AFTER_GEN
The first one print out the IR before link the bitcode lib.
The second one print out the IR result after linking.
Then last one print out the IR after gen translating.

Signed-off-by: Junyan He <junyan.he at linux.intel.com>
---
 backend/CMakeLists.txt            |    8 +-
 backend/src/CMakeLists.txt        |  135 ++++--------------
 backend/src/GBEConfig.h.in        |    5 +-
 backend/src/backend/program.cpp   |  276 +++++++++----------------------------
 backend/src/libocl/CMakeLists.txt |  209 ++++++++++++++++++++++++++++
 backend/src/libocl/include/ocl.h  |   23 ++++
 backend/src/llvm/llvm_to_gen.cpp  |   70 +++++++---
 utests/setenv.sh.in               |    5 +-
 8 files changed, 379 insertions(+), 352 deletions(-)
 create mode 100644 backend/src/libocl/CMakeLists.txt
 create mode 100644 backend/src/libocl/include/ocl.h

diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt
index ca674cf..832eda8 100644
--- a/backend/CMakeLists.txt
+++ b/backend/CMakeLists.txt
@@ -99,12 +99,14 @@ include_directories (${CMAKE_CURRENT_BINARY_DIR})
 # Project source code
 ##############################################################
 add_subdirectory (src)
-set(LOCAL_PCH_OBJECT_DIR ${LOCAL_PCH_OBJECT_DIR} PARENT_SCOPE)
-set(LOCAL_PCM_OBJECT_DIR ${LOCAL_PCM_OBJECT_DIR} PARENT_SCOPE)
+set(LOCAL_OCL_BITCODE_BIN "${LOCAL_OCL_BITCODE_BIN}" PARENT_SCOPE)
+set(LOCAL_OCL_HEADER_DIR "${LOCAL_OCL_HEADER_DIR}" PARENT_SCOPE)
+set(LOCAL_OCL_PCH_OBJECT "${LOCAL_OCL_PCH_OBJECT}" PARENT_SCOPE)
+
 set(LOCAL_GBE_OBJECT_DIR ${LOCAL_GBE_OBJECT_DIR} PARENT_SCOPE)
 set(LOCAL_INTERP_OBJECT_DIR ${LOCAL_INTERP_OBJECT_DIR} PARENT_SCOPE)
 
 set (GBE_BIN_GENERATER
-     OCL_PCM_PATH=${LOCAL_PCM_OBJECT_DIR} OCL_PCH_PATH=${LOCAL_PCH_OBJECT_DIR} LD_LIBRARY_PATH=${CMAKE_CURRENT_BINARY_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/src/gbe_bin_generater
+     OCL_BITCODE_BIN=${LOCAL_OCL_BITCODE_BIN} OCL_HEADER_DIR=${LOCAL_OCL_HEADER_DIR} OCL_PCH_OBJECT=${LOCAL_OCL_PCH_OBJECT} LD_LIBRARY_PATH=${CMAKE_CURRENT_BINARY_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/src/gbe_bin_generater
      PARENT_SCOPE)
 
diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt
index 85b5e21..1df8732 100644
--- a/backend/src/CMakeLists.txt
+++ b/backend/src/CMakeLists.txt
@@ -1,95 +1,25 @@
-set (ocl_vector_spec_file ${GBE_SOURCE_DIR}/src/builtin_vector_proto.def)
-set (ocl_vector_file ${GBE_SOURCE_DIR}/src/ocl_vector.h)
-set (ocl_as_file ${GBE_SOURCE_DIR}/src/ocl_as.h)
-set (ocl_convert_file ${GBE_SOURCE_DIR}/src/ocl_convert.h)
-set (ocl_stdlib_tmpl_file ${GBE_SOURCE_DIR}/src/ocl_stdlib.tmpl.h)
-set (ocl_common_header_file ${GBE_SOURCE_DIR}/src/ocl_common_defines.h)
-set (ocl_blob_file ${CMAKE_CURRENT_BINARY_DIR}${BEIGNET_INSTALL_DIR}ocl_stdlib.h)
-set (ocl_blob_cpp_file ${GBE_SOURCE_DIR}/src/ocl_stdlib_str.cpp)
-set (ocl_gen_blob_cmd ${GBE_SOURCE_DIR}/src/update_blob_ocl_header.py)
-set (ocl_gen_vector_cmd ${GBE_SOURCE_DIR}/src/gen_builtin_vector.py)
-
-set (string_header "\\\"string\\\"")
-add_custom_command(
-    OUTPUT ${ocl_blob_cpp_file}
-    COMMAND rm -rf ${ocl_blob_cpp_file}
-    COMMAND echo "\\\#include ${string_header}" >> ${ocl_blob_cpp_file}
-    COMMAND echo "namespace gbe {" >> ${ocl_blob_cpp_file}
-    COMMAND echo "std::string ocl_stdlib_str = " >> ${ocl_blob_cpp_file}
-    # Yeah!!! welcome to back slash hell
-    COMMAND cat ${ocl_blob_file} |sed 's/\\\\/\\\\\\\\/g' | sed 's/\\\"/\\\\\\\"/g' | awk '{ printf \(\"\\"%s\\\\n\\"\\n\", $$0\) }' >> ${ocl_blob_cpp_file}
-    COMMAND echo "\;" >> ${ocl_blob_cpp_file}
-    COMMAND echo "}" >> ${ocl_blob_cpp_file}
-    COMMAND echo "" >> ${ocl_blob_cpp_file}
-    DEPENDS ${ocl_blob_file})
-
-set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "ocl_vector.h;${ocl_blob_file}")
-
-add_custom_command(
-  OUTPUT ${ocl_vector_file}
-  COMMAND ${PYTHON_EXECUTABLE} ${ocl_gen_vector_cmd} ${ocl_vector_spec_file} ${ocl_vector_file}
-  DEPENDS ${ocl_gen_vector_cmd} ${ocl_vector_spec_file}
-  )
-
-add_custom_command(
-  OUTPUT ${ocl_blob_file}
-  COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/${BEIGNET_INSTALL_DIR}
-  COMMAND ${PYTHON_EXECUTABLE} ${ocl_gen_blob_cmd} ${ocl_stdlib_tmpl_file} ${ocl_blob_file}
-  DEPENDS ${ocl_gen_blob_cmd} ${ocl_stdlib_tmpl_file} ${ocl_common_header_file} ${ocl_vector_file} ${ocl_as_file} ${ocl_convert_file}
-  )
-
-set (pch_object ${ocl_blob_file}.pch)
-set (local_pch_object ${ocl_blob_file}.local.pch)
-# generate pch object
-if (LLVM_VERSION_NODOT VERSION_GREATER 32)
-    set (clang_cmd -cc1 -x cl -triple spir -ffp-contract=off -cl-kernel-arg-info)
-else (LLVM_VERSION_NODOT VERSION_GREATER 32)
-    if (LLVM_VERSION_NODOT VERSION_GREATER 31)
-        set (clang_cmd -cc1 -x cl -triple nvptx -ffp-contract=off)
-    else (LLVM_VERSION_NODOT VERSION_GREATER 31)
-        set (clang_cmd -cc1 -x cl -triple ptx32)
-    endif (LLVM_VERSION_NODOT VERSION_GREATER 31)
-endif (LLVM_VERSION_NODOT VERSION_GREATER 32)
-set (clang_cmd ${clang_cmd} -fno-builtin -DGEN7_SAMPLER_CLAMP_BORDER_WORKAROUND)
+set (OCL_BITCODE_BIN "${BEIGNET_INSTALL_DIR}beignet.bc:${CMAKE_CURRENT_BINARY_DIR}/libocl/lib/beignet.bc")
+set (OCL_HEADER_DIR "${CMAKE_INSTALL_PREFIX}/include/CL/ocl/:${CMAKE_CURRENT_BINARY_DIR}/libocl/include/")
+set (OCL_PCH_OBJECT "${BEIGNET_INSTALL_DIR}beignet.pch:${CMAKE_CURRENT_BINARY_DIR}/libocl/lib/beignet.pch")
+set (GBE_OBJECT_DIR "${BEIGNET_INSTALL_DIR}/libgbe.so")
+set (INTERP_OBJECT_DIR "${BEIGNET_INSTALL_DIR}/libgbeinterp.so")
 
-add_custom_command(
-     OUTPUT ${pch_object}
-     COMMAND rm -f ${pch_object}
-     COMMAND ${LLVM_INSTALL_DIR}clang ${clang_cmd} --relocatable-pch -emit-pch -isysroot ${CMAKE_CURRENT_BINARY_DIR} ${ocl_blob_file} -o ${pch_object}
-     COMMAND ${LLVM_INSTALL_DIR}clang ${clang_cmd} -emit-pch ${ocl_blob_file} -o ${local_pch_object}
-     DEPENDS ${ocl_blob_file}
-     )
+set (LOCAL_GBE_OBJECT_DIR "${CMAKE_CURRENT_BINARY_DIR}/libgbe.so" PARENT_SCOPE)
+set (LOCAL_OCL_BITCODE_BIN "${CMAKE_CURRENT_BINARY_DIR}/libocl/lib/beignet.bc" PARENT_SCOPE)
+set (LOCAL_OCL_HEADER_DIR "${CMAKE_CURRENT_BINARY_DIR}/libocl/include/" PARENT_SCOPE)
+set (LOCAL_OCL_PCH_OBJECT "${CMAKE_CURRENT_BINARY_DIR}/libocl/lib/beignet.pch" PARENT_SCOPE)
+set (LOCAL_INTERP_OBJECT_DIR "${CMAKE_CURRENT_BINARY_DIR}/libgbeinterp.so" PARENT_SCOPE)
 
-add_custom_target(pch_object
-                  DEPENDS ${pch_object})
+configure_file (
+    "GBEConfig.h.in"
+    "GBEConfig.h"
+)
 
-macro(ll_add_library ll_lib ll_sources)
-  foreach (ll ${${ll_sources}})
-  add_custom_command(
-       OUTPUT  ${ll}.bc
-       COMMAND rm -f ${ll}.bc
-       COMMAND ${LLVM_INSTALL_DIR}llvm-as -o ${ll}.bc ${GBE_SOURCE_DIR}/src/${ll}
-       DEPENDS ${ll}
-       )
-  set (ll_objects ${ll_objects} ${ll}.bc)
-  endforeach (ll ${ll_sources})
-  add_custom_command(
-       OUTPUT ${ll_lib}
-       COMMAND ${LLVM_INSTALL_DIR}llvm-link -o ${ll_lib} ${ll_objects}
-       DEPENDS ${ll_objects}
-       )
-  add_custom_target(${ll_lib}
-                    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ll_lib})
-endmacro(ll_add_library)
+add_subdirectory(libocl)
+add_dependencies(beignet_bitcode libocl)
 
-if (GBE_USE_BLOB)
-  set (GBE_SRC
-       blob.cpp
-       backend/gen/gen_mesa_disasm.c)
-else (GBE_USE_BLOB)
-  set (GBE_SRC
+set (GBE_SRC
     ${ocl_blob_file}
-    ocl_stdlib_str.cpp  # this file is auto-generated.
     sys/vector.hpp
     sys/hash_map.hpp
     sys/map.hpp
@@ -143,6 +73,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
@@ -176,19 +107,13 @@ else (GBE_USE_BLOB)
     backend/gen75_encoder.cpp
     )
 
-endif (GBE_USE_BLOB)
 
 include_directories (.)
 link_directories (${LLVM_LIBRARY_DIRS} ${DRM_LIBDIR})
 include_directories(${LLVM_INCLUDE_DIRS})
 add_library (gbe SHARED ${GBE_SRC})
 
-# for pre compiled module library.
-set (pcm_lib "beignet.bc")
-set (pcm_sources ocl_barrier.ll ocl_memset.ll ocl_memcpy.ll)
-ll_add_library (${pcm_lib} pcm_sources)
 
-ADD_DEPENDENCIES (gbe pch_object ${pcm_lib})
 target_link_libraries(
                       gbe
                       ${DRM_INTEL_LIBRARIES}
@@ -201,6 +126,8 @@ target_link_libraries(
 
 add_library(gbeinterp SHARED gbe_bin_interpreter.cpp)
 
+add_dependencies(gbe beignet_bitcode)
+
 if (LLVM_VERSION_NODOT VERSION_EQUAL 34)
   find_library(TERMINFO NAMES tinfo ncurses)
   if (${TERMINFO} STREQUAL TERMINFO-NOTFOUND)
@@ -217,22 +144,6 @@ TARGET_LINK_LIBRARIES(gbe_bin_generater gbe)
 
 install (TARGETS gbe LIBRARY DESTINATION ${BEIGNET_INSTALL_DIR})
 install (TARGETS gbeinterp LIBRARY DESTINATION ${BEIGNET_INSTALL_DIR})
-#install (FILES backend/program.h DESTINATION include/gen)
-install (FILES ${ocl_blob_file} DESTINATION ${BEIGNET_INSTALL_DIR})
-install (FILES ${pch_object} DESTINATION ${BEIGNET_INSTALL_DIR})
-install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${pcm_lib} DESTINATION ${BEIGNET_INSTALL_DIR})
-# When build beignet itself, we need to export the local precompiled header file and precompiled module
-# file to libcl and utests.
-set (LOCAL_PCH_OBJECT_DIR "${local_pch_object}:${BEIGNET_INSTALL_DIR}/ocl_stdlib.h.pch" PARENT_SCOPE)
-set (LOCAL_PCM_OBJECT_DIR "${CMAKE_CURRENT_BINARY_DIR}/${pcm_lib}:${BEIGNET_INSTALL_DIR}/${pcm_lib}" PARENT_SCOPE)
-set (LOCAL_GBE_OBJECT_DIR "${CMAKE_CURRENT_BINARY_DIR}/libgbe.so" PARENT_SCOPE)
-set (LOCAL_INTERP_OBJECT_DIR "${CMAKE_CURRENT_BINARY_DIR}/libgbeinterp.so" PARENT_SCOPE)
-
-set (PCH_OBJECT_DIR "${BEIGNET_INSTALL_DIR}/ocl_stdlib.h.pch")
-set (PCM_OBJECT_DIR "${BEIGNET_INSTALL_DIR}/${pcm_lib}")
-set (GBE_OBJECT_DIR "${BEIGNET_INSTALL_DIR}/libgbe.so")
-set (INTERP_OBJECT_DIR "${BEIGNET_INSTALL_DIR}/libgbeinterp.so")
-configure_file (
-  "GBEConfig.h.in"
-  "GBEConfig.h"
-)
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/libocl/lib/beignet.bc DESTINATION ${BEIGNET_INSTALL_DIR})
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/libocl/lib/beignet.pch DESTINATION ${BEIGNET_INSTALL_DIR})
+install (DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/libocl/include/ DESTINATION ${CMAKE_INSTALL_PREFIX}/include/CL/ocl/ PATTERN *.h)
diff --git a/backend/src/GBEConfig.h.in b/backend/src/GBEConfig.h.in
index f5c69c6..b5bec14 100644
--- a/backend/src/GBEConfig.h.in
+++ b/backend/src/GBEConfig.h.in
@@ -1,7 +1,8 @@
 // the configured options and settings for LIBGBE
 #define LIBGBE_VERSION_MAJOR @LIBGBE_VERSION_MAJOR@
 #define LIBGBE_VERSION_MINOR @LIBGBE_VERSION_MINOR@
-#define PCH_OBJECT_DIR "@PCH_OBJECT_DIR@"
-#define PCM_OBJECT_DIR "@PCM_OBJECT_DIR@"
 #define GBE_OBJECT_DIR "@GBE_OBJECT_DIR@"
 #define INTERP_OBJECT_DIR "@INTERP_OBJECT_DIR@"
+#define OCL_BITCODE_BIN "@OCL_BITCODE_BIN@"
+#define OCL_HEADER_DIR "@OCL_HEADER_DIR@"
+#define OCL_PCH_OBJECT "@OCL_PCH_OBJECT@"
diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp
index d992f7b..c04b752 100644
--- a/backend/src/backend/program.cpp
+++ b/backend/src/backend/program.cpp
@@ -491,38 +491,6 @@ namespace gbe {
 
   /*********************** End of Program class member function *************************/
 
-#define REDEF_MATH_FUNC(x) "#ifdef "#x"\n#undef "#x"\n#endif\n#define "#x" __gen_ocl_internal_fastpath_"#x"\n"
-  std::string ocl_mathfunc_fastpath_str =
-    REDEF_MATH_FUNC(acosh)
-    REDEF_MATH_FUNC(asinh)
-    REDEF_MATH_FUNC(atanh)
-    REDEF_MATH_FUNC(cbrt)
-    REDEF_MATH_FUNC(cos)
-    REDEF_MATH_FUNC(cosh)
-    REDEF_MATH_FUNC(cospi)
-    REDEF_MATH_FUNC(exp)
-    REDEF_MATH_FUNC(exp10)
-    REDEF_MATH_FUNC(expm1)
-    REDEF_MATH_FUNC(fmod)
-    REDEF_MATH_FUNC(hypot)
-    REDEF_MATH_FUNC(ilogb)
-    REDEF_MATH_FUNC(ldexp)
-    REDEF_MATH_FUNC(log)
-    REDEF_MATH_FUNC(log2)
-    REDEF_MATH_FUNC(log10)
-    REDEF_MATH_FUNC(log1p)
-    REDEF_MATH_FUNC(logb)
-    REDEF_MATH_FUNC(remainder)
-    REDEF_MATH_FUNC(rootn)
-    REDEF_MATH_FUNC(sin)
-    REDEF_MATH_FUNC(sincos)
-    REDEF_MATH_FUNC(sinh)
-    REDEF_MATH_FUNC(sinpi)
-    REDEF_MATH_FUNC(tan)
-    REDEF_MATH_FUNC(tanh)
-    "\n"
-  ;
-
   static void programDelete(gbe_program gbeProgram) {
     gbe::Program *program = (gbe::Program*)(gbeProgram);
     GBE_SAFE_DELETE(program);
@@ -535,38 +503,21 @@ namespace gbe {
 
 #ifdef GBE_COMPILER_AVAILABLE
   BVAR(OCL_OUTPUT_BUILD_LOG, false);
-  SVAR(OCL_PCH_PATH, PCH_OBJECT_DIR);
-  SVAR(OCL_PCM_PATH, PCM_OBJECT_DIR);
 
-  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) {
+  static bool buildModuleFromSource(const char* input, llvm::Module** out_module, llvm::LLVMContext* llvm_ctx,
+                                    std::vector<std::string>& options, size_t stringSize, char *err,
+                                    size_t *errSize) {
     // Arguments to pass to the clang frontend
     vector<const char *> args;
     bool bFastMath = false;
 
-    vector<std::string> useless; //hold substrings to avoid c_str free
-    size_t start = 0, end = 0;
-    /* FIXME
-       clang unsupport options:
-       -cl-denorms-are-zero, -cl-strict-aliasing
-       -cl-no-signed-zeros, -cl-fp32-correctly-rounded-divide-sqrt
-       all support options, refer to clang/include/clang/Driver/Options.inc
-    */
-    //Handle -cl-opt-disable in llvmToGen, skip here
-    const std::string unsupportedOptions("-cl-denorms-are-zero, -cl-strict-aliasing, -cl-opt-disable,"
-                                         "-cl-no-signed-zeros, -cl-fp32-correctly-rounded-divide-sqrt");
-    while (end != std::string::npos) {
-      end = options.find(' ', start);
-      std::string str = options.substr(start, end - start);
-      start = end + 1;
-      if(str.size() == 0)
-        continue;
-      if(str == "-cl-fast-relaxed-math") bFastMath = true;
-      if(unsupportedOptions.find(str) != std::string::npos)
-        continue;
-      useless.push_back(str);
-      args.push_back(str.c_str());
+    for (auto &s : options) {
+      args.push_back(s.c_str());
     }
+
+    args.push_back("-cl-kernel-arg-info");
+    args.push_back("-Dcl_khr_fp64");
+
     args.push_back("-mllvm");
     args.push_back("-inline-threshold=200000");
 #ifdef GEN7_SAMPLER_CLAMP_BORDER_WORKAROUND
@@ -590,28 +541,21 @@ namespace gbe {
 #endif /* LLVM_VERSION_MINOR <= 2 */
     args.push_back(input);
 
+    args.push_back("-ffp-contract=off");
+
     // The compiler invocation needs a DiagnosticsEngine so it can report problems
     std::string ErrorString;
     llvm::raw_string_ostream ErrorInfo(ErrorString);
     llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts = new clang::DiagnosticOptions();
     DiagOpts->ShowCarets = false;
     DiagOpts->ShowPresumedLoc = true;
-#if LLVM_VERSION_MINOR <= 1
-    args.push_back("-triple");
-    args.push_back("ptx32");
-
-    clang::TextDiagnosticPrinter *DiagClient =
-                             new clang::TextDiagnosticPrinter(ErrorInfo, *DiagOpts)
-    llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(new clang::DiagnosticIDs());
-    clang::DiagnosticsEngine Diags(DiagID, DiagClient);
-#else
-    args.push_back("-ffp-contract=off");
 
+  
     clang::TextDiagnosticPrinter *DiagClient =
                              new clang::TextDiagnosticPrinter(ErrorInfo, &*DiagOpts);
     llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(new clang::DiagnosticIDs());
     clang::DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
-#endif /* LLVM_VERSION_MINOR <= 1 */
+
     // Create the compiler invocation
     std::unique_ptr<clang::CompilerInvocation> CI(new clang::CompilerInvocation);
     clang::CompilerInvocation::CreateFromArgs(*CI,
@@ -623,11 +567,7 @@ namespace gbe {
     clang::CompilerInstance Clang;
     Clang.setInvocation(CI.release());
     // Get ready to report problems
-#if LLVM_VERSION_MINOR <= 2
-    Clang.createDiagnostics(args.size(), &args[0]);
-#else
     Clang.createDiagnostics(DiagClient, false);
-#endif /* LLVM_VERSION_MINOR <= 2 */
 
     Clang.getDiagnosticOpts().ShowCarets = false;
     if (!Clang.hasDiagnostics())
@@ -636,10 +576,7 @@ namespace gbe {
     // Set Language
     clang::LangOptions & lang_opts = Clang.getLangOpts();
     lang_opts.OpenCL = 1;
-
-    clang::PreprocessorOptions& prep_opt = Clang.getPreprocessorOpts();
-    prep_opt.DisablePCHValidation = 1;
-
+    
     //llvm flags need command line parsing to take effect
     if (!Clang.getFrontendOpts().LLVMArgs.empty()) {
       unsigned NumArgs = Clang.getFrontendOpts().LLVMArgs.size();
@@ -652,32 +589,17 @@ namespace gbe {
       llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args);
       delete [] Args;
     }
-
+  
     // Create an action and make the compiler instance carry it out
     std::unique_ptr<clang::CodeGenAction> Act(new clang::EmitLLVMOnlyAction(llvm_ctx));
-
-    std::string dirs = OCL_PCM_PATH;
-    std::string pcmFileName;
-    std::istringstream idirs(dirs);
-    bool findPcm = false;
-
-    while (getline(idirs, pcmFileName, ':')) {
-      if(access(pcmFileName.c_str(), R_OK) == 0) {
-        findPcm |= true;
-        break;
-      }
-    }
-
-    GBE_ASSERT(findPcm && "Could not find pre compiled module library.\n");
-
-    Clang.getCodeGenOpts().LinkBitcodeFile = pcmFileName;
+    
     auto retVal = Clang.ExecuteAction(*Act);
 
     if (err != NULL) {
       GBE_ASSERT(errSize != NULL);
       *errSize = ErrorString.copy(err, stringSize - 1, 0);
     }
-
+  
     if (err == NULL || OCL_OUTPUT_BUILD_LOG) {
       // flush the error messages to the errs() if there is no
       // error string buffer.
@@ -693,137 +615,70 @@ namespace gbe {
     return true;
   }
 
-  extern std::string ocl_stdlib_str;
 
-  BVAR(OCL_USE_PCH, true);
+  SVAR(OCL_HEADER_FILE_DIR, OCL_HEADER_DIR);
+
   static void processSourceAndOption(const char *source,
                                      const char *options,
                                      const char *temp_header_path,
-                                     std::string& clOpt,
+                                     std::vector<std::string>& clOpt,
                                      std::string& clName,
                                      int& optLevel)
   {
-    char clStr[] = "/tmp/XXXXXX.cl";
-    int clFd = mkstemps(clStr, 3);
-    clName = std::string(clStr);
-
-    FILE *clFile = fdopen(clFd, "w");
-    FATAL_IF(clFile == NULL, "Failed to open temporary file");
-
-    bool usePCH = OCL_USE_PCH;
-    bool findPCH = false;
-
-    /* Because our header file is so big, we want to avoid recompile the header from
-       scratch. We use the PCH support of Clang to save the huge compiling time.
-       We just use the most general build opt to build the PCH header file, so if
-       user pass new build options here, the PCH can not pass the Clang's compitable
-       validating. Clang will do three kinds of compatible check: Language Option,
-       Target Option and Preprocessing Option. Other kinds of options such as the
-       CodeGen options will not affect the AST result, so no need to check.
-
-       According to OpenCL 1.1's spec, the CL build options:
-       -D name=definition
-       If the definition is not used in our header, it is compitable
-
-       -cl-single-precision-constant
-       -cl-denorms-are-zero
-       -cl-std=
-       Language options, really affect.
-
-       -cl-opt-disable
-       -cl-mad-enable
-       -cl-no-signed-zeros
-       -cl-unsafe-math-optimizations
-       -cl-finite-math-only
-       -cl-fast-relaxed-math
-       CodeGen options, not affect
-
-       -Werror
-       -w
-       Our header should not block the compiling because of warning.
-
-       So we just disable the PCH validation of Clang and do the judgement by ourself. */
-
-    /* We always add -cl-kernel-arg-info to the options. This option just generate the arg
-       information for the backend, no other side effect and does not have performance issue. */
-    if (!options || !strstr(const_cast<char *>(options), "-cl-kernel-arg-info"))
-      clOpt += "-cl-kernel-arg-info ";
+    size_t start = 0, end = 0;
 
-    if (options) {
-      char *p;
-      /* FIXME: Though we can disable the pch valid check, and load pch successfully,
-         but these language opts and pre-defined macro will still generate the diag msg
-         to the diag engine of the Clang and cause the Clang to report error.
-         We filter them all here to avoid these. */
-      const char * incompatible_opts[] = {
-          "-cl-single-precision-constant",
-//        "-cl-denorms-are-zero",
-          "-cl-fast-relaxed-math",
-          "-cl-std=",
-      };
-      const char * incompatible_defs[] = {
-          "GET_FLOAT_WORD",
-          "__NV_CL_C_VERSION",
-          "GEN7_SAMPLER_CLAMP_BORDER_WORKAROUND"
-      };
-
-      for (unsigned int i = 0; i < sizeof(incompatible_opts)/sizeof(char *); i++ ) {
-        p = strstr(const_cast<char *>(options), incompatible_opts[i]);
-        if (p) {
-          usePCH = false;
-          break;
-        }
-      }
+    std::string hdirs = OCL_HEADER_FILE_DIR;
+    std::istringstream hidirs(hdirs);
+    std::string headerFilePath;
+    bool findOcl = false;
 
-      if (usePCH) {
-        for (unsigned int i = 0; i < sizeof(incompatible_defs)/sizeof(char *); i++ ) {
-          p = strstr(const_cast<char *>(options), incompatible_defs[i]);
-          if (p) {
-            usePCH = false;
-            break;
-          }
-        }
+    while (getline(hidirs, headerFilePath, ':')) {
+      std::string oclDotHName = headerFilePath + "/ocl.h";
+      if(access(oclDotHName.c_str(), R_OK) == 0) {
+        findOcl = true;
+        break;
       }
-
-      p = strstr(const_cast<char *>(options), "-cl-opt-disable");
-      if (p)
-        optLevel = 0;
-
-      clOpt += options;
     }
+    assert(findOcl);
+    std::string includePath  = "-I" + headerFilePath;
+    clOpt.push_back(includePath);
 
-    std::string dirs = OCL_PCH_PATH;
-    std::istringstream idirs(dirs);
-    std::string pchFileName;
-
-    while (getline(idirs, pchFileName, ':')) {
-      if(access(pchFileName.c_str(), R_OK) == 0) {
-        findPCH = true;
-        break;
+    if (options) {
+      char *str = (char *)malloc(sizeof(char) * (strlen(options) + 1));
+      memcpy(str, options, strlen(options) + 1);
+      std::string optionStr(str);
+      const std::string unsupportedOptions("-cl-denorms-are-zero, -cl-strict-aliasing, -cl-opt-disable,"
+                       "-cl-no-signed-zeros, -cl-fp32-correctly-rounded-divide-sqrt");
+      while (end != std::string::npos) {
+        end = optionStr.find(' ', start);
+        std::string str = optionStr.substr(start, end - start);
+        start = end + 1;
+        if(str.size() == 0)
+          continue;
+
+        if(unsupportedOptions.find(str) != std::string::npos)
+          continue;
+
+        clOpt.push_back(str);
       }
+      free(str);
     }
 
-    if (usePCH && findPCH) {
-      clOpt += " -include-pch ";
-      clOpt += pchFileName;
-      clOpt += " ";
-    } 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 += " ";
+      clOpt.push_back("-I");
+      clOpt.push_back(temp_header_path);
     }
 
-    if (!OCL_STRICT_CONFORMANCE) {
-        fwrite(ocl_mathfunc_fastpath_str.c_str(), strlen(ocl_mathfunc_fastpath_str.c_str()), 1, clFile);
-    }
+    char clStr[] = "/tmp/XXXXXX.cl";
+    int clFd = mkstemps(clStr, 3);
+    clName = std::string(clStr);
+
+    FILE *clFile = fdopen(clFd, "w");
+    FATAL_IF(clFile == NULL, "Failed to open temporary file");
 
-    // reset the file number in case we have inserted something into the kernel
-    std::string resetFileNum = "#line 1\n";
-    fwrite(resetFileNum.c_str(), strlen(resetFileNum.c_str()), 1, clFile);
+    clOpt.push_back("-include");
+    clOpt.push_back("ocl.h");
 
     // Write the source to the cl file
     fwrite(source, strlen(source), 1, clFile);
@@ -838,7 +693,7 @@ namespace gbe {
                                           size_t *errSize)
   {
     int optLevel = 1;
-    std::string clOpt;
+    std::vector<std::string> clOpt;
     std::string clName;
     processSourceAndOption(source, options, NULL, clOpt, clName, optLevel);
 
@@ -846,12 +701,11 @@ namespace gbe {
     // will delete the module and act in GenProgram::CleanLlvmResource().
     llvm::Module * out_module;
     llvm::LLVMContext* llvm_ctx = new llvm::LLVMContext;
-
     static std::mutex llvm_mutex;
     if (!llvm::llvm_is_multithreaded())
       llvm_mutex.lock();
 
-    if (buildModuleFromSource(clName.c_str(), &out_module, llvm_ctx, clOpt.c_str(),
+    if (buildModuleFromSource(clName.c_str(), &out_module, llvm_ctx, clOpt,
                               stringSize, err, errSize)) {
     // Now build the program from llvm
       size_t clangErrSize = 0;
@@ -890,7 +744,7 @@ namespace gbe {
                                           size_t *errSize)
   {
     int optLevel = 1;
-    std::string clOpt;
+    std::vector<std::string> clOpt;
     std::string clName;
     processSourceAndOption(source, options, temp_header_path, clOpt, clName, optLevel);
 
@@ -900,7 +754,7 @@ namespace gbe {
     //for some functions, so we use global context now, need switch to new context later.
     llvm::Module * out_module;
     llvm::LLVMContext* llvm_ctx = &llvm::getGlobalContext();
-    if (buildModuleFromSource(clName.c_str(), &out_module, llvm_ctx, clOpt.c_str(),
+    if (buildModuleFromSource(clName.c_str(), &out_module, llvm_ctx, clOpt,
                               stringSize, err, errSize)) {
     // Now build the program from llvm
       if (err != NULL) {
diff --git a/backend/src/libocl/CMakeLists.txt b/backend/src/libocl/CMakeLists.txt
new file mode 100644
index 0000000..d4e3a53
--- /dev/null
+++ b/backend/src/libocl/CMakeLists.txt
@@ -0,0 +1,209 @@
+PROJECT(LIBOCL)
+
+SET (OCL_HEADER_FILES ${LIBOCL_BINARY_DIR}/include/ocl_defines.h)
+SET (OCL_SOURCE_FILES "")
+
+ADD_CUSTOM_COMMAND(OUTPUT ${LIBOCL_BINARY_DIR}/include/ocl_defines.h
+    COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/include/
+    #   COMMAND echo "cat ${LIBOCL_SOURCE_DIR}/tmpl/ocl_defines.tmpl.h \\> ${LIBOCL_BINARY_DIR}/include/ocl_defines.h"
+    COMMAND cat ${LIBOCL_SOURCE_DIR}/tmpl/ocl_defines.tmpl.h > ${LIBOCL_BINARY_DIR}/include/ocl_defines.h
+    #   COMMAND echo "cat ${LIBOCL_SOURCE_DIR}/../ocl_common_defines.h \\>\\> ${LIBOCL_BINARY_DIR}/include/ocl_defines.h"
+    COMMAND cat ${LIBOCL_SOURCE_DIR}/../ocl_common_defines.h >> ${LIBOCL_BINARY_DIR}/include/ocl_defines.h
+    DEPENDS ${LIBOCL_SOURCE_DIR}/tmpl/ocl_defines.tmpl.h ${LIBOCL_SOURCE_DIR}/../ocl_common_defines.h
+    COMMENT "Generate the header: ${LIBOCL_BINARY_DIR}/include/ocl_defines.h"
+    )
+
+#other module just copy.
+MACRO(COPY_THE_HEADER _mod)
+    # Use the python script to generate the header files.
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/include/\\1.h" output_name ${_mod})
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/include/\\1.h" orgin_name ${_mod})
+    SET(OCL_HEADER_FILES ${OCL_HEADER_FILES} ${output_name})
+    IF(orgin_name STREQUAL output_name)
+    ELSE(orgin_name STREQUAL output_name)
+	ADD_CUSTOM_COMMAND(OUTPUT ${output_name}
+	    COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/include/
+	    #COMMAND echo "cp ${orgin_name} ${output_name}"
+	    COMMAND cp ${orgin_name} ${output_name}
+	    DEPENDS ${orgin_name}
+	    COMMENT "Copy the header: ${output_name}"
+	    )
+    ENDIF(orgin_name STREQUAL output_name)
+ENDMACRO(COPY_THE_HEADER)
+MACRO(COPY_THE_SOURCE _mod)
+    # Use the python script to generate the header files.
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/src/\\1.cl" output_name ${_mod})
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/src/\\1.cl" orgin_name ${_mod})
+    SET(OCL_SOURCE_FILES ${OCL_SOURCE_FILES} ${output_name})
+    IF(orgin_name STREQUAL output_name)
+    ELSE(orgin_name STREQUAL output_name)
+	ADD_CUSTOM_COMMAND(OUTPUT ${output_name}
+	    COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/src/
+	    #COMMAND echo "cp ${orgin_name} ${output_name}"
+	    COMMAND cp ${orgin_name} ${output_name}
+	    DEPENDS ${orgin_name}
+	    COMMENT "Copy the source: ${output_name}"
+	    )
+    ENDIF(orgin_name STREQUAL output_name)
+ENDMACRO(COPY_THE_SOURCE)
+
+SET (OCL_COPY_HEADERS ocl ocl_types ocl_float ocl_printf)
+FOREACH(M ${OCL_COPY_HEADERS})
+    COPY_THE_HEADER(${M})
+ENDFOREACH(M) 
+
+SET (OCL_COPY_MODULES ocl_workitem ocl_atom ocl_async ocl_sync ocl_misc ocl_vload ocl_geometric ocl_image)
+FOREACH(M ${OCL_COPY_MODULES})
+    COPY_THE_HEADER(${M})
+    COPY_THE_SOURCE(${M})
+ENDFOREACH(M) 
+
+
+MACRO(GENERATE_HEADER_PY _mod)
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/include/\\1.h" output_name ${_mod})
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/tmpl/\\1.tmpl.h" tmpl_name ${_mod})
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/script/\\1.def" def_name ${_mod})
+    SET(OCL_HEADER_FILES ${OCL_HEADER_FILES} ${output_name})
+    ADD_CUSTOM_COMMAND(OUTPUT ${output_name}
+	COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/include/
+	#COMMAND echo "cat ${tmpl_name} \\> ${output_name}"
+	COMMAND cat ${tmpl_name} > ${output_name} 
+	#COMMAND echo "${LIBOCL_SOURCE_DIR}/script/gen_vector.py ${def_name} ${output_name} 1"
+	COMMAND ${LIBOCL_SOURCE_DIR}/script/gen_vector.py ${def_name} ${output_name} 1
+	#COMMAND echo "echo \\#endif \\>\\> ${output_name}"
+	COMMAND echo "\\#endif" >> ${output_name}
+	DEPENDS ${tmpl_name}
+	COMMENT "Generate the header by python: ${output_name}"
+	)
+ENDMACRO(GENERATE_HEADER_PY)
+MACRO(GENERATE_SOURCE_PY _mod)
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/src/\\1.cl" output_name ${_mod})
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/tmpl/\\1.tmpl.cl" tmpl_name ${_mod})
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/script/\\1.def" def_name ${_mod})
+    SET(OCL_SOURCE_FILES ${OCL_SOURCE_FILES} ${output_name})
+    ADD_CUSTOM_COMMAND(OUTPUT ${output_name}
+	COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/src/
+	COMMAND cat ${tmpl_name} > ${output_name} 
+	COMMAND ${LIBOCL_SOURCE_DIR}/script/gen_vector.py ${def_name} ${output_name} 0
+	DEPENDS ${tmpl_name}
+	COMMENT "Generate the source by python: ${output_name}"
+	)
+ENDMACRO(GENERATE_SOURCE_PY)
+
+SET (OCL_PY_GENERATED_MODULES ocl_common ocl_relational ocl_integer ocl_math)
+FOREACH(M ${OCL_PY_GENERATED_MODULES})
+    GENERATE_HEADER_PY(${M})
+    GENERATE_SOURCE_PY(${M})
+ENDFOREACH(M) 
+
+
+MACRO(GENERATE_HEADER_BASH _mod)
+    # Use the python script to generate the header files.
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/include/\\1.h" output_name ${_mod})
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/script/\\1.sh" sh_name ${_mod})
+    SET(OCL_HEADER_FILES ${OCL_HEADER_FILES} ${output_name})
+    ADD_CUSTOM_COMMAND(OUTPUT ${output_name}
+	COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/include/
+	COMMAND ${sh_name} -p > ${output_name}
+	DEPENDS ${sh_name}
+	COMMENT "Generate the header by script: ${output_name}"
+	)
+ENDMACRO(GENERATE_HEADER_BASH)
+MACRO(GENERATE_SOURCE_BASH _mod)
+    # Use the python script to generate the header files.
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/src/\\1.cl" output_name ${_mod})
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/script/\\1.sh" def_name ${_mod})
+    SET(OCL_SOURCE_FILES ${OCL_SOURCE_FILES} ${output_name})
+    ADD_CUSTOM_COMMAND(OUTPUT ${output_name}
+	COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/src/
+	COMMAND ${sh_name} > ${output_name}
+	DEPENDS ${sh_name}
+	COMMENT "Generate the source by script: ${output_name}"
+	)
+ENDMACRO(GENERATE_SOURCE_BASH)
+
+SET (OCL_BASH_GENERATED_MODULES ocl_as ocl_convert)
+FOREACH(M ${OCL_BASH_GENERATED_MODULES})
+    GENERATE_HEADER_BASH(${M})
+    GENERATE_SOURCE_BASH(${M})
+ENDFOREACH(M) 
+
+
+SET (CLANG_OCL_FLAGS -fno-builtin -Dcl_khr_fp64 -ffp-contract=off -cl-kernel-arg-info -DGEN7_SAMPLER_CLAMP_BORDER_WORKAROUND)
+
+MACRO(ADD_CL_TO_BC_TARGET _file)
+    # CMake seems can not add pattern rule, use MACRO to replace.
+    STRING(REGEX REPLACE "${LIBOCL_BINARY_DIR}/src/\(o.*\)\\.cl" "${LIBOCL_BINARY_DIR}/lib/\\1.bc" output_name ${_file})
+    ADD_CUSTOM_COMMAND(OUTPUT ${output_name}
+	COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/lib/
+	#COMMAND echo ${LLVM_INSTALL_DIR}clang -cc1 ${CLANG_OCL_FLAGS} -I ${LIBOCL_BINARY_DIR}/include/ -emit-llvm-bc -triple spir -o ${output_name} -x cl ${_file}
+	COMMAND ${LLVM_INSTALL_DIR}clang -cc1 ${CLANG_OCL_FLAGS} -I ${LIBOCL_BINARY_DIR}/include/ -emit-llvm-bc -triple spir -o ${output_name} -x cl ${_file}
+	DEPENDS ${_file} ${OCL_HEADER_FILES}
+	COMMENT "Compiling ${_file}"
+	)
+ENDMACRO(ADD_CL_TO_BC_TARGET)
+
+
+FOREACH(f ${OCL_SOURCE_FILES})
+    ADD_CL_TO_BC_TARGET(${f})
+ENDFOREACH(f) 
+
+FOREACH(f ${OCL_SOURCE_FILES})
+    STRING(REGEX REPLACE "${LIBOCL_BINARY_DIR}/src/\(o.*\)\\.cl" "${LIBOCL_BINARY_DIR}/lib/\\1.bc" bc_name ${f})
+    SET(OCL_BC_FILES ${OCL_BC_FILES} ${bc_name})
+ENDFOREACH(f) 
+
+
+# handle the ll files
+MACRO(COPY_THE_LL _mod)
+    # Use the python script to generate the header files.
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/src/\\1.ll" output_name ${_mod})
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_SOURCE_DIR}/src/\\1.ll" orgin_name ${_mod})
+    IF(orgin_name STREQUAL output_name)
+    ELSE(orgin_name STREQUAL output_name)
+	ADD_CUSTOM_COMMAND(OUTPUT ${output_name}
+	    COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/src/
+	    #COMMAND echo "cp ${orgin_name} ${output_name}"
+	    COMMAND cp ${orgin_name} ${output_name}
+	    DEPENDS ${orgin_name}
+	    COMMENT "Copy the LL file: ${output_name}"
+	    )
+    ENDIF(orgin_name STREQUAL output_name)
+ENDMACRO(COPY_THE_LL)
+MACRO(ADD_LL_TO_BC_TARGET M)
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/lib/\\1.bc" output_name ${M})
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/src/\\1.ll" srcll_name ${M})
+    ADD_CUSTOM_COMMAND(OUTPUT ${output_name}
+	COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/lib/
+	#COMMAND echo ${LLVM_INSTALL_DIR}llvm-as -o ${output_name} ${srcll_name}
+	COMMAND ${LLVM_INSTALL_DIR}llvm-as -o ${output_name} ${srcll_name}
+	DEPENDS ${srcll_name}
+	COMMENT "Compiling ${srcll_name}"
+	)
+ENDMACRO(ADD_LL_TO_BC_TARGET)
+
+SET (OCL_LL_MODULES ocl_barrier ocl_memcpy ocl_memset)
+FOREACH(f ${OCL_LL_MODULES})
+    COPY_THE_LL(${f})
+    ADD_LL_TO_BC_TARGET(${f})
+    STRING(REGEX REPLACE "\(o.*\)" "${LIBOCL_BINARY_DIR}/lib/\\1.bc" bc_name ${f})
+    SET(OCL_BC_FILES ${OCL_BC_FILES} ${bc_name})
+ENDFOREACH(f) 
+
+
+ADD_CUSTOM_COMMAND(OUTPUT ${LIBOCL_BINARY_DIR}/lib/beignet.bc
+    COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/lib/
+    #COMMAND echo llvm-link -o ${LIBOCL_BINARY_DIR}/lib/beignet.bc ${OCL_BC_FILES}
+    COMMAND ${LLVM_INSTALL_DIR}llvm-link -o ${LIBOCL_BINARY_DIR}/lib/beignet.bc ${OCL_BC_FILES}
+    DEPENDS ${OCL_BC_FILES}
+    COMMENT "Generate the bitcode file: ${LIBOCL_BINARY_DIR}/lib/beignet.bc"
+    )
+
+ADD_CUSTOM_COMMAND(OUTPUT ${LIBOCL_BINARY_DIR}/lib/beignet.pch
+    COMMAND mkdir -p ${LIBOCL_BINARY_DIR}/lib/
+    COMMAND ${LLVM_INSTALL_DIR}clang -cc1 ${CLANG_OCL_FLAGS} -triple spir -I ${LIBOCL_BINARY_DIR}/include/ -emit-pch -x cl ${LIBOCL_BINARY_DIR}/include/ocl.h -o ${LIBOCL_BINARY_DIR}/lib/beignet.pch
+    DEPENDS ${OCL_HEADER_FILES}
+    COMMENT "Generate the pch file: ${LIBOCL_BINARY_DIR}/lib/beignet.pch"
+    )
+
+add_custom_target(beignet_bitcode ALL DEPENDS ${LIBOCL_BINARY_DIR}/lib/beignet.bc ${LIBOCL_BINARY_DIR}/lib/beignet.pch)
diff --git a/backend/src/libocl/include/ocl.h b/backend/src/libocl/include/ocl.h
new file mode 100644
index 0000000..a7d03e6
--- /dev/null
+++ b/backend/src/libocl/include/ocl.h
@@ -0,0 +1,23 @@
+#ifndef __OCL_H__
+#define __OCL_H__
+
+#include "ocl_defines.h"
+#include "ocl_types.h"
+#include "ocl_as.h"
+#include "ocl_async.h"
+#include "ocl_atom.h"
+#include "ocl_common.h"
+#include "ocl_convert.h"
+#include "ocl_float.h"
+#include "ocl_geometric.h"
+#include "ocl_image.h"
+#include "ocl_integer.h"
+#include "ocl_math.h"
+#include "ocl_misc.h"
+#include "ocl_printf.h"
+#include "ocl_relational.h"
+#include "ocl_sync.h"
+#include "ocl_vload.h"
+#include "ocl_workitem.h"
+
+#endif
diff --git a/backend/src/llvm/llvm_to_gen.cpp b/backend/src/llvm/llvm_to_gen.cpp
index beb36c0..8e49cbb 100644
--- a/backend/src/llvm/llvm_to_gen.cpp
+++ b/backend/src/llvm/llvm_to_gen.cpp
@@ -72,10 +72,8 @@
 
 namespace gbe
 {
-  BVAR(OCL_OUTPUT_LLVM, false);
   BVAR(OCL_OUTPUT_CFG, false);
   BVAR(OCL_OUTPUT_CFG_ONLY, false);
-  BVAR(OCL_OUTPUT_LLVM_BEFORE_EXTRA_PASS, false);
   using namespace llvm;
 
   void runFuntionPass(Module &mod, TargetLibraryInfo *libraryInfo)
@@ -177,29 +175,68 @@ namespace gbe
     MPM.run(mod);
   }
 
+
+#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5
+#define OUTPUT_BITCODE(STAGE, MOD)  do {         \
+   llvm::PassManager passes__;                   \
+   if (OCL_OUTPUT_LLVM_##STAGE) {                \
+     passes__.add(createPrintModulePass(*o));    \
+     passes__.run(MOD);                          \
+   }                                             \
+ }while(0)
+#else
+#define OUTPUT_BITCODE(STAGE, MOD)  do {         \
+   llvm::PassManager passes__;                   \
+   if (OCL_OUTPUT_LLVM_##STAGE) {                \
+     passes__.add(createPrintModulePass(&*o));   \
+     passes__.run(MOD);                          \
+   }                                             \
+ }while(0)
+#endif
+
+  BVAR(OCL_OUTPUT_LLVM_BEFORE_LINK, false);
+  BVAR(OCL_OUTPUT_LLVM_AFTER_LINK, false);
+  BVAR(OCL_OUTPUT_LLVM_AFTER_GEN, false);
+
   bool llvmToGen(ir::Unit &unit, const char *fileName,const void* module, int optLevel)
   {
     std::string errInfo;
     std::unique_ptr<llvm::raw_fd_ostream> o = NULL;
-    if (OCL_OUTPUT_LLVM_BEFORE_EXTRA_PASS || OCL_OUTPUT_LLVM)
+    if (OCL_OUTPUT_LLVM_BEFORE_LINK || OCL_OUTPUT_LLVM_AFTER_LINK || OCL_OUTPUT_LLVM_AFTER_GEN)
       o = std::unique_ptr<llvm::raw_fd_ostream>(new llvm::raw_fd_ostream(fileno(stdout), false));
 
     // Get the module from its file
     llvm::SMDiagnostic Err;
-    std::unique_ptr<Module> M;
 
-    if(fileName){
-      // only when module is null, Get the global LLVM context
+    Module* cl_mod = NULL;
+    if (module) {
+      cl_mod = reinterpret_cast<Module*>(const_cast<void*>(module));
+    } else if (fileName){
       llvm::LLVMContext& c = llvm::getGlobalContext();
-      M.reset(ParseIRFile(fileName, Err, c));
-      if (M.get() == 0) return false;
+      cl_mod = ParseIRFile(fileName, Err, c);
     }
-    Module &mod = (module!=NULL)?*(llvm::Module*)module:*M.get();
+
+    if (!cl_mod) return false;
+
+    OUTPUT_BITCODE(BEFORE_LINK, (*cl_mod));
+
+    std::unique_ptr<Module> M;
+
+    /* Before do any thing, we first filter in all CL functions in bitcode. */ 
+    M.reset(runBitCodeLinker(cl_mod));
+    if (!module)
+      delete cl_mod;
+    if (M.get() == 0)
+      return false;
+
+    Module &mod = *M.get();
 
     Triple TargetTriple(mod.getTargetTriple());
     TargetLibraryInfo *libraryInfo = new TargetLibraryInfo(TargetTriple);
     libraryInfo->disableAllFunctions();
 
+    OUTPUT_BITCODE(AFTER_LINK, mod);
+
     runFuntionPass(mod, libraryInfo);
     runModulePass(mod, libraryInfo, optLevel);
 
@@ -210,12 +247,6 @@ namespace gbe
     passes.add(new DataLayout(&mod));
 #endif
     // Print the code before further optimizations
-    if (OCL_OUTPUT_LLVM_BEFORE_EXTRA_PASS)
-#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5
-      passes.add(createPrintModulePass(*o));
-#else
-      passes.add(createPrintModulePass(&*o));
-#endif
     passes.add(createIntrinsicLoweringPass());
     passes.add(createFunctionInliningPass(200000));
     passes.add(createScalarReplAggregatesPass()); // Break up allocas
@@ -237,15 +268,10 @@ namespace gbe
     if(OCL_OUTPUT_CFG_ONLY)
       passes.add(createCFGOnlyPrinterPass());
     passes.add(createGenPass(unit));
+    passes.run(mod);
 
     // Print the code extra optimization passes
-    if (OCL_OUTPUT_LLVM)
-#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5
-      passes.add(createPrintModulePass(*o));
-#else
-      passes.add(createPrintModulePass(&*o));
-#endif
-    passes.run(mod);
+    OUTPUT_BITCODE(AFTER_GEN, mod);
 
     const ir::Unit::FunctionSet& fs = unit.getFunctionSet();
     ir::Unit::FunctionSet::const_iterator iter = fs.begin();
diff --git a/utests/setenv.sh.in b/utests/setenv.sh.in
index b0f575f..ac06b10 100644
--- a/utests/setenv.sh.in
+++ b/utests/setenv.sh.in
@@ -1,7 +1,8 @@
 #!/bin/sh
 #
-export OCL_PCM_PATH=@LOCAL_PCM_OBJECT_DIR@
-export OCL_PCH_PATH=@LOCAL_PCH_OBJECT_DIR@
+export OCL_BITCODE_LIB_PATH=@LOCAL_OCL_BITCODE_BIN@
+export OCL_HEADER_FILE_DIR=@LOCAL_OCL_HEADER_DIR@
+export OCL_PCH_PATH=@LOCAL_OCL_PCH_OBJECT@
 export OCL_KERNEL_PATH=@CMAKE_CURRENT_SOURCE_DIR@/../kernels
 export OCL_GBE_PATH=@LOCAL_GBE_OBJECT_DIR@
 export OCL_INTERP_PATH=@LOCAL_INTERP_OBJECT_DIR@
-- 
1.7.9.5



More information about the Beignet mailing list