summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2017-10-19 10:11:22 -0700
committerJason Ekstrand <[email protected]>2017-12-02 08:07:35 -0800
commit6bd876dcaa4403b30eedd5ebe66bfadcef1f1a0c (patch)
tree769f3abfb15b350a4e878d01af9a243a6f2e2ffa
parentf5aad36d2e5bd7d699cd6bbbfc8c9866c815f52e (diff)
spirv: Only emit functions which are actually used
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. Reviewed-by: Kenneth Graunke <[email protected]> Reviewed-by: Kristian H. Kristensen <[email protected]>
-rw-r--r--src/compiler/spirv/spirv_to_nir.c29
-rw-r--r--src/compiler/spirv/vtn_cfg.c2
-rw-r--r--src/compiler/spirv/vtn_private.h3
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 c58cf5cbfdf..2c4f5b0c93e 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++) {
@@ -3366,12 +3369,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 13f02217710..70bbccb7cdd 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 173a7b3d7c7..751f5011b7d 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;