summaryrefslogtreecommitdiffstats
path: root/src/compiler/nir
diff options
context:
space:
mode:
authorJason Ekstrand <jason.ekstrand@intel.com>2016-08-10 14:34:49 -0700
committerJason Ekstrand <jason.ekstrand@intel.com>2016-09-08 20:53:01 -0700
commit88a2a2e05302179c59e257533ed77d2d0a6a5021 (patch)
tree7b552b25b277a2ee80e2aafdbd34477946610b96 /src/compiler/nir
parent99ff4b3eb21ccc5df670e4dc62073cee96d07f23 (diff)
downloadexternal_mesa3d-88a2a2e05302179c59e257533ed77d2d0a6a5021.zip
external_mesa3d-88a2a2e05302179c59e257533ed77d2d0a6a5021.tar.gz
external_mesa3d-88a2a2e05302179c59e257533ed77d2d0a6a5021.tar.bz2
nir/gcm: Add global value numbering support
Unlike the current CSE pass, global value numbering is capable of detecting common values even if one does not dominate the other. For instance, in you have if (...) { ssa_1 = ssa_0 + 7; /* use ssa_1 */ } else { ssa_2 = ssa_0 + 7; /* use ssa_2 */ } Global value numbering doesn't care about dominance relationships so it figures out that ssa_1 and ssa_2 are the same and converts this to if (...) { ssa_1 = ssa_0 + 7; /* use ssa_1 */ } else { /* use ssa_1 */ } Obviously, we just broke SSA form which is bad. Global code motion, however, will repair this for us by turning this into ssa_1 = ssa_0 + 7; if (...) { /* use ssa_1 */ } else { /* use ssa_1 */ } This intended to eventually mostly replace CSE. However, conventional CSE may still be useful because it's less of a scorched-earth approach and doesn't require GCM. This makes it a bit more appropriate for use as a clean-up in a late optimization run. Signed-off-by: Jason Ekstrand <jason@jlekstrand.net> Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Diffstat (limited to 'src/compiler/nir')
-rw-r--r--src/compiler/nir/nir.h2
-rw-r--r--src/compiler/nir/nir_opt_gcm.c29
2 files changed, 25 insertions, 6 deletions
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index c1cf940..ff7c422 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -2587,7 +2587,7 @@ bool nir_opt_dce(nir_shader *shader);
bool nir_opt_dead_cf(nir_shader *shader);
-void nir_opt_gcm(nir_shader *shader);
+bool nir_opt_gcm(nir_shader *shader, bool value_number);
bool nir_opt_peephole_select(nir_shader *shader);
diff --git a/src/compiler/nir/nir_opt_gcm.c b/src/compiler/nir/nir_opt_gcm.c
index 02a9348..77eb8e6 100644
--- a/src/compiler/nir/nir_opt_gcm.c
+++ b/src/compiler/nir/nir_opt_gcm.c
@@ -26,6 +26,7 @@
*/
#include "nir.h"
+#include "nir_instr_set.h"
/*
* Implements Global Code Motion. A description of GCM can be found in
@@ -451,8 +452,8 @@ gcm_place_instr(nir_instr *instr, struct gcm_state *state)
block_info->last_instr = instr;
}
-static void
-opt_gcm_impl(nir_function_impl *impl)
+static bool
+opt_gcm_impl(nir_function_impl *impl, bool value_number)
{
struct gcm_state state;
@@ -470,6 +471,18 @@ opt_gcm_impl(nir_function_impl *impl)
gcm_pin_instructions_block(block, &state);
}
+ bool progress = false;
+ if (value_number) {
+ struct set *gvn_set = nir_instr_set_create(NULL);
+ foreach_list_typed_safe(nir_instr, instr, node, &state.instrs) {
+ if (nir_instr_set_add_or_rewrite(gvn_set, instr)) {
+ nir_instr_remove(instr);
+ progress = true;
+ }
+ }
+ nir_instr_set_destroy(gvn_set);
+ }
+
foreach_list_typed(nir_instr, instr, node, &state.instrs)
gcm_schedule_early_instr(instr, &state);
@@ -486,13 +499,19 @@ opt_gcm_impl(nir_function_impl *impl)
nir_metadata_preserve(impl, nir_metadata_block_index |
nir_metadata_dominance);
+
+ return progress;
}
-void
-nir_opt_gcm(nir_shader *shader)
+bool
+nir_opt_gcm(nir_shader *shader, bool value_number)
{
+ bool progress = false;
+
nir_foreach_function(function, shader) {
if (function->impl)
- opt_gcm_impl(function->impl);
+ progress |= opt_gcm_impl(function->impl, value_number);
}
+
+ return progress;
}