Add the PCH support when building the source.
authorJunyan He <junyan.he@linux.intel.com>
Wed, 17 Jul 2013 08:38:41 +0000 (16:38 +0800)
committerZhigang Gong <zhigang.gong@linux.intel.com>
Wed, 24 Jul 2013 03:51:11 +0000 (11:51 +0800)
Because the utest grows bigger, the runtime compiling time seems a big
problem to cause the utest_run very slow.  Most of the time wastes on
re-parsing the big header file such as ocl_stdlib.h.
Using the PCH feature of Clang can shorten the compiling time a lot.
Because we build the pch file at building time, but some source
has runtime building option for LLVM, and these options may cause
the compitable problem between the pch header and the CL source code.
We fallback to build the whole header and source when we find the
options are not compitable.

v2 from Zhigang:
Based on junyan's patch, I made the following changes and fixing:
1. Change the way to find correct pch file, now we just define
two possible locations of the header file at build time. Don't
need to query the linker to get correct pch file directory.

2. Use python to generate a big blob of all ocl standard headers
into one file.

3. Fix those broken dependencies in the CMakeLists.txt, now it
works fine.

Signed-off-by: Junyan He <junyan.he@linux.intel.com>
Signed-off-by: Zhigang Gong <zhigang.gong@linux.intel.com>
Reviewed-by: Simon Richter <Simon.Richter@hogyros.de>
backend/CMakeLists.txt
backend/src/CMakeLists.txt
backend/src/GBEConfig.h.in
backend/src/backend/program.cpp
backend/src/ocl_stdlib.tmpl.h
backend/src/update_blob_ocl_header.py

index 5498ff0..8622f3e 100644 (file)
@@ -1,12 +1,6 @@
 project (GBE)
 set (LIBGBE_VERSION_MAJOR 0)
-set (LIBGBE_VERSION_MINOR 1)
-
-configure_file (
-  "src/GBEConfig.h.in"
-  "src/GBEConfig.h"
-)
-
+set (LIBGBE_VERSION_MINOR 2)
 cmake_minimum_required (VERSION 2.6.0)
 
 set (GBE_CMAKE_DIR "${GBE_SOURCE_DIR}/cmake")
@@ -97,7 +91,7 @@ elseif (COMPILER STREQUAL "ICC")
   set (CCMAKE_CXX_FLAGS_MINSIZEREL "-Os -DGBE_DEBUG=0")
   set (CMAKE_EXE_LINKER_FLAGS "")
 endif ()
-
+include_directories (${CMAKE_CURRENT_BINARY_DIR})
 ##############################################################
 # Project source code
 ##############################################################
index a7a9f0f..b7b47ae 100644 (file)
@@ -1,37 +1,27 @@
-#add_subdirectory(llvm)
-
-macro (stringify TO_STRINGIFY_PATH TO_STRINGIFY_FILES)
-foreach (to_stringify_file ${TO_STRINGIFY_FILES})
-  set (input_file ${TO_STRINGIFY_PATH}/${to_stringify_file}.h)
-  set (output_file ${TO_STRINGIFY_PATH}/${to_stringify_file}_str.cpp)
-  set (string_header "\\\"string\\\"")
-  add_custom_command(
-    OUTPUT ${output_file}
-    COMMAND rm -rf ${output_file}
-    COMMAND echo "\\\#include ${string_header}" >> ${output_file}
-    COMMAND echo "namespace gbe {" >> ${output_file}
-    COMMAND echo "std::string ${to_stringify_file}_str = " >> ${output_file}
-    # Yeah!!! welcome to back slash hell
-    COMMAND cat ${input_file} |sed 's/\\\\/\\\\\\\\/g' | sed 's/\\\"/\\\\\\\"/g' | awk '{ printf \(\"\\"%s\\\\n\\"\\n\", $$0\) }' >> ${output_file}
-    COMMAND echo "\;" >> ${output_file}
-    COMMAND echo "}" >> ${output_file}
-    COMMAND echo "" >> ${output_file}
-    DEPENDS ${input_file})
-endforeach (to_stringify_file)
-endmacro (stringify)
-
-set (TO_STRINGIFY_FILES ocl_stdlib ocl_common_defines)
-stringify ("${GBE_SOURCE_DIR}/src/" "${TO_STRINGIFY_FILES}")
-
 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_blob_file ${GBE_SOURCE_DIR}/src/ocl_stdlib.h)
+set (ocl_blob_file ${CMAKE_CURRENT_BINARY_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_stdlib.h")
 
 add_custom_command(
@@ -42,7 +32,31 @@ add_custom_command(
 add_custom_command(
   OUTPUT ${ocl_blob_file}
   COMMAND ${ocl_gen_blob_cmd} ${ocl_stdlib_tmpl_file} ${ocl_blob_file}
-  DEPENDS ${ocl_gen_blob_cmd} ${ocl_vector_file} ${ocl_as_file} ${ocl_convert_file})
+  DEPENDS ${ocl_gen_blob_cmd} ${ocl_stdlib_tmpl_file} ${ocl_vector_file} ${ocl_as_file} ${ocl_convert_file})
+
+
+set (pch_object ${ocl_blob_file}.pch)
+# generate pch object
+if (LLVM_VERSION_NODOT VERSION_GREATER 32)
+    set (clang_cmd -cc1 -x cl -triple spir -ffp-contract=off -emit-pch)
+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 -emit-pch)
+    else (LLVM_VERSION_NODOT VERSION_GREATER 31)
+        set (clang_cmd -cc1 -x cl -triple ptx32 -emit-pch)
+    endif (LLVM_VERSION_NODOT VERSION_GREATER 31)
+endif (LLVM_VERSION_NODOT VERSION_GREATER 32)
+set (clang_cmd ${clang_cmd} -fno-builtin)
+
+add_custom_command(
+     OUTPUT ${pch_object}
+     COMMAND rm -f ${pch_object}
+     COMMAND clang ${clang_cmd} ${ocl_blob_file} -o ${pch_object}
+     DEPENDS ${ocl_blob_file}
+     )
+
+add_custom_target(pch_object
+                  DEPENDS ${pch_object})
 
 if (GBE_USE_BLOB)
   set (GBE_SRC
@@ -52,9 +66,6 @@ else (GBE_USE_BLOB)
   set (GBE_SRC
     ocl_stdlib.h
     ocl_stdlib_str.cpp  # this file is auto-generated.
-    ocl_stdlib_str.cpp
-    ocl_common_defines.h
-    ocl_common_defines_str.cpp # this file is auto-generated.
     sys/vector.hpp
     sys/hash_map.hpp
     sys/map.hpp
@@ -132,6 +143,7 @@ link_directories (${LLVM_LIBRARY_DIRS})
 include_directories(${LLVM_INCLUDE_DIRS})
 add_library (gbe SHARED ${GBE_SRC})
 
+ADD_DEPENDENCIES (gbe pch_object)
 target_link_libraries(
                       gbe
                       ${DRM_INTEL_LIBRARY}
@@ -143,5 +155,11 @@ target_link_libraries(
                       ${CMAKE_DL_LIBS})
 
 install (TARGETS gbe LIBRARY DESTINATION lib)
+install (FILES ${pch_object} DESTINATION lib)
 install (FILES backend/program.h DESTINATION include/gen)
 
+set (PCH_OBJECT_DIR "${pch_object};${CMAKE_INSTALL_PREFIX}/lib/ocl_stdlib.h.pch")
+configure_file (
+  "GBEConfig.h.in"
+  "GBEConfig.h"
+)
index 369b184..74bef3f 100644 (file)
@@ -1,3 +1,4 @@
 // 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@"
index bac1ce9..20bdcec 100644 (file)
@@ -35,6 +35,8 @@
 #include <cstring>
 #include <algorithm>
 #include <fstream>
+#include <dlfcn.h>
+#include <sstream>
 
 /* Not defined for LLVM 3.0 */
 #if !defined(LLVM_VERSION_MAJOR)
@@ -66,6 +68,7 @@
 #endif  /* LLVM_VERSION_MINOR <= 2 */
 #include <llvm/Bitcode/ReaderWriter.h>
 #include <llvm/Support/raw_ostream.h>
+#include "src/GBEConfig.h"
 
 namespace gbe {
 
@@ -224,7 +227,8 @@ namespace gbe {
   }
 
   extern std::string ocl_stdlib_str;
-  extern std::string ocl_common_defines_str;
+
+  BVAR(OCL_USE_PCH, true);
   static gbe_program programNewFromSource(const char *source,
                                           size_t stringSize,
                                           const char *options,
@@ -234,16 +238,45 @@ namespace gbe {
     char clStr[L_tmpnam+1], llStr[L_tmpnam+1];
     const std::string clName = std::string(tmpnam_r(clStr)) + ".cl"; /* unsafe! */
     const std::string llName = std::string(tmpnam_r(llStr)) + ".ll"; /* unsafe! */
+    std::string pchHeaderName;
+    std::string clOpt;
 
-    // Write the source to the cl file
     FILE *clFile = fopen(clName.c_str(), "w");
     FATAL_IF(clFile == NULL, "Failed to open temporary file");
-    fwrite(ocl_common_defines_str.c_str(), strlen(ocl_common_defines_str.c_str()), 1, clFile);
-    fwrite(ocl_stdlib_str.c_str(), strlen(ocl_stdlib_str.c_str()), 1, clFile);
+
+    bool usePCH = false;
+
+    if(options)
+      clOpt += options;
+
+    if (options || !OCL_USE_PCH) {
+      /* Some building option may cause the prebuild pch header file
+         not compatible with the XXX.cl source. We need rebuild all here.*/
+      usePCH = false;
+    } else {
+      std::string dirs = PCH_OBJECT_DIR;
+      std::istringstream idirs(dirs);
+
+      while (getline(idirs, pchHeaderName, ';')) {
+        FILE *pchFile = fopen(pchHeaderName.c_str(), "r");
+        if (pchFile != NULL) {
+          usePCH = true;
+          fclose(pchFile);
+          break;
+        }
+      }
+    }
+    if (usePCH) {
+      clOpt += " -include-pch ";
+      clOpt += pchHeaderName;
+      clOpt += " ";
+    } else
+      fwrite(ocl_stdlib_str.c_str(), strlen(ocl_stdlib_str.c_str()), 1, clFile);
+    // Write the source to the cl file
     fwrite(source, strlen(source), 1, clFile);
     fclose(clFile);
 
-    buildModuleFromSource(clName.c_str(), llName.c_str(), options ? options : "");
+    buildModuleFromSource(clName.c_str(), llName.c_str(), clOpt.c_str());
     remove(clName.c_str());
 
     // Now build the program from llvm
index fa4794f..387e6fb 100644 (file)
@@ -1326,6 +1326,9 @@ int __gen_ocl_force_simd16(void);
 
 #define NULL ((void*)0)
 
+// ##BEGIN_COMMON_DEFINES##
+// ##END_COMMON_DEFINES##
+
 /////////////////////////////////////////////////////////////////////////////
 // Image access functions
 /////////////////////////////////////////////////////////////////////////////
index 2aecfe7..197f16c 100755 (executable)
@@ -22,7 +22,7 @@ import os
 
 if len(sys.argv) != 3:
     print "Invalid argument {}".format(sys.argv)
-    print "use {} spec_file_name output_file_name".format(sys.argv[0])
+    print "use {} tmpl_file_name output_file_name".format(sys.argv[0])
     raise
 
 def safeUnlink(filename):
@@ -31,7 +31,7 @@ def safeUnlink(filename):
     except OSError:
         pass
 
-
+header_segments = [ "vector", "as", "convert", "common_defines"]
 blobFileName = sys.argv[2]
 blobTempName = sys.argv[2] + '.tmp'
 safeUnlink(blobFileName)
@@ -40,7 +40,6 @@ blob = open(sys.argv[2] + '.tmp', 'w')
 path = os.path.dirname(sys.argv[1])
 if path == '':
     path = '.'
-header_segments = [ "vector", "as", "convert"]
 
 matched_header = ""
 for tline in tmplFile: