mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-28 05:20:23 +01:00
Via the Coccinelle patch at the end of the commit message, followed by
sed -ie 's/progress = progress | /progress |=/g' $(git grep -l 'progress = prog')
ninja -C ~/mesa/build clang-format
cd ~/mesa/src/compiler/nir && clang-format -i *.c
agxfmt
@@
identifier prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
-return prog;
+return nir_progress(prog, impl, metadata);
@@
expression prog_expr, impl, metadata;
@@
-if (prog_expr) {
-nir_metadata_preserve(impl, metadata);
-return true;
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-return false;
-}
+bool progress = prog_expr;
+return nir_progress(progress, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-nir_metadata_preserve(impl, prog ? (metadata) : nir_metadata_all);
-return prog;
+return nir_progress(prog, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-nir_metadata_preserve(impl, prog ? (metadata) : nir_metadata_all);
+nir_progress(prog, impl, metadata);
@@
expression impl, metadata;
@@
-nir_metadata_preserve(impl, metadata);
-return true;
+return nir_progress(true, impl, metadata);
@@
expression impl;
@@
-nir_metadata_preserve(impl, nir_metadata_all);
-return false;
+return nir_no_progress(impl);
@@
identifier other_prog, prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
-other_prog |= prog;
+other_prog = other_prog | nir_progress(prog, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+nir_progress(prog, impl, metadata);
@@
identifier other_prog, prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-other_prog = true;
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+other_prog = other_prog | nir_progress(prog, impl, metadata);
@@
expression prog_expr, impl, metadata;
identifier prog;
@@
-if (prog_expr) {
-nir_metadata_preserve(impl, metadata);
-prog = true;
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+bool impl_progress = prog_expr;
+prog = prog | nir_progress(impl_progress, impl, metadata);
@@
identifier other_prog, prog;
expression impl, metadata;
@@
-if (prog) {
-other_prog = true;
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+other_prog = other_prog | nir_progress(prog, impl, metadata);
@@
expression prog_expr, impl, metadata;
identifier prog;
@@
-if (prog_expr) {
-prog = true;
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+bool impl_progress = prog_expr;
+prog = prog | nir_progress(impl_progress, impl, metadata);
@@
expression prog_expr, impl, metadata;
@@
-if (prog_expr) {
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+bool impl_progress = prog_expr;
+nir_progress(impl_progress, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-nir_metadata_preserve(impl, metadata);
-prog = true;
+prog = nir_progress(true, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-}
-return prog;
+return nir_progress(prog, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-}
+nir_progress(prog, impl, metadata);
@@
expression impl;
@@
-nir_metadata_preserve(impl, nir_metadata_all);
+nir_no_progress(impl);
@@
expression impl, metadata;
@@
-nir_metadata_preserve(impl, metadata);
+nir_progress(true, impl, metadata);
squashme! sed -ie 's/progress = progress | /progress |=/g' $(git grep -l 'progress = prog')
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Georg Lehmann <dadschoorse@gmail.com>
Acked-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33722>
266 lines
8.2 KiB
C
266 lines
8.2 KiB
C
/*
|
|
* Copyright © 2024 Valve Corporation
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include "nir.h"
|
|
#include "nir_builder.h"
|
|
#include "nir_phi_builder.h"
|
|
|
|
struct call_liveness_entry {
|
|
struct list_head list;
|
|
nir_call_instr *instr;
|
|
const BITSET_WORD *live_set;
|
|
};
|
|
|
|
static bool
|
|
can_remat_instr(nir_instr *instr)
|
|
{
|
|
switch (instr->type) {
|
|
case nir_instr_type_alu:
|
|
case nir_instr_type_load_const:
|
|
case nir_instr_type_undef:
|
|
return true;
|
|
case nir_instr_type_intrinsic:
|
|
switch (nir_instr_as_intrinsic(instr)->intrinsic) {
|
|
case nir_intrinsic_load_ray_launch_id:
|
|
case nir_intrinsic_load_ray_launch_size:
|
|
case nir_intrinsic_vulkan_resource_index:
|
|
case nir_intrinsic_vulkan_resource_reindex:
|
|
case nir_intrinsic_load_vulkan_descriptor:
|
|
case nir_intrinsic_load_push_constant:
|
|
case nir_intrinsic_load_global_constant:
|
|
case nir_intrinsic_load_smem_amd:
|
|
case nir_intrinsic_load_scalar_arg_amd:
|
|
case nir_intrinsic_load_vector_arg_amd:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static void
|
|
remat_ssa_def(nir_builder *b, nir_def *def, struct hash_table *remap_table,
|
|
struct hash_table *phi_value_table,
|
|
struct nir_phi_builder *phi_builder, BITSET_WORD *def_blocks)
|
|
{
|
|
memset(def_blocks, 0, BITSET_WORDS(b->impl->num_blocks) * sizeof(BITSET_WORD));
|
|
BITSET_SET(def_blocks, def->parent_instr->block->index);
|
|
BITSET_SET(def_blocks, nir_cursor_current_block(b->cursor)->index);
|
|
struct nir_phi_builder_value *val =
|
|
nir_phi_builder_add_value(phi_builder, def->num_components,
|
|
def->bit_size, def_blocks);
|
|
_mesa_hash_table_insert(phi_value_table, def, val);
|
|
|
|
nir_instr *clone = nir_instr_clone_deep(b->shader, def->parent_instr,
|
|
remap_table);
|
|
nir_builder_instr_insert(b, clone);
|
|
nir_def *new_def = nir_instr_def(clone);
|
|
|
|
_mesa_hash_table_insert(remap_table, def, new_def);
|
|
if (nir_cursor_current_block(b->cursor)->index !=
|
|
def->parent_instr->block->index)
|
|
nir_phi_builder_value_set_block_def(val, def->parent_instr->block, def);
|
|
nir_phi_builder_value_set_block_def(val, nir_cursor_current_block(b->cursor),
|
|
new_def);
|
|
}
|
|
|
|
struct remat_chain_check_data {
|
|
struct hash_table *remap_table;
|
|
unsigned chain_length;
|
|
};
|
|
|
|
static bool
|
|
can_remat_chain(nir_src *src, void *data)
|
|
{
|
|
struct remat_chain_check_data *check_data = data;
|
|
|
|
if (_mesa_hash_table_search(check_data->remap_table, src->ssa))
|
|
return true;
|
|
|
|
if (!can_remat_instr(src->ssa->parent_instr))
|
|
return false;
|
|
|
|
if (check_data->chain_length++ >= 16)
|
|
return false;
|
|
|
|
return nir_foreach_src(src->ssa->parent_instr, can_remat_chain, check_data);
|
|
}
|
|
|
|
struct remat_chain_data {
|
|
nir_builder *b;
|
|
struct hash_table *remap_table;
|
|
struct hash_table *phi_value_table;
|
|
struct nir_phi_builder *phi_builder;
|
|
BITSET_WORD *def_blocks;
|
|
};
|
|
|
|
static bool
|
|
do_remat_chain(nir_src *src, void *data)
|
|
{
|
|
struct remat_chain_data *remat_data = data;
|
|
|
|
if (_mesa_hash_table_search(remat_data->remap_table, src->ssa))
|
|
return true;
|
|
|
|
nir_foreach_src(src->ssa->parent_instr, do_remat_chain, remat_data);
|
|
|
|
remat_ssa_def(remat_data->b, src->ssa, remat_data->remap_table,
|
|
remat_data->phi_value_table, remat_data->phi_builder,
|
|
remat_data->def_blocks);
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
rewrite_instr_src_from_phi_builder(nir_src *src, void *data)
|
|
{
|
|
struct hash_table *phi_value_table = data;
|
|
|
|
if (nir_src_is_const(*src)) {
|
|
nir_builder b = nir_builder_at(nir_before_instr(nir_src_parent_instr(src)));
|
|
nir_src_rewrite(src, nir_build_imm(&b, src->ssa->num_components,
|
|
src->ssa->bit_size,
|
|
nir_src_as_const_value(*src)));
|
|
return true;
|
|
}
|
|
|
|
struct hash_entry *entry = _mesa_hash_table_search(phi_value_table, src->ssa);
|
|
if (!entry)
|
|
return true;
|
|
|
|
nir_block *block = nir_src_parent_instr(src)->block;
|
|
nir_def *new_def = nir_phi_builder_value_get_block_def(entry->data, block);
|
|
|
|
bool can_rewrite = true;
|
|
if (new_def->parent_instr->block == block && new_def->index != UINT32_MAX)
|
|
can_rewrite =
|
|
!nir_instr_is_before(nir_src_parent_instr(src), new_def->parent_instr);
|
|
|
|
if (can_rewrite)
|
|
nir_src_rewrite(src, new_def);
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
nir_minimize_call_live_states_impl(nir_function_impl *impl)
|
|
{
|
|
nir_metadata_require(impl, nir_metadata_block_index |
|
|
nir_metadata_live_defs |
|
|
nir_metadata_dominance);
|
|
bool progress = false;
|
|
void *mem_ctx = ralloc_context(NULL);
|
|
|
|
struct list_head call_list;
|
|
list_inithead(&call_list);
|
|
unsigned num_defs = impl->ssa_alloc;
|
|
|
|
nir_def **rematerializable =
|
|
rzalloc_array_size(mem_ctx, sizeof(nir_def *), num_defs);
|
|
|
|
nir_foreach_block(block, impl) {
|
|
nir_foreach_instr(instr, block) {
|
|
nir_def *def = nir_instr_def(instr);
|
|
if (def &&
|
|
can_remat_instr(instr)) {
|
|
rematerializable[def->index] = def;
|
|
}
|
|
|
|
if (instr->type != nir_instr_type_call)
|
|
continue;
|
|
nir_call_instr *call = nir_instr_as_call(instr);
|
|
if (!call->indirect_callee.ssa)
|
|
continue;
|
|
|
|
struct call_liveness_entry *entry =
|
|
ralloc_size(mem_ctx, sizeof(struct call_liveness_entry));
|
|
entry->instr = call;
|
|
entry->live_set = nir_get_live_defs(nir_after_instr(instr), mem_ctx);
|
|
list_addtail(&entry->list, &call_list);
|
|
}
|
|
}
|
|
|
|
const unsigned block_words = BITSET_WORDS(impl->num_blocks);
|
|
BITSET_WORD *def_blocks = ralloc_array(mem_ctx, BITSET_WORD, block_words);
|
|
|
|
list_for_each_entry(struct call_liveness_entry, entry, &call_list, list) {
|
|
unsigned i;
|
|
|
|
nir_builder b = nir_builder_at(nir_after_instr(&entry->instr->instr));
|
|
|
|
struct nir_phi_builder *builder = nir_phi_builder_create(impl);
|
|
struct hash_table *phi_value_table =
|
|
_mesa_pointer_hash_table_create(mem_ctx);
|
|
struct hash_table *remap_table =
|
|
_mesa_pointer_hash_table_create(mem_ctx);
|
|
|
|
BITSET_FOREACH_SET(i, entry->live_set, num_defs) {
|
|
if (!rematerializable[i] ||
|
|
_mesa_hash_table_search(remap_table, rematerializable[i]))
|
|
continue;
|
|
|
|
assert(!_mesa_hash_table_search(phi_value_table, rematerializable[i]));
|
|
|
|
struct remat_chain_check_data check_data = {
|
|
.remap_table = remap_table,
|
|
.chain_length = 1,
|
|
};
|
|
|
|
if (!nir_foreach_src(rematerializable[i]->parent_instr,
|
|
can_remat_chain, &check_data))
|
|
continue;
|
|
|
|
struct remat_chain_data remat_data = {
|
|
.b = &b,
|
|
.remap_table = remap_table,
|
|
.phi_value_table = phi_value_table,
|
|
.phi_builder = builder,
|
|
.def_blocks = def_blocks,
|
|
};
|
|
|
|
nir_foreach_src(rematerializable[i]->parent_instr, do_remat_chain,
|
|
&remat_data);
|
|
|
|
remat_ssa_def(&b, rematerializable[i], remap_table, phi_value_table,
|
|
builder, def_blocks);
|
|
progress = true;
|
|
}
|
|
_mesa_hash_table_destroy(remap_table, NULL);
|
|
|
|
nir_foreach_block(block, impl) {
|
|
nir_foreach_instr(instr, block) {
|
|
if (instr->type == nir_instr_type_phi)
|
|
continue;
|
|
|
|
nir_foreach_src(instr, rewrite_instr_src_from_phi_builder,
|
|
phi_value_table);
|
|
}
|
|
}
|
|
|
|
nir_phi_builder_finish(builder);
|
|
_mesa_hash_table_destroy(phi_value_table, NULL);
|
|
}
|
|
|
|
ralloc_free(mem_ctx);
|
|
|
|
nir_progress(true, impl, nir_metadata_block_index | nir_metadata_dominance);
|
|
return progress;
|
|
}
|
|
|
|
/* Tries to rematerialize as many live vars as possible after calls.
|
|
* Note: nir_opt_cse will undo any rematerializations done by this pass,
|
|
* so it shouldn't be run afterward.
|
|
*/
|
|
bool
|
|
nir_minimize_call_live_states(nir_shader *shader)
|
|
{
|
|
bool progress = false;
|
|
|
|
nir_foreach_function_impl(impl, shader) {
|
|
progress |= nir_minimize_call_live_states_impl(impl);
|
|
}
|
|
|
|
return progress;
|
|
}
|