[Beignet] [PATCH 10/19] OCL20: enable -cl-std=CL2.0.

Yang Rong rong.r.yang at intel.com
Mon Nov 28 11:32:36 UTC 2016


When build from source, get the OpenCL version from the option. Use
spir64 triple if it is OpenCL 2.0.
Get the OpenCL version for llvm module's meta. If OpenCL version is
2.0, set the unit's point size to 64 bits before using
unit.getPointerSize().

Signed-off-by: Yang Rong <rong.r.yang at intel.com>
---
 backend/src/backend/context.cpp        |  2 +-
 backend/src/backend/gen_program.cpp    |  6 ++--
 backend/src/backend/program.cpp        | 56 +++++++++++++++++++++++++---------
 backend/src/ir/unit.hpp                |  3 +-
 backend/src/llvm/llvm_bitcode_link.cpp | 19 +++++++++---
 backend/src/llvm/llvm_gen_backend.cpp  |  3 ++
 backend/src/llvm/llvm_gen_backend.hpp  |  4 ++-
 backend/src/llvm/llvm_passes.cpp       | 25 +++++++++++++--
 backend/src/llvm/llvm_to_gen.cpp       |  5 +--
 9 files changed, 94 insertions(+), 29 deletions(-)

diff --git a/backend/src/backend/context.cpp b/backend/src/backend/context.cpp
index 1426e0c..8174954 100644
--- a/backend/src/backend/context.cpp
+++ b/backend/src/backend/context.cpp
@@ -345,7 +345,7 @@ namespace gbe
   Context::Context(const ir::Unit &unit, const std::string &name) :
     unit(unit), fn(*unit.getFunction(name)), name(name), liveness(NULL), dag(NULL), useDWLabel(false)
   {
-    GBE_ASSERT(unit.getPointerSize() == ir::POINTER_32_BITS);
+    GBE_ASSERT(unit.getPointerSize() == ir::POINTER_32_BITS || unit.getPointerSize() == ir::POINTER_64_BITS);
     this->liveness = GBE_NEW(ir::Liveness, const_cast<ir::Function&>(fn), true);
     this->dag = GBE_NEW(ir::FunctionDAG, *this->liveness);
     // r0 (GEN_REG_SIZE) is always set by the HW and used at the end by EOT
diff --git a/backend/src/backend/gen_program.cpp b/backend/src/backend/gen_program.cpp
index ebba7d4..1872b01 100644
--- a/backend/src/backend/gen_program.cpp
+++ b/backend/src/backend/gen_program.cpp
@@ -352,8 +352,10 @@ namespace gbe {
 #endif
     // if load 32 bit spir binary, the triple should be spir-unknown-unknown.
     llvm::Triple triple(module->getTargetTriple());
-    if(triple.getArchName() == "spir" && triple.getVendorName() == "unknown" && triple.getOSName() == "unknown"){
+    if (triple.getArchName() == "spir" && triple.getVendorName() == "unknown" && triple.getOSName() == "unknown"){
       module->setTargetTriple("spir");
+    } else if (triple.getArchName() == "spir64" && triple.getVendorName() == "unknown" && triple.getOSName() == "unknown"){
+      module->setTargetTriple("spir64");
     }
     releaseLLVMContextLock();
     if(module == NULL){
@@ -525,7 +527,7 @@ namespace gbe {
                                       size_t stringSize,
                                       char *err,
                                       size_t *errSize,
-                                      const char *          options)
+                                      const char * options)
   {
 #ifdef GBE_COMPILER_AVAILABLE
     using namespace gbe;
diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp
index c68d604..413f397 100644
--- a/backend/src/backend/program.cpp
+++ b/backend/src/backend/program.cpp
@@ -122,7 +122,10 @@ namespace gbe {
   IVAR(OCL_PROFILING_LOG, 0, 0, 1); // Int for different profiling types.
   BVAR(OCL_OUTPUT_BUILD_LOG, false);
 
-  bool Program::buildFromLLVMFile(const char *fileName, const void* module, 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();
     llvm::Module * cloned_module = NULL;
     bool ret = false;
@@ -649,7 +652,7 @@ namespace gbe {
 #ifdef GBE_COMPILER_AVAILABLE
   static bool buildModuleFromSource(const char *source, llvm::Module** out_module, llvm::LLVMContext* llvm_ctx,
                                     std::string dumpLLVMFileName, std::string dumpSPIRBinaryName, std::vector<std::string>& options, size_t stringSize, char *err,
-                                    size_t *errSize) {
+                                    size_t *errSize, uint32_t oclVersion) {
     // Arguments to pass to the clang frontend
     vector<const char *> args;
     bool bFastMath = false;
@@ -687,7 +690,10 @@ namespace gbe {
     args.push_back("-x");
     args.push_back("cl");
     args.push_back("-triple");
-    args.push_back("spir");
+    if (oclVersion >= 200)
+      args.push_back("spir64");
+    else
+      args.push_back("spir");
 #endif /* LLVM_VERSION_MINOR <= 2 */
     args.push_back("stringInput.cl");
     args.push_back("-ffp-contract=on");
@@ -829,6 +835,7 @@ namespace gbe {
 
 
   SVAR(OCL_PCH_PATH, OCL_PCH_OBJECT);
+  SVAR(OCL_PCH_20_PATH, OCL_PCH_OBJECT_20);
   SVAR(OCL_HEADER_FILE_DIR, OCL_HEADER_DIR);
   BVAR(OCL_OUTPUT_KERNEL_SOURCE, false);
 
@@ -842,10 +849,9 @@ namespace gbe {
                                      int& optLevel,
                                      size_t stringSize,
                                      char *err,
-                                     size_t *errSize)
+                                     size_t *errSize,
+                                     uint32_t &oclVersion)
   {
-    std::string dirs = OCL_PCH_PATH;
-    std::istringstream idirs(dirs);
     std::string pchFileName;
     bool findPCH = false;
 #if defined(__ANDROID__)
@@ -858,8 +864,6 @@ namespace gbe {
     std::string hdirs = OCL_HEADER_FILE_DIR;
     if(hdirs == "")
       hdirs = OCL_HEADER_DIR;
-    if(dirs == "")
-      dirs = OCL_PCH_OBJECT;
     std::istringstream hidirs(hdirs);
     std::string headerFilePath;
     bool findOcl = false;
@@ -967,11 +971,16 @@ EXTEND_QUOTE:
 
         if(str.find("-cl-std=") != std::string::npos) {
           useDefaultCLCVersion = false;
-          if (str == "-cl-std=CL1.1")
+          if (str == "-cl-std=CL1.1") {
             clOpt.push_back("-D__OPENCL_C_VERSION__=110");
-          else if (str == "-cl-std=CL1.2")
+            oclVersion = 110;
+          } else if (str == "-cl-std=CL1.2") {
             clOpt.push_back("-D__OPENCL_C_VERSION__=120");
-          else {
+            oclVersion = 120;
+          } else if (str == "-cl-std=CL2.0") {
+            clOpt.push_back("-D__OPENCL_C_VERSION__=200");
+            oclVersion = 200;
+          } else {
             if (err && stringSize > 0 && errSize)
               *errSize = snprintf(err, stringSize, "Invalid build option: %s\n", str.c_str());
             return false;
@@ -1007,8 +1016,15 @@ EXTEND_QUOTE:
     }
 
     if (useDefaultCLCVersion) {
+#ifdef ENABLE_OPENCL_20
+      clOpt.push_back("-D__OPENCL_C_VERSION__=200");
+      clOpt.push_back("-cl-std=CL2.0");
+      oclVersion = 200;
+#else
       clOpt.push_back("-D__OPENCL_C_VERSION__=120");
       clOpt.push_back("-cl-std=CL1.2");
+      oclVersion = 120;
+#endif
     }
     //for clCompilerProgram usage.
     if(temp_header_path){
@@ -1016,6 +1032,14 @@ EXTEND_QUOTE:
       clOpt.push_back(temp_header_path);
     }
 
+    std::string dirs = OCL_PCH_PATH;
+    if(oclVersion >= 200)
+      dirs = OCL_PCH_20_PATH;
+    if(dirs == "") {
+      dirs = oclVersion >= 200 ? OCL_PCH_OBJECT_20 : OCL_PCH_OBJECT;
+    }
+    std::istringstream idirs(dirs);
+
     while (getline(idirs, pchFileName, ':')) {
       if(access(pchFileName.c_str(), R_OK) == 0) {
         findPCH = true;
@@ -1046,10 +1070,11 @@ EXTEND_QUOTE:
     std::vector<std::string> clOpt;
     std::string dumpLLVMFileName, dumpASMFileName;
     std::string dumpSPIRBinaryName;
+    uint32_t oclVersion = 0;
     if (!processSourceAndOption(source, options, NULL, clOpt,
                                 dumpLLVMFileName, dumpASMFileName, dumpSPIRBinaryName,
                                 optLevel,
-                                stringSize, err, errSize))
+                                stringSize, err, errSize, oclVersion))
       return NULL;
 
     gbe_program p;
@@ -1061,7 +1086,7 @@ EXTEND_QUOTE:
       llvm_mutex.lock();
 
     if (buildModuleFromSource(source, &out_module, llvm_ctx, dumpLLVMFileName, dumpSPIRBinaryName, clOpt,
-                              stringSize, err, errSize)) {
+                              stringSize, err, errSize, oclVersion)) {
     // Now build the program from llvm
       size_t clangErrSize = 0;
       if (err != NULL && *errSize != 0) {
@@ -1108,9 +1133,10 @@ EXTEND_QUOTE:
     std::vector<std::string> clOpt;
     std::string dumpLLVMFileName, dumpASMFileName;
     std::string dumpSPIRBinaryName;
+    uint32_t oclVersion = 0;
     if (!processSourceAndOption(source, options, temp_header_path, clOpt,
                                 dumpLLVMFileName, dumpASMFileName, dumpSPIRBinaryName,
-                                optLevel, stringSize, err, errSize))
+                                optLevel, stringSize, err, errSize, oclVersion))
       return NULL;
 
     gbe_program p;
@@ -1125,7 +1151,7 @@ EXTEND_QUOTE:
 #endif
 
     if (buildModuleFromSource(source, &out_module, llvm_ctx, dumpLLVMFileName, dumpSPIRBinaryName, clOpt,
-                              stringSize, err, errSize)) {
+                              stringSize, err, errSize, oclVersion)) {
     // Now build the program from llvm
       if (err != NULL) {
         GBE_ASSERT(errSize != NULL);
diff --git a/backend/src/ir/unit.hpp b/backend/src/ir/unit.hpp
index cce7eac..08dc646 100644
--- a/backend/src/ir/unit.hpp
+++ b/backend/src/ir/unit.hpp
@@ -67,6 +67,7 @@ namespace ir {
     }
     /*! Return the size of the pointers manipulated */
     INLINE PointerSize getPointerSize(void) const { return pointerSize; }
+    INLINE void setPointerSize(PointerSize size) { pointerSize = size; }
     /*! Return the family of registers that contain pointer */
     INLINE RegisterFamily getPointerFamily(void) const {
       if (this->getPointerSize() == POINTER_32_BITS)
@@ -88,7 +89,7 @@ namespace ir {
     bool getInProfilingMode(void) const { return inProfilingMode; }
     void setValid(bool value) { valid = value; }
     bool getValid() { return valid; }
-    void setOclVersoin(uint32_t version) { oclVersion = version; }
+    void setOclVersion(uint32_t version) { oclVersion = version; }
     uint32_t getOclVersion() const { return oclVersion; }
   private:
     friend class ContextInterface; //!< Can free modify the unit
diff --git a/backend/src/llvm/llvm_bitcode_link.cpp b/backend/src/llvm/llvm_bitcode_link.cpp
index 934dd2e..89d5e7c 100644
--- a/backend/src/llvm/llvm_bitcode_link.cpp
+++ b/backend/src/llvm/llvm_bitcode_link.cpp
@@ -26,18 +26,23 @@
 #include "src/GBEConfig.h"
 #include "llvm_includes.hpp"
 #include "llvm/llvm_gen_backend.hpp"
+#include "ir/unit.hpp"
 
 using namespace llvm;
 
 SVAR(OCL_BITCODE_LIB_PATH, OCL_BITCODE_BIN);
+SVAR(OCL_BITCODE_LIB_20_PATH, OCL_BITCODE_BIN_20);
 
 namespace gbe
 {
-  static Module* createOclBitCodeModule(LLVMContext& ctx, bool strictMath)
+  static Module* createOclBitCodeModule(LLVMContext& ctx,
+                                                 bool strictMath,
+                                                 uint32_t oclVersion)
   {
-    std::string bitCodeFiles = OCL_BITCODE_LIB_PATH;
+    std::string bitCodeFiles = oclVersion >= 200 ?
+                               OCL_BITCODE_LIB_20_PATH : OCL_BITCODE_LIB_PATH;
     if(bitCodeFiles == "")
-      bitCodeFiles = OCL_BITCODE_BIN;
+      bitCodeFiles = oclVersion >= 200 ? OCL_BITCODE_BIN_20 : OCL_BITCODE_BIN;
     std::istringstream bitCodeFilePath(bitCodeFiles);
     std::string FilePath;
     bool findBC = false;
@@ -135,12 +140,16 @@ namespace gbe
   }
 
 
-  Module* runBitCodeLinker(Module *mod, bool strictMath)
+  Module* runBitCodeLinker(Module *mod, bool strictMath, ir::Unit &unit)
   {
     LLVMContext& ctx = mod->getContext();
     std::set<std::string> materializedFuncs;
     std::vector<GlobalValue *> Gvs;
-    Module* clonedLib = createOclBitCodeModule(ctx, strictMath);
+
+    uint32_t oclVersion = getModuleOclVersion(mod);
+    ir::PointerSize size = oclVersion >= 200 ? ir::POINTER_64_BITS : ir::POINTER_32_BITS;
+    unit.setPointerSize(size);
+    Module* clonedLib = createOclBitCodeModule(ctx, strictMath, oclVersion);
     if (clonedLib == NULL)
       return NULL;
 
diff --git a/backend/src/llvm/llvm_gen_backend.cpp b/backend/src/llvm/llvm_gen_backend.cpp
index 17eaec6..e7a8b7f 100644
--- a/backend/src/llvm/llvm_gen_backend.cpp
+++ b/backend/src/llvm/llvm_gen_backend.cpp
@@ -1697,6 +1697,9 @@ namespace gbe
 
     // Initialize
     TheModule = &M;
+    uint32_t oclVersion = getModuleOclVersion(TheModule);
+    legacyMode = oclVersion >= 200 ? false : true;
+    unit.setOclVersion(oclVersion);
     collectGlobalConstant();
     return false;
   }
diff --git a/backend/src/llvm/llvm_gen_backend.hpp b/backend/src/llvm/llvm_gen_backend.hpp
index f2a278e..1fecc73 100644
--- a/backend/src/llvm/llvm_gen_backend.hpp
+++ b/backend/src/llvm/llvm_gen_backend.hpp
@@ -153,7 +153,9 @@ namespace gbe
   llvm::FunctionPass* createSamplerFixPass();
 
   /*! Add all the function call of ocl to our bitcode. */
-  llvm::Module* runBitCodeLinker(llvm::Module *mod, bool strictMath);
+  llvm::Module* runBitCodeLinker(llvm::Module *mod, bool strictMath, ir::Unit &unit);
+
+  uint32_t getModuleOclVersion(const llvm::Module *M);
 
   void* getPrintfInfo(llvm::CallInst* inst);
 } /* namespace gbe */
diff --git a/backend/src/llvm/llvm_passes.cpp b/backend/src/llvm/llvm_passes.cpp
index 02dd4bf..f5d9052 100644
--- a/backend/src/llvm/llvm_passes.cpp
+++ b/backend/src/llvm/llvm_passes.cpp
@@ -65,6 +65,27 @@ namespace gbe
     return bKernel;
   }
 
+  uint32_t getModuleOclVersion(const llvm::Module *M) {
+    uint32_t oclVersion = 120;
+    NamedMDNode *version = M->getNamedMetadata("opencl.ocl.version");
+    if (version == NULL)
+      return oclVersion;
+    uint32_t ops = version->getNumOperands();
+    if(ops > 0) {
+      uint32_t major = 0, minor = 0;
+      MDNode* node = version->getOperand(0);
+#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 6
+      major = mdconst::extract<ConstantInt>(node->getOperand(0))->getZExtValue();
+      minor = mdconst::extract<ConstantInt>(node->getOperand(1))->getZExtValue();
+#else
+      major = cast<ConstantInt>(MD->getOperand(0))->getZExtValue();
+      minor = cast<ConstantInt>(MD->getOperand(1))->getZExtValue();
+#endif
+      oclVersion = major * 100 + minor * 10;
+    }
+    return oclVersion;
+  }
+
   int32_t getPadding(int32_t offset, int32_t align) {
     return (align - (offset % align)) % align; 
   }
@@ -262,7 +283,7 @@ namespace gbe
 
         if(!operand)
           continue;
-
+#if 0
         //HACK TODO: Inserted by type replacement.. this code could break something????
         if(getTypeByteSize(unit, operand->getType())>4)
         {
@@ -286,7 +307,7 @@ namespace gbe
                   "", GEPInst);
           }
         }
-
+#endif
         Value* tmpMul = operand;
         if (size != 1) {
           tmpMul = BinaryOperator::Create(Instruction::Mul, newConstSize, operand,
diff --git a/backend/src/llvm/llvm_to_gen.cpp b/backend/src/llvm/llvm_to_gen.cpp
index 42f24b3..7847769 100644
--- a/backend/src/llvm/llvm_to_gen.cpp
+++ b/backend/src/llvm/llvm_to_gen.cpp
@@ -321,8 +321,9 @@ namespace gbe
 
     std::unique_ptr<Module> M;
 
-    /* Before do any thing, we first filter in all CL functions in bitcode. */ 
-    M.reset(runBitCodeLinker(cl_mod, strictMath));
+    /* Before do any thing, we first filter in all CL functions in bitcode. */
+    /* Also set unit's pointer size in runBitCodeLinker */
+    M.reset(runBitCodeLinker(cl_mod, strictMath, unit));
     if (!module)
       delete cl_mod;
     if (M.get() == 0)
-- 
2.1.4



More information about the Beignet mailing list