summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/src/backend/gen_program.cpp5
-rw-r--r--backend/src/backend/program.cpp23
-rw-r--r--backend/src/backend/program.h3
-rw-r--r--backend/src/backend/program.hpp2
-rw-r--r--backend/src/llvm/llvm_to_gen.cpp102
-rw-r--r--backend/src/llvm/llvm_to_gen.hpp5
-rw-r--r--src/cl_program.c2
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;