[Beignet] [PATCH 16/18] Enable the libocl to replace the huge PCH header.

junyan.he at inbox.com junyan.he at inbox.com
Tue Aug 12 00:32:57 PDT 2014


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

Move out the workitesm function into the ocl lib.
The llvm ir print out also be 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/src/CMakeLists.txt              | 138 +++---------------
 backend/src/backend/program.cpp         | 239 +++++---------------------------
 backend/src/libocl/include/ocl.h        |  14 ++
 backend/src/libocl/include/ocl_printf.h |  15 ++
 backend/src/libocl/lib/beignet.bc       |   0
 backend/src/llvm/llvm_gen_backend.hpp   |   3 +
 backend/src/llvm/llvm_to_gen.cpp        |  71 +++++++---
 7 files changed, 130 insertions(+), 350 deletions(-)
 create mode 100644 backend/src/libocl/include/ocl_printf.h
 delete mode 100644 backend/src/libocl/lib/beignet.bc

diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt
index 262815c..d214c1f 100644
--- a/backend/src/CMakeLists.txt
+++ b/backend/src/CMakeLists.txt
@@ -1,67 +1,22 @@
-set (OCL_BITCODE_BIN "${BEIGNET_INSTALL_DIR}beignet.bc")
-set (OCL_BITCODE_DIR "${BEIGNET_INSTALL_DIR}")
-set (OCL_HEADER_DIR "${CMAKE_INSTALL_PREFIX}/include/CL/ocl/")
-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 (OCL_BITCODE_BIN "${BEIGNET_INSTALL_DIR}beignet.bc:${CMAKE_CURRENT_SOURCE_DIR}/libocl/lib/beignet.bc")
+set (OCL_BITCODE_DIR "${BEIGNET_INSTALL_DIR}:${CMAKE_CURRENT_SOURCE_DIR}/libocl/lib/")
+set (OCL_HEADER_DIR "${CMAKE_INSTALL_PREFIX}/include/CL/ocl/:${CMAKE_CURRENT_SOURCE_DIR}/libocl/include/")
+set (GBE_OBJECT_DIR "${BEIGNET_INSTALL_DIR}/libgbe.so")
+set (INTERP_OBJECT_DIR "${BEIGNET_INSTALL_DIR}/libgbeinterp.so")
 
-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 (LOCAL_GBE_OBJECT_DIR "${CMAKE_CURRENT_BINARY_DIR}/libgbe.so" PARENT_SCOPE)
+set (LOCAL_OCL_BITCODE_BIN "${CMAKE_CURRENT_SOURCE_DIR}/libocl/lib/beignet.bc" PARENT_SCOPE)
+set (LOCAL_OCL_HEADER_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libocl/include/" PARENT_SCOPE)
+set (LOCAL_INTERP_OBJECT_DIR "${CMAKE_CURRENT_BINARY_DIR}/libgbeinterp.so" PARENT_SCOPE)
 
-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}
-     )
+configure_file (
+    "GBEConfig.h.in"
+    "GBEConfig.h"
+)
+configure_file (
+    "libocl/Makefile.in"
+    "libocl/Makefile"
+)
 
 add_custom_command (
     OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/libocl/lib/beignet.bc
@@ -71,36 +26,9 @@ add_custom_command (
 add_custom_target(beignet_bitcode ALL
     DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/libocl/lib/beignet.bc
     )
-add_custom_target(pch_object
-                  DEPENDS ${pch_object})
 
-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)
-
-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
@@ -188,19 +116,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}
@@ -231,29 +153,5 @@ 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})
 install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/libocl/lib/beignet.bc DESTINATION ${OCL_BITCODE_DIR})
 install (DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/libocl/include/ DESTINATION ${OCL_HEADER_DIR} PATTERN *.h)
-
-# 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"
-)
-configure_file (
-    "libocl/Makefile.in"
-    "libocl/Makefile"
-    )
diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp
index 50396c8..b4bb6e1 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,32 @@ 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);
+  SVAR(OCL_HEADER_FILE_DIR, OCL_HEADER_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) {
     // 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());
+    std::string hdirs = OCL_HEADER_FILE_DIR;
+    std::istringstream hidirs(hdirs);
+    std::string headerFilePath;
+    bool findOcl = false;
+
+    while (getline(hidirs, headerFilePath, ':')) {
+      std::string oclDotHName = headerFilePath + "/ocl.h";
+      if(access(oclDotHName.c_str(), R_OK) == 0) {
+        findOcl = true;
+        break;
+      }
     }
+    assert(findOcl);
+    std::string includePath  = "-I" + headerFilePath;
+    args.push_back(includePath.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 +552,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 +578,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 +587,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 +600,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,9 +626,6 @@ namespace gbe {
     return true;
   }
 
-  extern std::string ocl_stdlib_str;
-
-  BVAR(OCL_USE_PCH, true);
   static void processSourceAndOption(const char *source,
                                      const char *options,
                                      const char *temp_header_path,
@@ -710,118 +640,11 @@ namespace gbe {
     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 ";
-
-    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;
-        }
-      }
-
-      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;
-          }
-        }
-      }
-
-      p = strstr(const_cast<char *>(options), "-cl-opt-disable");
-      if (p)
-        optLevel = 0;
-
-      clOpt += options;
-    }
-
-    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 (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 += " ";
-    }
-
-    if (!OCL_STRICT_CONFORMANCE) {
-        fwrite(ocl_mathfunc_fastpath_str.c_str(), strlen(ocl_mathfunc_fastpath_str.c_str()), 1, clFile);
-    }
+    //Add the include header file
+    std::string includeOclStr = "#include \"ocl.h\"\n";
+    fwrite(includeOclStr.c_str(), strlen(includeOclStr.c_str()), 1, clFile);
 
-    // reset the file number in case we have inserted something into the kernel
+    // Ensure the file number begin with line 1
     std::string resetFileNum = "#line 1\n";
     fwrite(resetFileNum.c_str(), strlen(resetFileNum.c_str()), 1, clFile);
 
diff --git a/backend/src/libocl/include/ocl.h b/backend/src/libocl/include/ocl.h
index 5e150bf..a7d03e6 100644
--- a/backend/src/libocl/include/ocl.h
+++ b/backend/src/libocl/include/ocl.h
@@ -4,6 +4,20 @@
 #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/libocl/include/ocl_printf.h b/backend/src/libocl/include/ocl_printf.h
new file mode 100644
index 0000000..6089640
--- /dev/null
+++ b/backend/src/libocl/include/ocl_printf.h
@@ -0,0 +1,15 @@
+#ifndef __OCL_PRINTF_H__
+#define __OCL_PRINTF_H__ 
+
+#include "ocl_types.h"
+
+/* The printf function. */
+/* From LLVM 3.4, c string are all in constant address space */
+#if 100*__clang_major__ + __clang_minor__ < 304
+int __gen_ocl_printf_stub(const char * format, ...);
+#else
+int __gen_ocl_printf_stub(constant char * format, ...);
+#endif
+#define printf __gen_ocl_printf_stub
+
+#endif
diff --git a/backend/src/libocl/lib/beignet.bc b/backend/src/libocl/lib/beignet.bc
deleted file mode 100644
index e69de29..0000000
diff --git a/backend/src/llvm/llvm_gen_backend.hpp b/backend/src/llvm/llvm_gen_backend.hpp
index cc5cdad..ee44a8a 100644
--- a/backend/src/llvm/llvm_gen_backend.hpp
+++ b/backend/src/llvm/llvm_gen_backend.hpp
@@ -98,6 +98,9 @@ namespace gbe
   /*! Passer the printf function call. */
   llvm::FunctionPass* createPrintfParserPass();
 
+  /*! Add all the function call of ocl to our bitcode. */
+  llvm::Module* runBitCodeLinker(llvm::Module *mod);
+
   void* getPrintfInfo(llvm::CallInst* inst);
 } /* namespace gbe */
 
diff --git a/backend/src/llvm/llvm_to_gen.cpp b/backend/src/llvm/llvm_to_gen.cpp
index 3527491..1d00533 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,28 +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::auto_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::auto_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);
 
@@ -209,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
@@ -236,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();
-- 
1.8.3.2



More information about the Beignet mailing list