Browse Source

Optimizer: separate LLVM IR optimization passes from compiler

cl-refactor
Paweł Bylica 10 years ago
parent
commit
e5519d00d8
  1. 11
      evmjit/libevmjit/Compiler.cpp
  2. 1
      evmjit/libevmjit/ExecStats.cpp
  3. 10
      evmjit/libevmjit/ExecutionEngine.cpp
  4. 1
      evmjit/libevmjit/ExecutionEngine.h
  5. 24
      evmjit/libevmjit/Optimizer.cpp
  6. 19
      evmjit/libevmjit/Optimizer.h

11
evmjit/libevmjit/Compiler.cpp

@ -6,13 +6,10 @@
#include <sstream> #include <sstream>
#include "preprocessor/llvm_includes_start.h" #include "preprocessor/llvm_includes_start.h"
#include <llvm/ADT/PostOrderIterator.h>
#include <llvm/IR/CFG.h> #include <llvm/IR/CFG.h>
#include <llvm/IR/Module.h> #include <llvm/IR/Module.h>
#include <llvm/IR/IntrinsicInst.h> #include <llvm/IR/IntrinsicInst.h>
#include <llvm/IR/MDBuilder.h> #include <llvm/IR/MDBuilder.h>
#include <llvm/PassManager.h>
#include <llvm/Transforms/Scalar.h>
#include "preprocessor/llvm_includes_end.h" #include "preprocessor/llvm_includes_end.h"
#include "Instruction.h" #include "Instruction.h"
@ -230,14 +227,6 @@ std::unique_ptr<llvm::Module> Compiler::compile(code_iterator _begin, code_itera
dumpCFGifRequired("blocks-sync.dot"); dumpCFGifRequired("blocks-sync.dot");
if (m_jumpTableBlock && m_options.rewriteSwitchToBranches)
{
llvm::FunctionPassManager fpManager(module.get());
fpManager.add(llvm::createLowerSwitchPass());
fpManager.doInitialization();
fpManager.run(*m_mainFunc);
}
auto compilationEndTime = std::chrono::high_resolution_clock::now(); auto compilationEndTime = std::chrono::high_resolution_clock::now();
clog(JIT) << "JIT: " << std::chrono::duration_cast<std::chrono::milliseconds>(compilationEndTime - compilationStartTime).count(); clog(JIT) << "JIT: " << std::chrono::duration_cast<std::chrono::milliseconds>(compilationEndTime - compilationStartTime).count();
return module; return module;

1
evmjit/libevmjit/ExecStats.cpp

@ -67,6 +67,7 @@ char const* getExecStateName(ExecState _state)
case ExecState::CacheLoad: return "CacheLoad"; case ExecState::CacheLoad: return "CacheLoad";
case ExecState::CacheWrite: return "CacheWrite"; case ExecState::CacheWrite: return "CacheWrite";
case ExecState::Compilation: return "Compilation"; case ExecState::Compilation: return "Compilation";
case ExecState::Optimization: return "Optimization";
case ExecState::CodeGen: return "CodeGen"; case ExecState::CodeGen: return "CodeGen";
case ExecState::Execution: return "Execution"; case ExecState::Execution: return "Execution";
case ExecState::Return: return "Return"; case ExecState::Return: return "Return";

10
evmjit/libevmjit/ExecutionEngine.cpp

@ -16,6 +16,7 @@
#include "Runtime.h" #include "Runtime.h"
#include "Compiler.h" #include "Compiler.h"
#include "Optimizer.h"
#include "Cache.h" #include "Cache.h"
#include "ExecStats.h" #include "ExecStats.h"
#include "Utils.h" #include "Utils.h"
@ -70,6 +71,7 @@ bool showInfo()
ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env) ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env)
{ {
static auto optimizationEnabled = getEnvOption("EVMJIT_OPT", false);
static auto debugDumpModule = getEnvOption("EVMJIT_DUMP", false); static auto debugDumpModule = getEnvOption("EVMJIT_DUMP", false);
static auto objectCacheEnabled = getEnvOption("EVMJIT_CACHE", true); static auto objectCacheEnabled = getEnvOption("EVMJIT_CACHE", true);
static auto statsCollectingEnabled = getEnvOption("EVMJIT_STATS", false); static auto statsCollectingEnabled = getEnvOption("EVMJIT_STATS", false);
@ -118,7 +120,13 @@ ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env)
{ {
listener->stateChanged(ExecState::Compilation); listener->stateChanged(ExecState::Compilation);
assert(_data->code || !_data->codeSize); //TODO: Is it good idea to execute empty code? assert(_data->code || !_data->codeSize); //TODO: Is it good idea to execute empty code?
module = Compiler({}).compile(_data->code, _data->code + _data->codeSize, mainFuncName); module = Compiler{{}}.compile(_data->code, _data->code + _data->codeSize, mainFuncName);
if (optimizationEnabled)
{
listener->stateChanged(ExecState::Optimization);
optimize(*module);
}
} }
if (debugDumpModule) if (debugDumpModule)
module->dump(); module->dump();

1
evmjit/libevmjit/ExecutionEngine.h

@ -17,6 +17,7 @@ enum class ExecState
CacheLoad, CacheLoad,
CacheWrite, CacheWrite,
Compilation, Compilation,
Optimization,
CodeGen, CodeGen,
Execution, Execution,
Return, Return,

24
evmjit/libevmjit/Optimizer.cpp

@ -0,0 +1,24 @@
#include "Optimizer.h"
#include "preprocessor/llvm_includes_start.h"
#include <llvm/PassManager.h>
#include <llvm/Transforms/Scalar.h>
#include "preprocessor/llvm_includes_end.h"
namespace dev
{
namespace eth
{
namespace jit
{
bool optimize(llvm::Module& _module)
{
auto pm = llvm::PassManager{};
pm.add(llvm::createLowerSwitchPass());
return pm.run(_module);
}
}
}
}

19
evmjit/libevmjit/Optimizer.h

@ -0,0 +1,19 @@
#pragma once
namespace llvm
{
class Module;
}
namespace dev
{
namespace eth
{
namespace jit
{
bool optimize(llvm::Module& _module);
}
}
}
Loading…
Cancel
Save