diff options
-rw-r--r-- | backend/src/backend/gen_program.cpp | 5 | ||||
-rw-r--r-- | backend/src/backend/program.cpp | 23 | ||||
-rw-r--r-- | backend/src/backend/program.h | 3 | ||||
-rw-r--r-- | backend/src/backend/program.hpp | 2 | ||||
-rw-r--r-- | backend/src/llvm/llvm_to_gen.cpp | 102 | ||||
-rw-r--r-- | backend/src/llvm/llvm_to_gen.hpp | 5 | ||||
-rw-r--r-- | 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 e0a6f91f..22f4aa19 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 46ec04fd..3ab1bc2d 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 9a3570e4..b1debee9 100644 --- a/backend/src/backend/program.h +++ b/backend/src/backend/program.h @@ -132,7 +132,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 0f887424..e6fc4110 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 e11e449a..a9f70d9d 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 40066671..50ea267e 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 d6d68c07..10eeceed 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; |