diff options
author | Roland Scheidegger <[email protected]> | 2015-03-27 02:39:59 +0100 |
---|---|---|
committer | Roland Scheidegger <[email protected]> | 2015-03-27 19:25:53 +0100 |
commit | 56076be2ac60f005770516a9ac305e60e6285497 (patch) | |
tree | 1b52258911bece7c5ebd234a8f65a2796a4ba95d /src/gallium/auxiliary/gallivm/lp_bld_init.c | |
parent | 8dad9455ff748c543635b24908566c3b94cb93a9 (diff) |
gallivm: use llvm function calls for texturing instead of inlining
There are issues with inlining everything, most notably llvm will use much
more memory (and be slower) when compiling. Ideally we'd probably use
functions for shader functions too but texture sampling usually is responsible
for quite some IR (it can easily reach 80% of total IR instructions) so this
seems like a good start.
This still generates a different function for all different combinations just
like before, however it is possible llvm is missing some optimization
opportunities - it is believed though such opportunities should be somewhat
rare, but at least for now it can still be switched off (at compile time only).
It should probably make compiled code also smaller because the same function
should be used for different variants in the same module (so for the
opaque/partial or linear/elts variants).
No piglit change (though it does indeed speed up unrealistic tests like
fp-indirections2 by a factor of 30 or so).
Has a small negative performance impact in openarena - I suspect this could
be fixed by running some IPO passes (despite the private linkage, llvm right
now does NO optimization at all wrt anything going past the call, even if
there's just one caller - so things like values stored before the call and then
always written by the function etc. will not be optimized away, nor will dead
arguments (which we mostly shouldn't have) be eliminated, always constant
arguments promoted etc.).
v2: use proper return values instead of pointer function arguments.
llvm supports aggregate return values, which do wonders here eliminating
unnecessary stack variables - everything in fact will be returned in registers
even without any IPO optimizations. It makes the code simpler too.
With this I could not measure a peformance impact in openarena any longer
(though since there's still no constant value propagation etc. into the tex
functions this does not mean it couldn't have a negative impact elsewhere).
v3: fix some minor issues suggested by Jose, and do disassembly (and the
profiling) without hacks.
Reviewed-by: Jose Fonseca <[email protected]>
Diffstat (limited to 'src/gallium/auxiliary/gallivm/lp_bld_init.c')
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_init.c | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.c b/src/gallium/auxiliary/gallivm/lp_bld_init.c index 6133883e149..7b906c27ed5 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_init.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_init.c @@ -113,6 +113,11 @@ create_pass_manager(struct gallivm_state *gallivm) gallivm->passmgr = LLVMCreateFunctionPassManagerForModule(gallivm->module); if (!gallivm->passmgr) return FALSE; + /* + * TODO: some per module pass manager with IPO passes might be helpful - + * the generated texture functions may benefit from inlining if they are + * simple, or constant propagation into them, etc. + */ // Old versions of LLVM get the DataLayout from the pass manager. LLVMAddTargetData(gallivm->target, gallivm->passmgr); @@ -556,6 +561,37 @@ gallivm_compile_module(struct gallivm_state *gallivm) assert(gallivm->engine); ++gallivm->compiled; + + if (gallivm_debug & GALLIVM_DEBUG_ASM) { + LLVMValueRef llvm_func = LLVMGetFirstFunction(gallivm->module); + + while (llvm_func) { + /* + * Need to filter out functions which don't have an implementation, + * such as the intrinsics. May not be sufficient in case of IPO? + * LLVMGetPointerToGlobal() will abort otherwise. + */ + if (!LLVMIsDeclaration(llvm_func)) { + void *func_code = LLVMGetPointerToGlobal(gallivm->engine, llvm_func); + lp_disassemble(llvm_func, func_code); + } + llvm_func = LLVMGetNextFunction(llvm_func); + } + } + +#if defined(PROFILE) + { + LLVMValueRef llvm_func = LLVMGetFirstFunction(gallivm->module); + + while (llvm_func) { + if (!LLVMIsDeclaration(llvm_func)) { + void *func_code = LLVMGetPointerToGlobal(gallivm->engine, llvm_func); + lp_profile(llvm_func, func_code); + } + llvm_func = LLVMGetNextFunction(llvm_func); + } + } +#endif } @@ -574,13 +610,5 @@ gallivm_jit_function(struct gallivm_state *gallivm, assert(code); jit_func = pointer_to_func(code); - if (gallivm_debug & GALLIVM_DEBUG_ASM) { - lp_disassemble(func, code); - } - -#if defined(PROFILE) - lp_profile(func, code); -#endif - return jit_func; } |