[Beignet] [PATCH 1/2] Move the llvm optimize pass from clang to backend.

Yang Rong rong.r.yang at intel.com
Wed Dec 25 17:55:54 PST 2013


Call llvm opt pass in llvmToGen. Remove SROA pass and call GVN pass with NoLoads is true to avoid
large integer. Also handle the opt level in function llvmToGen, 0 equal to clang -O1, and 1 equal to
clang -O2.

Signed-off-by: Yang Rong <rong.r.yang at intel.com>
---
 backend/src/backend/gen_program.cpp |   5 +-
 backend/src/backend/program.cpp     |  23 ++++----
 backend/src/backend/program.h       |   3 +-
 backend/src/backend/program.hpp     |   2 +-
 backend/src/llvm/llvm_to_gen.cpp    | 102 ++++++++++++++++++++++++++++++++++--
 backend/src/llvm/llvm_to_gen.hpp    |   5 +-
 src/cl_program.c                    |   2 +-
 7 files changed, 119 insertions(+), 23 deletions(-)

diff --git a/backend/src/backend/gen_program.cpp b/backend/src/backend/gen_program.cpp
index e0a6f91..22f4aa1 100644
--- a/backend/src/backend/gen_program.cpp
+++ b/backend/src/backend/gen_program.cpp
@@ -151,13 +151,14 @@ namespace gbe {
   static gbe_program genProgramNewFromLLVM(const char *fileName,
                                            size_t stringSize,
                                            char *err,
-                                           size_t *errSize)
+                                           size_t *errSize,
+                                           int optLevel)
   {
     using namespace gbe;
     GenProgram *program = GBE_NEW_NO_ARG(GenProgram);
     std::string error;
     // Try to compile the program
-    if (program->buildFromLLVMFile(fileName, error) == false) {
+    if (program->buildFromLLVMFile(fileName, error, optLevel) == false) {
       if (err != NULL && errSize != NULL && stringSize > 0u) {
         const size_t msgSize = std::min(error.size(), stringSize-1u);
         std::memcpy(err, error.c_str(), msgSize);
diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp
index 46ec04f..3ab1bc2 100644
--- a/backend/src/backend/program.cpp
+++ b/backend/src/backend/program.cpp
@@ -102,9 +102,9 @@ namespace gbe {
 
   BVAR(OCL_OUTPUT_GEN_IR, false);
 
-  bool Program::buildFromLLVMFile(const char *fileName, std::string &error) {
+  bool Program::buildFromLLVMFile(const char *fileName, std::string &error, int optLevel) {
     ir::Unit unit;
-    if (llvmToGen(unit, fileName) == false) {
+    if (llvmToGen(unit, fileName, optLevel) == false) {
       error = std::string(fileName) + " not found";
       return false;
     }
@@ -469,7 +469,6 @@ namespace gbe {
                                     size_t stringSize, char *err, size_t *errSize) {
     // Arguments to pass to the clang frontend
     vector<const char *> args;
-    bool bOpt = true;
     bool bFastMath = false;
 
     vector<std::string> useless; //hold substrings to avoid c_str free
@@ -480,7 +479,8 @@ namespace gbe {
        -cl-no-signed-zeros, -cl-fp32-correctly-rounded-divide-sqrt
        all support options, refer to clang/include/clang/Driver/Options.inc
     */
-    const std::string unsupportedOptions("-cl-denorms-are-zero, -cl-strict-aliasing,"
+    //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);
@@ -488,7 +488,6 @@ namespace gbe {
       start = end + 1;
       if(str.size() == 0)
         continue;
-      if(str == "-cl-opt-disable") bOpt = false;
       if(str == "-cl-fast-relaxed-math") bFastMath = true;
       if(unsupportedOptions.find(str) != std::string::npos)
         continue;
@@ -504,12 +503,7 @@ namespace gbe {
     // FIXME we haven't implement those builtin functions,
     // so disable it currently.
     args.push_back("-fno-builtin");
-    // FIXME as we don't support function call currently, we may encounter
-    // build problem with -O0 as we rely on always inline all functions option. 
-    if(bOpt)
-      args.push_back("-O2");
-    else
-      args.push_back("-O1");
+    args.push_back("-disable-llvm-optzns");
     if(bFastMath)
       args.push_back("-D __FAST_RELAXED_MATH__=1");
 #if LLVM_VERSION_MINOR <= 2
@@ -659,6 +653,7 @@ namespace gbe {
     const std::string llName = std::string(tmpnam_r(llStr)) + ".ll"; /* unsafe! */
     std::string pchHeaderName;
     std::string clOpt;
+    int optLevel = 1;
 
     FILE *clFile = fopen(clName.c_str(), "w");
     FATAL_IF(clFile == NULL, "Failed to open temporary file");
@@ -728,6 +723,10 @@ namespace gbe {
         }
       }
 
+      p = strstr(const_cast<char *>(options), "-cl-opt-disable");
+      if (p)
+        optLevel = 0;
+
       clOpt += options;
     }
 
@@ -766,7 +765,7 @@ namespace gbe {
         clangErrSize = *errSize;
       }
       p = gbe_program_new_from_llvm(llName.c_str(), stringSize,
-                                    err, errSize);
+                                    err, errSize, optLevel);
       if (err != NULL)
         *errSize += clangErrSize;
       gbe_mutex.unlock();
diff --git a/backend/src/backend/program.h b/backend/src/backend/program.h
index e574764..d00ea51 100644
--- a/backend/src/backend/program.h
+++ b/backend/src/backend/program.h
@@ -130,7 +130,8 @@ extern gbe_program_serialize_to_binary_cb *gbe_program_serialize_to_binary;
 typedef gbe_program (gbe_program_new_from_llvm_cb)(const char *fileName,
                                                    size_t string_size,
                                                    char *err,
-                                                   size_t *err_size);
+                                                   size_t *err_size,
+                                                   int optLevel);
 extern gbe_program_new_from_llvm_cb *gbe_program_new_from_llvm;
 
 /*! Get the size of global constants */
diff --git a/backend/src/backend/program.hpp b/backend/src/backend/program.hpp
index 0f88742..e6fc411 100644
--- a/backend/src/backend/program.hpp
+++ b/backend/src/backend/program.hpp
@@ -231,7 +231,7 @@ namespace gbe {
     /*! Build a program from a ir::Unit */
     bool buildFromUnit(const ir::Unit &unit, std::string &error);
     /*! Buils a program from a LLVM source code */
-    bool buildFromLLVMFile(const char *fileName, std::string &error);
+    bool buildFromLLVMFile(const char *fileName, std::string &error, int optLevel);
     /*! Buils a program from a OCL string */
     bool buildFromSource(const char *source, std::string &error);
     /*! Get size of the global constant arrays */
diff --git a/backend/src/llvm/llvm_to_gen.cpp b/backend/src/llvm/llvm_to_gen.cpp
index e11e449..a9f70d9 100644
--- a/backend/src/llvm/llvm_to_gen.cpp
+++ b/backend/src/llvm/llvm_to_gen.cpp
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright © 2012 Intel Corporation
  *
  * This library is free software; you can redistribute it and/or
@@ -26,12 +26,19 @@
 #if LLVM_VERSION_MINOR <= 2
 #include "llvm/LLVMContext.h"
 #include "llvm/Module.h"
+#include "llvm/DataLayout.h"
 #else
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/DataLayout.h"
 #endif  /* LLVM_VERSION_MINOR <= 2 */
 #include "llvm/PassManager.h"
 #include "llvm/Pass.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Analysis/Passes.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Target/TargetLibraryInfo.h"
+#include "llvm/ADT/Triple.h"
 #if LLVM_VERSION_MINOR <= 2
 #include "llvm/Support/IRReader.h"
 #else
@@ -56,11 +63,92 @@ namespace gbe
 {
   BVAR(OCL_OUTPUT_LLVM, false);
   BVAR(OCL_OUTPUT_LLVM_BEFORE_EXTRA_PASS, false);
+  using namespace llvm;
 
-  bool llvmToGen(ir::Unit &unit, const char *fileName)
+  void runFuntionPass(Module &mod, TargetLibraryInfo *libraryInfo)
   {
-    using namespace llvm;
+    FunctionPassManager FPM(&mod);
+    FPM.add(new DataLayout(&mod));
+    FPM.add(createVerifierPass());
+    FPM.add(new TargetLibraryInfo(*libraryInfo));
+    FPM.add(createTypeBasedAliasAnalysisPass());
+    FPM.add(createBasicAliasAnalysisPass());
+    FPM.add(createCFGSimplificationPass());
+    FPM.add(createSROAPass());
+    FPM.add(createEarlyCSEPass());
+    FPM.add(createLowerExpectIntrinsicPass());
 
+    FPM.doInitialization();
+    for (Module::iterator I = mod.begin(),
+           E = mod.end(); I != E; ++I)
+      if (!I->isDeclaration())
+        FPM.run(*I);
+    FPM.doFinalization();
+  }
+
+  void runModulePass(Module &mod, TargetLibraryInfo *libraryInfo, int optLevel)
+  {
+    llvm::PassManager MPM;
+
+    MPM.add(new DataLayout(&mod));
+    MPM.add(new TargetLibraryInfo(*libraryInfo));
+    MPM.add(createTypeBasedAliasAnalysisPass());
+    MPM.add(createBasicAliasAnalysisPass());
+    MPM.add(createGlobalOptimizerPass());     // Optimize out global vars
+
+    MPM.add(createIPSCCPPass());              // IP SCCP
+    MPM.add(createDeadArgEliminationPass());  // Dead argument elimination
+
+    MPM.add(createInstructionCombiningPass());// Clean up after IPCP & DAE
+    MPM.add(createCFGSimplificationPass());   // Clean up after IPCP & DAE
+    MPM.add(createPruneEHPass());             // Remove dead EH info
+    MPM.add(createFunctionInliningPass(200000));
+    MPM.add(createFunctionAttrsPass());       // Set readonly/readnone attrs
+
+    //MPM.add(createScalarReplAggregatesPass(64, true, -1, -1, 64))
+    //MPM.add(createSROAPass(/*RequiresDomTree*/ false));
+    MPM.add(createEarlyCSEPass());              // Catch trivial redundancies
+    MPM.add(createJumpThreadingPass());         // Thread jumps.
+    MPM.add(createCorrelatedValuePropagationPass()); // Propagate conditionals
+    MPM.add(createCFGSimplificationPass());     // Merge & remove BBs
+    MPM.add(createInstructionCombiningPass());  // Combine silly seq's
+
+    MPM.add(createTailCallEliminationPass());   // Eliminate tail calls
+    MPM.add(createCFGSimplificationPass());     // Merge & remove BBs
+    MPM.add(createReassociatePass());           // Reassociate expressions
+    MPM.add(createLoopRotatePass());            // Rotate Loop
+    MPM.add(createLICMPass());                  // Hoist loop invariants
+    MPM.add(createLoopUnswitchPass(true));
+    MPM.add(createInstructionCombiningPass());
+    MPM.add(createIndVarSimplifyPass());        // Canonicalize indvars
+    MPM.add(createLoopIdiomPass());             // Recognize idioms like memset.
+    MPM.add(createLoopDeletionPass());          // Delete dead loops
+    MPM.add(createLoopUnrollPass());          // Unroll small loops
+    if(optLevel > 0)
+      MPM.add(createGVNPass(true));                 // Remove redundancies
+    MPM.add(createMemCpyOptPass());             // Remove memcpy / form memset
+    MPM.add(createSCCPPass());                  // Constant prop with SCCP
+
+    // Run instcombine after redundancy elimination to exploit opportunities
+    // opened up by them.
+    MPM.add(createInstructionCombiningPass());
+    MPM.add(createJumpThreadingPass());         // Thread jumps
+    MPM.add(createCorrelatedValuePropagationPass());
+    MPM.add(createDeadStoreEliminationPass());  // Delete dead stores
+    MPM.add(createAggressiveDCEPass());         // Delete dead instructions
+    MPM.add(createCFGSimplificationPass()); // Merge & remove BBs
+    MPM.add(createInstructionCombiningPass());  // Clean up after everything.
+    MPM.add(createStripDeadPrototypesPass()); // Get rid of dead prototypes
+    if(optLevel > 0) {
+      MPM.add(createGlobalDCEPass());         // Remove dead fns and globals.
+      MPM.add(createConstantMergePass());     // Merge dup global constants
+    }
+
+    MPM.run(mod);
+  }
+
+  bool llvmToGen(ir::Unit &unit, const char *fileName, int optLevel)
+  {
     // Get the global LLVM context
     llvm::LLVMContext& c = llvm::getGlobalContext();
     std::string errInfo;
@@ -75,6 +163,13 @@ namespace gbe
     if (M.get() == 0) return false;
     Module &mod = *M.get();
 
+    Triple TargetTriple(mod.getTargetTriple());
+    TargetLibraryInfo *libraryInfo = new TargetLibraryInfo(TargetTriple);
+    libraryInfo->disableAllFunctions();
+
+    runFuntionPass(mod, libraryInfo);
+    runModulePass(mod, libraryInfo, optLevel);
+
     llvm::PassManager passes;
 
     // Print the code before further optimizations
@@ -98,4 +193,3 @@ namespace gbe
     return true;
   }
 } /* namespace gbe */
-
diff --git a/backend/src/llvm/llvm_to_gen.hpp b/backend/src/llvm/llvm_to_gen.hpp
index 4006667..50ea267 100644
--- a/backend/src/llvm/llvm_to_gen.hpp
+++ b/backend/src/llvm/llvm_to_gen.hpp
@@ -30,8 +30,9 @@ namespace gbe {
     class Unit;
   } /* namespace ir */
 
-  /*! Convert the LLVM IR code to a GEN IR code */
-  bool llvmToGen(ir::Unit &unit, const char *fileName);
+  /*! Convert the LLVM IR code to a GEN IR code,
+		  optLevel 0 equal to clang -O1 and 1 equal to clang -O2*/
+  bool llvmToGen(ir::Unit &unit, const char *fileName, int optLevel);
 
 } /* namespace gbe */
 
diff --git a/src/cl_program.c b/src/cl_program.c
index d6d68c0..10eecee 100644
--- a/src/cl_program.c
+++ b/src/cl_program.c
@@ -225,7 +225,7 @@ cl_program_create_from_llvm(cl_context ctx,
   INVALID_VALUE_IF (file_name == NULL);
 
   program = cl_program_new(ctx);
-  program->opaque = gbe_program_new_from_llvm(file_name, program->build_log_max_sz, program->build_log, &program->build_log_sz);
+  program->opaque = gbe_program_new_from_llvm(file_name, program->build_log_max_sz, program->build_log, &program->build_log_sz, 1);
   if (UNLIKELY(program->opaque == NULL)) {
     err = CL_INVALID_PROGRAM;
     goto error;
-- 
1.8.1.2



More information about the Beignet mailing list