Mesa (master): compiler/nir: Add support for lowering stores with nir_lower_instruction
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Tue Jan 26 15:49:21 UTC 2021
Module: Mesa
Branch: master
Commit: 4099cdc97f2a8ecdc9a74e7bf1127886f8980033
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=4099cdc97f2a8ecdc9a74e7bf1127886f8980033
Author: Gert Wollny <gert.wollny at collabora.com>
Date: Wed Dec 9 09:50:11 2020 +0100
compiler/nir: Add support for lowering stores with nir_lower_instruction
The function is very convenient for lowering any type of instruction
that can be easily filtered, but so far instructions that didn't return
a value were siletly ignored.
Fix this by
- not requiring a return value in the instruction
- add a new special return value from the lowering implementation
function to indicated that an instruction that doesn't have a
return value must be removed, and
- don't try to collect and replace uses in this case.
Signed-off-by: Gert Wollny <gert.wollny at collabora.com>
Reviewed-by: Timur Kristóf <timur.kristof at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8177>
---
src/compiler/nir/nir.c | 49 +++++++++++++++++++++++++++----------------------
src/compiler/nir/nir.h | 8 ++++++++
2 files changed, 35 insertions(+), 22 deletions(-)
diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c
index 934b3887365..7f63cc40612 100644
--- a/src/compiler/nir/nir.c
+++ b/src/compiler/nir/nir.c
@@ -2041,31 +2041,30 @@ nir_function_impl_lower_instructions(nir_function_impl *impl,
assert(nir_foreach_dest(instr, dest_is_ssa, NULL));
nir_ssa_def *old_def = nir_instr_ssa_def(instr);
- if (old_def == NULL) {
- iter = nir_after_instr(instr);
- continue;
- }
-
- /* We're about to ask the callback to generate a replacement for instr.
- * Save off the uses from instr's SSA def so we know what uses to
- * rewrite later. If we use nir_ssa_def_rewrite_uses, it fails in the
- * case where the generated replacement code uses the result of instr
- * itself. If we use nir_ssa_def_rewrite_uses_after (which is the
- * normal solution to this problem), it doesn't work well if control-
- * flow is inserted as part of the replacement, doesn't handle cases
- * where the replacement is something consumed by instr, and suffers
- * from performance issues. This is the only way to 100% guarantee
- * that we rewrite the correct set efficiently.
- */
struct list_head old_uses, old_if_uses;
- list_replace(&old_def->uses, &old_uses);
- list_inithead(&old_def->uses);
- list_replace(&old_def->if_uses, &old_if_uses);
- list_inithead(&old_def->if_uses);
+ if (old_def != NULL) {
+ /* We're about to ask the callback to generate a replacement for instr.
+ * Save off the uses from instr's SSA def so we know what uses to
+ * rewrite later. If we use nir_ssa_def_rewrite_uses, it fails in the
+ * case where the generated replacement code uses the result of instr
+ * itself. If we use nir_ssa_def_rewrite_uses_after (which is the
+ * normal solution to this problem), it doesn't work well if control-
+ * flow is inserted as part of the replacement, doesn't handle cases
+ * where the replacement is something consumed by instr, and suffers
+ * from performance issues. This is the only way to 100% guarantee
+ * that we rewrite the correct set efficiently.
+ */
+
+ list_replace(&old_def->uses, &old_uses);
+ list_inithead(&old_def->uses);
+ list_replace(&old_def->if_uses, &old_if_uses);
+ list_inithead(&old_def->if_uses);
+ }
b.cursor = nir_after_instr(instr);
nir_ssa_def *new_def = lower(&b, instr, cb_data);
- if (new_def && new_def != NIR_LOWER_INSTR_PROGRESS) {
+ if (new_def && new_def != NIR_LOWER_INSTR_PROGRESS &&
+ new_def != NIR_LOWER_INSTR_PROGRESS_REPLACE) {
assert(old_def != NULL);
if (new_def->parent_instr->block != instr->block)
preserved = nir_metadata_none;
@@ -2089,7 +2088,13 @@ nir_function_impl_lower_instructions(nir_function_impl *impl,
list_replace(&old_uses, &old_def->uses);
list_replace(&old_if_uses, &old_def->if_uses);
}
- iter = nir_after_instr(instr);
+ if (new_def == NIR_LOWER_INSTR_PROGRESS_REPLACE) {
+ /* Only instructions without a return value can be removed like this */
+ assert(!old_def);
+ iter = nir_instr_remove(instr);
+ progress = true;
+ } else
+ iter = nir_after_instr(instr);
if (new_def == NIR_LOWER_INSTR_PROGRESS)
progress = true;
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index b65882e619c..0326725e1c0 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -4130,6 +4130,14 @@ typedef nir_ssa_def *(*nir_lower_instr_cb)(struct nir_builder *,
*/
#define NIR_LOWER_INSTR_PROGRESS ((nir_ssa_def *)(uintptr_t)1)
+/**
+ * Special return value for nir_lower_instr_cb when some progress occurred
+ * that should remove the current instruction that doesn't create an output
+ * (like a store)
+ */
+
+#define NIR_LOWER_INSTR_PROGRESS_REPLACE ((nir_ssa_def *)(uintptr_t)2)
+
/** Iterate over all the instructions in a nir_function_impl and lower them
* using the provided callbacks
*
More information about the mesa-commit
mailing list