Make LLVM compile and optimize for the current CPU

This commit is contained in:
Magnus Norddahl 2016-09-27 03:07:03 +02:00
parent 4f2ae42ed5
commit d5c7a7ab76
3 changed files with 75 additions and 26 deletions

View file

@ -13,36 +13,75 @@
RenderProgram::RenderProgram() RenderProgram::RenderProgram()
{ {
llvm::install_fatal_error_handler([](void *user_data, const std::string& reason, bool gen_crash_diag) { using namespace llvm;
I_FatalError(reason.c_str());
install_fatal_error_handler([](void *user_data, const std::string& reason, bool gen_crash_diag) {
I_FatalError("LLVM fatal error: %s", reason.c_str());
}); });
//llvm::llvm_start_multithreaded(); InitializeNativeTarget();
llvm::InitializeNativeTarget(); InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmPrinter(); InitializeNativeTargetAsmParser();
llvm::InitializeNativeTargetAsmParser();
mContext = std::make_unique<llvm::LLVMContext>();
auto moduleOwner = std::make_unique<llvm::Module>("render", context());
mModule = moduleOwner.get();
std::string errorstring; std::string errorstring;
llvm::EngineBuilder engineBuilder(std::move(moduleOwner));
std::string targetTriple = sys::getProcessTriple();
std::string cpuName = sys::getHostCPUName();
StringMap<bool> cpuFeatures;
sys::getHostCPUFeatures(cpuFeatures);
std::string cpuFeaturesStr;
for (const auto &it : cpuFeatures)
{
if (!cpuFeaturesStr.empty())
cpuFeaturesStr.push_back(' ');
cpuFeaturesStr.push_back(it.getValue() ? '+' : '-');
cpuFeaturesStr += it.getKey();
}
Printf("LLVM target triple: %s\n", targetTriple.c_str());
Printf("LLVM CPU and features: %s, %s\n", cpuName.c_str(), cpuFeaturesStr.c_str());
const Target *target = TargetRegistry::lookupTarget(targetTriple, errorstring);
if (!target)
I_FatalError("Could not find LLVM target: %s", errorstring.c_str());
TargetOptions opt;
auto relocModel = Optional<Reloc::Model>(Reloc::Static);
TargetMachine *machine = target->createTargetMachine(targetTriple, cpuName, cpuFeaturesStr, opt, relocModel, CodeModel::Default, CodeGenOpt::Aggressive);
if (!machine)
I_FatalError("Could not create LLVM target machine");
mContext = std::make_unique<LLVMContext>();
auto moduleOwner = std::make_unique<Module>("render", context());
mModule = moduleOwner.get();
mModule->setTargetTriple(targetTriple);
mModule->setDataLayout(machine->createDataLayout());
EngineBuilder engineBuilder(std::move(moduleOwner));
engineBuilder.setErrorStr(&errorstring); engineBuilder.setErrorStr(&errorstring);
engineBuilder.setOptLevel(llvm::CodeGenOpt::Aggressive); engineBuilder.setOptLevel(CodeGenOpt::Aggressive);
engineBuilder.setRelocationModel(llvm::Reloc::Static); engineBuilder.setRelocationModel(Reloc::Static);
engineBuilder.setEngineKind(llvm::EngineKind::JIT); engineBuilder.setEngineKind(EngineKind::JIT);
mEngine.reset(engineBuilder.create()); mEngine.reset(engineBuilder.create(machine));
if (!mEngine) if (!mEngine)
I_FatalError(errorstring.c_str()); I_FatalError("Could not create LLVM execution engine: %s", errorstring.c_str());
mModulePassManager = std::make_unique<legacy::PassManager>();
mFunctionPassManager = std::make_unique<legacy::FunctionPassManager>(mModule);
PassManagerBuilder passManagerBuilder;
passManagerBuilder.OptLevel = 3;
passManagerBuilder.SizeLevel = 0;
passManagerBuilder.Inliner = createFunctionInliningPass();
passManagerBuilder.populateModulePassManager(*mModulePassManager.get());
passManagerBuilder.populateFunctionPassManager(*mFunctionPassManager.get());
} }
RenderProgram::~RenderProgram() RenderProgram::~RenderProgram()
{ {
mEngine.reset(); mEngine.reset();
mContext.reset(); mContext.reset();
//llvm::llvm_stop_multithreaded();
} }
void *RenderProgram::PointerToFunction(const char *name) void *RenderProgram::PointerToFunction(const char *name)
@ -57,6 +96,7 @@ FixedFunction::FixedFunction()
{ {
CodegenDrawSpan(); CodegenDrawSpan();
mProgram.engine()->finalizeObject(); mProgram.engine()->finalizeObject();
mProgram.modulePassManager()->run(*mProgram.module());
DrawSpan = mProgram.GetProcAddress<void(int, uint32_t *)>("DrawSpan"); DrawSpan = mProgram.GetProcAddress<void(int, uint32_t *)>("DrawSpan");
} }
@ -81,12 +121,12 @@ void FixedFunction::CodegenDrawSpan()
SSAInt index = stack_index.load(); SSAInt index = stack_index.load();
loop.loop_block(index < count); loop.loop_block(index < count);
//SSAVec4i color(255, 255, 0, 255); SSAVec4i color(0, 128, 255, 255);
//data[index * 4].store_vec4ub(color); data[index * 4].store_vec4ub(color);
data[index * 4].store(0); /*data[index * 4].store(0);
data[index * 4 + 1].store(128); data[index * 4 + 1].store(128);
data[index * 4 + 2].store(255); data[index * 4 + 2].store(255);
data[index * 4 + 3].store(255); data[index * 4 + 3].store(255);*/
stack_index.store(index + 1); stack_index.store(index + 1);
} }
loop.end_block(); loop.end_block();
@ -95,6 +135,8 @@ void FixedFunction::CodegenDrawSpan()
if (llvm::verifyFunction(*function.func)) if (llvm::verifyFunction(*function.func))
I_FatalError("verifyFunction failed for " __FUNCTION__); I_FatalError("verifyFunction failed for " __FUNCTION__);
mProgram.functionPassManager()->run(*function.func);
} }
#if 0 #if 0

View file

@ -26,6 +26,8 @@ public:
llvm::LLVMContext &context() { return *mContext; } llvm::LLVMContext &context() { return *mContext; }
llvm::Module *module() { return mModule; } llvm::Module *module() { return mModule; }
llvm::ExecutionEngine *engine() { return mEngine.get(); } llvm::ExecutionEngine *engine() { return mEngine.get(); }
llvm::legacy::PassManager *modulePassManager() { return mModulePassManager.get(); }
llvm::legacy::FunctionPassManager *functionPassManager() { return mFunctionPassManager.get(); }
private: private:
void *PointerToFunction(const char *name); void *PointerToFunction(const char *name);
@ -33,6 +35,8 @@ private:
std::unique_ptr<llvm::LLVMContext> mContext; std::unique_ptr<llvm::LLVMContext> mContext;
llvm::Module *mModule; llvm::Module *mModule;
std::unique_ptr<llvm::ExecutionEngine> mEngine; std::unique_ptr<llvm::ExecutionEngine> mEngine;
std::unique_ptr<llvm::legacy::PassManager> mModulePassManager;
std::unique_ptr<llvm::legacy::FunctionPassManager> mFunctionPassManager;
}; };
class FixedFunction class FixedFunction

View file

@ -20,19 +20,22 @@
#pragma warning(disable: 4291) // warning C4291: 'void *llvm::User::operator new(std::size_t,unsigned int,unsigned int)': no matching operator delete found; memory will not be freed if initialization throws an exception #pragma warning(disable: 4291) // warning C4291: 'void *llvm::User::operator new(std::size_t,unsigned int,unsigned int)': no matching operator delete found; memory will not be freed if initialization throws an exception
#include <llvm/IR/DerivedTypes.h> #include <llvm/IR/DerivedTypes.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/IR/LLVMContext.h> #include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h> #include <llvm/IR/Module.h>
#include <llvm/IR/Attributes.h> #include <llvm/IR/Attributes.h>
#include <llvm/IR/Verifier.h> #include <llvm/IR/Verifier.h>
#include <llvm/IR/PassManager.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/Intrinsics.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/Analysis/Passes.h> #include <llvm/Analysis/Passes.h>
#include <llvm/Transforms/Scalar.h> #include <llvm/Transforms/Scalar.h>
#include <llvm/Transforms/IPO.h> #include <llvm/Transforms/IPO.h>
#include <llvm/Transforms/IPO/PassManagerBuilder.h> #include <llvm/Transforms/IPO/PassManagerBuilder.h>
#include <llvm/Support/TargetSelect.h> #include <llvm/Support/TargetSelect.h>
#include <llvm/IR/IRBuilder.h> #include <llvm/Support/TargetRegistry.h>
#include <llvm/IR/Intrinsics.h>
#include <llvm/CodeGen/AsmPrinter.h> #include <llvm/CodeGen/AsmPrinter.h>
#include <llvm/MC/MCAsmInfo.h> #include <llvm/MC/MCAsmInfo.h>