mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-26 06:01:14 +00:00
Cache the optimized bitcode (note: this adds LLVMBitWriter as a dependency)
This commit is contained in:
parent
d197ebca78
commit
b4eb49678a
3 changed files with 190 additions and 109 deletions
|
@ -294,7 +294,7 @@ endif()
|
||||||
set( LLVM_PRECOMPILED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../llvm" )
|
set( LLVM_PRECOMPILED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../llvm" )
|
||||||
|
|
||||||
if( NOT WIN32 )
|
if( NOT WIN32 )
|
||||||
set( LLVM_COMPONENTS core support asmparser asmprinter bitreader codegen ipo
|
set( LLVM_COMPONENTS core support asmparser asmprinter bitreader bitwriter codegen ipo
|
||||||
irreader transformutils instrumentation profiledata runtimedyld
|
irreader transformutils instrumentation profiledata runtimedyld
|
||||||
object instcombine linker analysis selectiondag scalaropts vectorize executionengine
|
object instcombine linker analysis selectiondag scalaropts vectorize executionengine
|
||||||
mc mcdisassembler mcparser mcjit target x86asmprinter x86info x86desc x86utils x86codegen )
|
mc mcdisassembler mcparser mcjit target x86asmprinter x86info x86desc x86utils x86codegen )
|
||||||
|
@ -307,7 +307,7 @@ if( NOT WIN32 )
|
||||||
include_directories( ${LLVM_INCLUDE_DIRS} )
|
include_directories( ${LLVM_INCLUDE_DIRS} )
|
||||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} ${llvm_libs} )
|
set( ZDOOM_LIBS ${ZDOOM_LIBS} ${llvm_libs} )
|
||||||
else()
|
else()
|
||||||
set( LLVM_COMPONENTS core support asmparser asmprinter bitreader codegen passes ipo
|
set( LLVM_COMPONENTS core support asmparser asmprinter bitreader bitwriter codegen passes ipo
|
||||||
irreader transformutils instrumentation profiledata debuginfocodeview runtimedyld
|
irreader transformutils instrumentation profiledata debuginfocodeview runtimedyld
|
||||||
object instcombine linker analysis selectiondag scalaropts vectorize executionengine
|
object instcombine linker analysis selectiondag scalaropts vectorize executionengine
|
||||||
mc mcdisassembler mcparser mcjit target x86asmprinter x86info x86desc x86utils x86codegen )
|
mc mcdisassembler mcparser mcjit target x86asmprinter x86info x86desc x86utils x86codegen )
|
||||||
|
|
|
@ -75,6 +75,7 @@
|
||||||
#include <llvm/CodeGen/AsmPrinter.h>
|
#include <llvm/CodeGen/AsmPrinter.h>
|
||||||
#include <llvm/MC/MCAsmInfo.h>
|
#include <llvm/MC/MCAsmInfo.h>
|
||||||
#include <llvm/Target/TargetSubtargetInfo.h>
|
#include <llvm/Target/TargetSubtargetInfo.h>
|
||||||
|
#include <llvm/Bitcode/ReaderWriter.h>
|
||||||
|
|
||||||
#if LLVM_VERSION_MAJOR < 3 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 8)
|
#if LLVM_VERSION_MAJOR < 3 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 8)
|
||||||
#include <llvm/Support/FormattedStream.h>
|
#include <llvm/Support/FormattedStream.h>
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "m_misc.h"
|
||||||
|
|
||||||
CUSTOM_CVAR(String, llvm_cpu, "auto", CVAR_ARCHIVE | CVAR_NOINITCALL)
|
CUSTOM_CVAR(String, llvm_cpu, "auto", CVAR_ARCHIVE | CVAR_NOINITCALL)
|
||||||
{
|
{
|
||||||
|
@ -51,7 +52,9 @@ public:
|
||||||
LLVMProgram();
|
LLVMProgram();
|
||||||
|
|
||||||
void CreateModule();
|
void CreateModule();
|
||||||
void CreateEE();
|
std::string GetTargetCPU();
|
||||||
|
bool LoadCachedModule(int version, std::string targetCPU);
|
||||||
|
void CreateEE(int version, std::string targetCPU, bool optimize);
|
||||||
std::string GenerateAssembly(std::string cpuName);
|
std::string GenerateAssembly(std::string cpuName);
|
||||||
std::string DumpModule();
|
std::string DumpModule();
|
||||||
void StopLogFatalErrors();
|
void StopLogFatalErrors();
|
||||||
|
@ -64,6 +67,8 @@ public:
|
||||||
llvm::ExecutionEngine *engine() { return mEngine.get(); }
|
llvm::ExecutionEngine *engine() { return mEngine.get(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void SaveCachedModule(llvm::Module *module, int version, std::string targetCPU);
|
||||||
|
FString GetDrawerCacheFilename(int version, FString cpu);
|
||||||
void *PointerToFunction(const char *name);
|
void *PointerToFunction(const char *name);
|
||||||
|
|
||||||
llvm::TargetMachine *machine = nullptr;
|
llvm::TargetMachine *machine = nullptr;
|
||||||
|
@ -121,6 +126,11 @@ LLVMDrawers *LLVMDrawers::Instance()
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
LLVMDrawersImpl::LLVMDrawersImpl()
|
LLVMDrawersImpl::LLVMDrawersImpl()
|
||||||
|
{
|
||||||
|
int version = 1; // Increment this number if the drawer codegen is modified (forces recreation of the module).
|
||||||
|
std::string targetCPU = mProgram.GetTargetCPU();
|
||||||
|
bool loaded = mProgram.LoadCachedModule(version, targetCPU);
|
||||||
|
if (!loaded)
|
||||||
{
|
{
|
||||||
mProgram.CreateModule();
|
mProgram.CreateModule();
|
||||||
|
|
||||||
|
@ -198,8 +208,9 @@ LLVMDrawersImpl::LLVMDrawersImpl()
|
||||||
CodegenDrawTriangle("TriFillSubsector32_" + std::to_string(i), TriDrawVariant::FillSubsector, (TriBlendMode)i, true);
|
CodegenDrawTriangle("TriFillSubsector32_" + std::to_string(i), TriDrawVariant::FillSubsector, (TriBlendMode)i, true);
|
||||||
}
|
}
|
||||||
CodegenDrawTriangle("TriStencil", TriDrawVariant::Stencil, TriBlendMode::Copy, false);
|
CodegenDrawTriangle("TriStencil", TriDrawVariant::Stencil, TriBlendMode::Copy, false);
|
||||||
|
}
|
||||||
|
|
||||||
mProgram.CreateEE();
|
mProgram.CreateEE(version, targetCPU, !loaded);
|
||||||
|
|
||||||
FillColumn = mProgram.GetProcAddress<void(const DrawColumnArgs *, const WorkerThreadData *)>("FillColumn");
|
FillColumn = mProgram.GetProcAddress<void(const DrawColumnArgs *, const WorkerThreadData *)>("FillColumn");
|
||||||
FillColumnAdd = mProgram.GetProcAddress<void(const DrawColumnArgs *, const WorkerThreadData *)>("FillColumnAdd");
|
FillColumnAdd = mProgram.GetProcAddress<void(const DrawColumnArgs *, const WorkerThreadData *)>("FillColumnAdd");
|
||||||
|
@ -603,12 +614,64 @@ void LLVMProgram::CreateModule()
|
||||||
mModule = std::make_unique<llvm::Module>("render", context());
|
mModule = std::make_unique<llvm::Module>("render", context());
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLVMProgram::CreateEE()
|
bool LLVMProgram::LoadCachedModule(int version, std::string targetCPU)
|
||||||
|
{
|
||||||
|
FString filename = GetDrawerCacheFilename(version, targetCPU.c_str());
|
||||||
|
FILE *file = fopen(filename, "rb");
|
||||||
|
if (!file)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
std::string data;
|
||||||
|
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
int length = ftell(file);
|
||||||
|
fseek(file, 0, SEEK_SET);
|
||||||
|
if (length > 0)
|
||||||
|
{
|
||||||
|
data.resize(length);
|
||||||
|
success = fread(&data[0], length, 1, file) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
if (!success)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto result = llvm::parseBitcodeFile(llvm::MemoryBufferRef(data, filename.GetChars()), *mContext.get());
|
||||||
|
if (!result)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
mModule = std::move(result.get());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLVMProgram::SaveCachedModule(llvm::Module *module, int version, std::string targetCPU)
|
||||||
|
{
|
||||||
|
std::string str;
|
||||||
|
llvm::raw_string_ostream stream(str);
|
||||||
|
llvm::WriteBitcodeToFile(module, stream);
|
||||||
|
std::string data = stream.str();
|
||||||
|
|
||||||
|
FString filename = GetDrawerCacheFilename(version, targetCPU.c_str());
|
||||||
|
FILE *file = fopen(filename, "wb");
|
||||||
|
if (file)
|
||||||
|
{
|
||||||
|
fwrite(data.data(), data.size(), 1, file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FString LLVMProgram::GetDrawerCacheFilename(int version, FString cpu)
|
||||||
|
{
|
||||||
|
FString path = M_GetCachePath(true);
|
||||||
|
FString filename;
|
||||||
|
filename.Format("%s/LLVMDrawers-%d-%s.bc", path.GetChars(), version, cpu.GetChars());
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LLVMProgram::GetTargetCPU()
|
||||||
{
|
{
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
std::string errorstring;
|
|
||||||
|
|
||||||
std::string mcpu = sys::getHostCPUName();
|
std::string mcpu = sys::getHostCPUName();
|
||||||
if (std::string(CPU.CPUString).find("G840") != std::string::npos && mcpu == "sandybridge")
|
if (std::string(CPU.CPUString).find("G840") != std::string::npos && mcpu == "sandybridge")
|
||||||
mcpu = "westmere"; // Pentium G840 is misdetected as a sandy bridge CPU
|
mcpu = "westmere"; // Pentium G840 is misdetected as a sandy bridge CPU
|
||||||
|
@ -618,13 +681,21 @@ void LLVMProgram::CreateEE()
|
||||||
mcpu = llvm_cpu;
|
mcpu = llvm_cpu;
|
||||||
Printf("Overriding LLVM CPU target to %s\n", mcpu.c_str());
|
Printf("Overriding LLVM CPU target to %s\n", mcpu.c_str());
|
||||||
}
|
}
|
||||||
|
return mcpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLVMProgram::CreateEE(int version, std::string targetCPU, bool optimize)
|
||||||
|
{
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
std::string errorstring;
|
||||||
|
|
||||||
llvm::Module *module = mModule.get();
|
llvm::Module *module = mModule.get();
|
||||||
EngineBuilder engineBuilder(std::move(mModule));
|
EngineBuilder engineBuilder(std::move(mModule));
|
||||||
engineBuilder.setErrorStr(&errorstring);
|
engineBuilder.setErrorStr(&errorstring);
|
||||||
engineBuilder.setOptLevel(CodeGenOpt::Aggressive);
|
engineBuilder.setOptLevel(CodeGenOpt::Aggressive);
|
||||||
engineBuilder.setEngineKind(EngineKind::JIT);
|
engineBuilder.setEngineKind(EngineKind::JIT);
|
||||||
engineBuilder.setMCPU(mcpu);
|
engineBuilder.setMCPU(targetCPU);
|
||||||
machine = engineBuilder.selectTarget();
|
machine = engineBuilder.selectTarget();
|
||||||
if (!machine)
|
if (!machine)
|
||||||
I_FatalError("Could not create LLVM target machine");
|
I_FatalError("Could not create LLVM target machine");
|
||||||
|
@ -638,6 +709,10 @@ void LLVMProgram::CreateEE()
|
||||||
Printf("LLVM target triple: %s\n", targetTriple.c_str());
|
Printf("LLVM target triple: %s\n", targetTriple.c_str());
|
||||||
Printf("LLVM target CPU: %s\n", cpuName.c_str());
|
Printf("LLVM target CPU: %s\n", cpuName.c_str());
|
||||||
|
|
||||||
|
if (optimize)
|
||||||
|
{
|
||||||
|
Printf("Optimizing drawers..\n");
|
||||||
|
|
||||||
module->setTargetTriple(targetTriple);
|
module->setTargetTriple(targetTriple);
|
||||||
#if LLVM_VERSION_MAJOR < 3 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 8)
|
#if LLVM_VERSION_MAJOR < 3 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 8)
|
||||||
module->setDataLayout(new DataLayout(*machine->getSubtargetImpl()->getDataLayout()));
|
module->setDataLayout(new DataLayout(*machine->getSubtargetImpl()->getDataLayout()));
|
||||||
|
@ -675,6 +750,11 @@ void LLVMProgram::CreateEE()
|
||||||
// Run module passes:
|
// Run module passes:
|
||||||
PerModulePasses.run(*module);
|
PerModulePasses.run(*module);
|
||||||
|
|
||||||
|
SaveCachedModule(module, version, targetCPU);
|
||||||
|
}
|
||||||
|
|
||||||
|
Printf("Compiling drawers..\n");
|
||||||
|
|
||||||
// Create execution engine and generate machine code
|
// Create execution engine and generate machine code
|
||||||
mEngine.reset(engineBuilder.create(machine));
|
mEngine.reset(engineBuilder.create(machine));
|
||||||
if (!mEngine)
|
if (!mEngine)
|
||||||
|
|
Loading…
Reference in a new issue