gallivm: move to new pass manager to handle coroutines change.
LLVM 15 ripped out the legacy coroutine passes. This means moving to the new pass manager is the best option to move forward and is long overdue. I've tried to recreate the same set of passes in the new pass mgr as the old, but I expect some tweaking may be needed to confirm this. Acked-by: Kai Wasserbäch <kai@dev.carbon-project.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16289>
This commit is contained in:
@@ -81,12 +81,19 @@
|
||||
#define LLVMInsertBasicBlock ILLEGAL_LLVM_FUNCTION
|
||||
#define LLVMCreateBuilder ILLEGAL_LLVM_FUNCTION
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 8
|
||||
#if LLVM_VERSION_MAJOR >= 15
|
||||
#define GALLIVM_HAVE_CORO 0
|
||||
#define GALLIVM_USE_NEW_PASS 1
|
||||
#elif LLVM_VERSION_MAJOR >= 8
|
||||
#define GALLIVM_HAVE_CORO 1
|
||||
#define GALLIVM_USE_NEW_PASS 0
|
||||
#else
|
||||
#define GALLIVM_HAVE_CORO 0
|
||||
#define GALLIVM_USE_NEW_PASS 0
|
||||
#endif
|
||||
|
||||
#define GALLIVM_COROUTINES (GALLIVM_HAVE_CORO || GALLIVM_USE_NEW_PASS)
|
||||
|
||||
/* LLVM is transitioning to "opaque pointers", and as such deprecates
|
||||
* LLVMBuildGEP, LLVMBuildCall, LLVMBuildLoad, replacing them with
|
||||
* LLVMBuildGEP2, LLVMBuildCall2, LLVMBuildLoad2 respectivelly.
|
||||
|
@@ -44,7 +44,9 @@
|
||||
#include <llvm-c/Transforms/Utils.h>
|
||||
#endif
|
||||
#include <llvm-c/BitWriter.h>
|
||||
#if GALLIVM_HAVE_CORO
|
||||
#if GALLIVM_USE_NEW_PASS == 1
|
||||
#include <llvm-c/Transforms/PassBuilder.h>
|
||||
#elif GALLIVM_HAVE_CORO == 1
|
||||
#if LLVM_VERSION_MAJOR <= 8 && (defined(PIPE_ARCH_AARCH64) || defined (PIPE_ARCH_ARM) || defined(PIPE_ARCH_S390) || defined(PIPE_ARCH_MIPS64))
|
||||
#include <llvm-c/Transforms/IPO.h>
|
||||
#endif
|
||||
@@ -109,6 +111,7 @@ enum LLVM_CodeGenOpt_Level {
|
||||
static boolean
|
||||
create_pass_manager(struct gallivm_state *gallivm)
|
||||
{
|
||||
#if GALLIVM_USE_NEW_PASS == 0
|
||||
assert(!gallivm->passmgr);
|
||||
assert(gallivm->target);
|
||||
|
||||
@@ -116,7 +119,7 @@ create_pass_manager(struct gallivm_state *gallivm)
|
||||
if (!gallivm->passmgr)
|
||||
return FALSE;
|
||||
|
||||
#if GALLIVM_HAVE_CORO
|
||||
#if GALLIVM_HAVE_CORO == 1
|
||||
gallivm->cgpassmgr = LLVMCreatePassManager();
|
||||
#endif
|
||||
/*
|
||||
@@ -133,7 +136,7 @@ create_pass_manager(struct gallivm_state *gallivm)
|
||||
free(td_str);
|
||||
}
|
||||
|
||||
#if GALLIVM_HAVE_CORO
|
||||
#if GALLIVM_HAVE_CORO == 1
|
||||
#if LLVM_VERSION_MAJOR <= 8 && (defined(PIPE_ARCH_AARCH64) || defined (PIPE_ARCH_ARM) || defined(PIPE_ARCH_S390) || defined(PIPE_ARCH_MIPS64))
|
||||
LLVMAddArgumentPromotionPass(gallivm->cgpassmgr);
|
||||
LLVMAddFunctionAttrsPass(gallivm->cgpassmgr);
|
||||
@@ -180,14 +183,13 @@ create_pass_manager(struct gallivm_state *gallivm)
|
||||
*/
|
||||
LLVMAddPromoteMemoryToRegisterPass(gallivm->passmgr);
|
||||
}
|
||||
#if GALLIVM_HAVE_CORO
|
||||
#if GALLIVM_HAVE_CORO == 1
|
||||
LLVMAddCoroCleanupPass(gallivm->passmgr);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free gallivm object's LLVM allocations, but not any generated code
|
||||
* nor the gallivm object itself.
|
||||
@@ -195,14 +197,16 @@ create_pass_manager(struct gallivm_state *gallivm)
|
||||
void
|
||||
gallivm_free_ir(struct gallivm_state *gallivm)
|
||||
{
|
||||
#if GALLIVM_USE_NEW_PASS == 0
|
||||
if (gallivm->passmgr) {
|
||||
LLVMDisposePassManager(gallivm->passmgr);
|
||||
}
|
||||
|
||||
#if GALLIVM_HAVE_CORO
|
||||
#if GALLIVM_HAVE_CORO == 1
|
||||
if (gallivm->cgpassmgr) {
|
||||
LLVMDisposePassManager(gallivm->cgpassmgr);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (gallivm->engine) {
|
||||
@@ -231,8 +235,12 @@ gallivm_free_ir(struct gallivm_state *gallivm)
|
||||
gallivm->target = NULL;
|
||||
gallivm->module = NULL;
|
||||
gallivm->module_name = NULL;
|
||||
#if GALLIVM_USE_NEW_PASS == 0
|
||||
#if GALLIVM_HAVE_CORO == 1
|
||||
gallivm->cgpassmgr = NULL;
|
||||
#endif
|
||||
gallivm->passmgr = NULL;
|
||||
#endif
|
||||
gallivm->context = NULL;
|
||||
gallivm->builder = NULL;
|
||||
gallivm->cache = NULL;
|
||||
@@ -568,7 +576,6 @@ gallivm_verify_function(struct gallivm_state *gallivm,
|
||||
void
|
||||
gallivm_compile_module(struct gallivm_state *gallivm)
|
||||
{
|
||||
LLVMValueRef func;
|
||||
int64_t time_begin = 0;
|
||||
|
||||
assert(!gallivm->compiled);
|
||||
@@ -578,6 +585,13 @@ gallivm_compile_module(struct gallivm_state *gallivm)
|
||||
gallivm->builder = NULL;
|
||||
}
|
||||
|
||||
LLVMSetDataLayout(gallivm->module, "");
|
||||
assert(!gallivm->engine);
|
||||
if (!init_gallivm_engine(gallivm)) {
|
||||
assert(0);
|
||||
}
|
||||
assert(gallivm->engine);
|
||||
|
||||
if (gallivm->cache && gallivm->cache->data_size) {
|
||||
goto skip_cached;
|
||||
}
|
||||
@@ -601,11 +615,33 @@ gallivm_compile_module(struct gallivm_state *gallivm)
|
||||
if (gallivm_debug & GALLIVM_DEBUG_PERF)
|
||||
time_begin = os_time_get();
|
||||
|
||||
#if GALLIVM_HAVE_CORO
|
||||
#if GALLIVM_USE_NEW_PASS == 1
|
||||
char passes[1024];
|
||||
passes[0] = 0;
|
||||
|
||||
/*
|
||||
* there should be some way to combine these two pass runs but I'm not seeing it,
|
||||
* at the time of writing.
|
||||
*/
|
||||
strcpy(passes, "default<O0>");
|
||||
|
||||
LLVMPassBuilderOptionsRef opts = LLVMCreatePassBuilderOptions();
|
||||
LLVMRunPasses(gallivm->module, passes, LLVMGetExecutionEngineTargetMachine(gallivm->engine), opts);
|
||||
|
||||
if (!(gallivm_perf & GALLIVM_PERF_NO_OPT))
|
||||
strcpy(passes, "sroa,early-cse,simplifycfg,reassociate,mem2reg,constprop,instcombine,");
|
||||
else
|
||||
strcpy(passes, "mem2reg");
|
||||
|
||||
LLVMRunPasses(gallivm->module, passes, LLVMGetExecutionEngineTargetMachine(gallivm->engine), opts);
|
||||
LLVMDisposePassBuilderOptions(opts);
|
||||
#else
|
||||
#if GALLIVM_HAVE_CORO == 1
|
||||
LLVMRunPassManager(gallivm->cgpassmgr, gallivm->module);
|
||||
#endif
|
||||
/* Run optimization passes */
|
||||
LLVMInitializeFunctionPassManager(gallivm->passmgr);
|
||||
LLVMValueRef func;
|
||||
func = LLVMGetFirstFunction(gallivm->module);
|
||||
while (func) {
|
||||
if (0) {
|
||||
@@ -623,7 +659,7 @@ gallivm_compile_module(struct gallivm_state *gallivm)
|
||||
func = LLVMGetNextFunction(func);
|
||||
}
|
||||
LLVMFinalizeFunctionPassManager(gallivm->passmgr);
|
||||
|
||||
#endif
|
||||
if (gallivm_debug & GALLIVM_DEBUG_PERF) {
|
||||
int64_t time_end = os_time_get();
|
||||
int time_msec = (int)((time_end - time_begin) / 1000);
|
||||
@@ -650,12 +686,6 @@ gallivm_compile_module(struct gallivm_state *gallivm)
|
||||
* lp_build_create_jit_compiler_for_module()
|
||||
*/
|
||||
skip_cached:
|
||||
LLVMSetDataLayout(gallivm->module, "");
|
||||
assert(!gallivm->engine);
|
||||
if (!init_gallivm_engine(gallivm)) {
|
||||
assert(0);
|
||||
}
|
||||
assert(gallivm->engine);
|
||||
|
||||
++gallivm->compiled;
|
||||
|
||||
|
@@ -46,8 +46,12 @@ struct gallivm_state
|
||||
LLVMModuleRef module;
|
||||
LLVMExecutionEngineRef engine;
|
||||
LLVMTargetDataRef target;
|
||||
#if GALLIVM_USE_NEW_PASS == 0
|
||||
LLVMPassManagerRef passmgr;
|
||||
#if GALLIVM_HAVE_CORO == 1
|
||||
LLVMPassManagerRef cgpassmgr;
|
||||
#endif
|
||||
#endif
|
||||
LLVMContextRef context;
|
||||
LLVMBuilderRef builder;
|
||||
LLVMMCJITMemoryManagerRef memorymgr;
|
||||
|
@@ -215,7 +215,7 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
|
||||
return lscreen->use_tgsi ? 330 : 450;
|
||||
}
|
||||
case PIPE_CAP_COMPUTE:
|
||||
return GALLIVM_HAVE_CORO;
|
||||
return GALLIVM_COROUTINES;
|
||||
case PIPE_CAP_USER_VERTEX_BUFFERS:
|
||||
return 1;
|
||||
case PIPE_CAP_TGSI_TEXCOORD:
|
||||
@@ -394,7 +394,7 @@ llvmpipe_get_shader_param(struct pipe_screen *screen,
|
||||
case PIPE_SHADER_TESS_CTRL:
|
||||
case PIPE_SHADER_TESS_EVAL:
|
||||
/* Tessellation shader needs llvm coroutines support */
|
||||
if (!GALLIVM_HAVE_CORO || lscreen->use_tgsi)
|
||||
if (!GALLIVM_COROUTINES || lscreen->use_tgsi)
|
||||
return 0;
|
||||
FALLTHROUGH;
|
||||
case PIPE_SHADER_VERTEX:
|
||||
|
Reference in New Issue
Block a user