[Mesa-dev] [PATCH 02/12] spirv: Only emit functions which are actually used
Jason Ekstrand
jason at jlekstrand.net
Thu Oct 19 18:04:04 UTC 2017
Instead of emitting absolutely everything, just emit the few functions
that are actually referenced in some way by the entrypoint. This should
save us quite a bit of time when handed large shader modules containing
many entrypoints.
---
src/compiler/spirv/spirv_to_nir.c | 29 +++++++++++++++++++++--------
src/compiler/spirv/vtn_cfg.c | 2 ++
src/compiler/spirv/vtn_private.h | 3 +++
3 files changed, 26 insertions(+), 8 deletions(-)
diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c
index d22c3dc..e5e12ff 100644
--- a/src/compiler/spirv/spirv_to_nir.c
+++ b/src/compiler/spirv/spirv_to_nir.c
@@ -1394,8 +1394,11 @@ vtn_handle_function_call(struct vtn_builder *b, SpvOp opcode,
const uint32_t *w, unsigned count)
{
struct vtn_type *res_type = vtn_value(b, w[1], vtn_value_type_type)->type;
- struct nir_function *callee =
- vtn_value(b, w[3], vtn_value_type_function)->func->impl->function;
+ struct vtn_function *vtn_callee =
+ vtn_value(b, w[3], vtn_value_type_function)->func;
+ struct nir_function *callee = vtn_callee->impl->function;
+
+ vtn_callee->referenced = true;
nir_call_instr *call = nir_call_instr_create(b->nb.shader, callee);
for (unsigned i = 0; i < call->num_params; i++) {
@@ -3367,12 +3370,22 @@ spirv_to_nir(const uint32_t *words, size_t word_count,
vtn_build_cfg(b, words, word_end);
- foreach_list_typed(struct vtn_function, func, node, &b->functions) {
- b->const_table = _mesa_hash_table_create(b, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
-
- vtn_function_emit(b, func, vtn_handle_body_instruction);
- }
+ assert(b->entry_point->value_type == vtn_value_type_function);
+ b->entry_point->func->referenced = true;
+
+ bool progress;
+ do {
+ progress = false;
+ foreach_list_typed(struct vtn_function, func, node, &b->functions) {
+ if (func->referenced && !func->emitted) {
+ b->const_table = _mesa_hash_table_create(b, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+
+ vtn_function_emit(b, func, vtn_handle_body_instruction);
+ progress = true;
+ }
+ }
+ } while (progress);
assert(b->entry_point->value_type == vtn_value_type_function);
nir_function *entry_point = b->entry_point->func->impl->function;
diff --git a/src/compiler/spirv/vtn_cfg.c b/src/compiler/spirv/vtn_cfg.c
index 13f0221..70bbccb 100644
--- a/src/compiler/spirv/vtn_cfg.c
+++ b/src/compiler/spirv/vtn_cfg.c
@@ -783,4 +783,6 @@ vtn_function_emit(struct vtn_builder *b, struct vtn_function *func,
*/
if (b->has_loop_continue)
nir_repair_ssa_impl(func->impl);
+
+ func->emitted = true;
}
diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h
index 728c1ff..2551e0b 100644
--- a/src/compiler/spirv/vtn_private.h
+++ b/src/compiler/spirv/vtn_private.h
@@ -159,6 +159,9 @@ struct vtn_block {
struct vtn_function {
struct exec_node node;
+ bool referenced;
+ bool emitted;
+
nir_function_impl *impl;
struct vtn_block *start_block;
--
2.5.0.400.gff86faf
More information about the mesa-dev
mailing list