summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBas Nieuwenhuizen <[email protected]>2018-07-15 01:19:17 +0200
committerBas Nieuwenhuizen <[email protected]>2018-07-20 12:09:19 +0200
commit8cacf38f527d42e41441ef8c25d95d4b2f4e8602 (patch)
tree452ba4b392264021e195d8d0a333374e226a7e17 /src
parentce454d02cc4c3d6bd0e69af82933731abaccfebb (diff)
nir: Do not use continue block after removing it.
Reinserting code directly before a jump means the block gets split and merged, removing the original block and replacing it in the process. Hence keeping a pointer to the continue block over a reinsert causes issues. This code changes nir_opt_if to simply look for the new continue block. Reviewed-by: Jason Ekstrand <[email protected]> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=107275 CC: 18.1 <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/compiler/nir/nir_opt_if.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/src/compiler/nir/nir_opt_if.c b/src/compiler/nir/nir_opt_if.c
index a52de120ad6..49ba5de09e9 100644
--- a/src/compiler/nir/nir_opt_if.c
+++ b/src/compiler/nir/nir_opt_if.c
@@ -27,6 +27,26 @@
#include "nir_loop_analyze.h"
/**
+ * Gets the single block that jumps back to the loop header. Already assumes
+ * there is exactly one such block.
+ */
+static nir_block*
+find_continue_block(nir_loop *loop)
+{
+ nir_block *header_block = nir_loop_first_block(loop);
+ nir_block *prev_block =
+ nir_cf_node_as_block(nir_cf_node_prev(&loop->cf_node));
+
+ assert(header_block->predecessors->entries == 2);
+
+ struct set_entry *pred_entry;
+ set_foreach(header_block->predecessors, pred_entry) {
+ if (pred_entry->key != prev_block)
+ return (nir_block*)pred_entry->key;
+ }
+}
+
+/**
* This optimization detects if statements at the tops of loops where the
* condition is a phi node of two constants and moves half of the if to above
* the loop and the other half of the if to the end of the loop. A simple for
@@ -97,12 +117,7 @@ opt_peel_loop_initial_if(nir_loop *loop)
if (header_block->predecessors->entries != 2)
return false;
- nir_block *continue_block = NULL;
- struct set_entry *pred_entry;
- set_foreach(header_block->predecessors, pred_entry) {
- if (pred_entry->key != prev_block)
- continue_block = (void *)pred_entry->key;
- }
+ nir_block *continue_block = find_continue_block(loop);
nir_cf_node *if_node = nir_cf_node_next(&header_block->cf_node);
if (!if_node || if_node->type != nir_cf_node_if)
@@ -193,6 +208,10 @@ opt_peel_loop_initial_if(nir_loop *loop)
nir_cf_reinsert(&tmp, nir_before_cf_node(&loop->cf_node));
nir_cf_reinsert(&header, nir_after_block_before_jump(continue_block));
+
+ /* Get continue block again as the previous reinsert might have removed the block. */
+ continue_block = find_continue_block(loop);
+
nir_cf_extract(&tmp, nir_before_cf_list(continue_list),
nir_after_cf_list(continue_list));
nir_cf_reinsert(&tmp, nir_after_block_before_jump(continue_block));