intel/ir: Fix CFG corruption in opt_predicated_break().
authorFrancisco Jerez <currojerez@riseup.net>
Tue, 23 Jul 2019 23:17:07 +0000 (16:17 -0700)
committerFrancisco Jerez <currojerez@riseup.net>
Thu, 1 Aug 2019 23:56:48 +0000 (16:56 -0700)
Specifically the optimization of a conditional BREAK + WHILE sequence
into a conditional WHILE seems pretty broken.  The list of successors
of "earlier_block" (where the conditional BREAK was found) is emptied
and then re-created with the same edges for no apparent reason.  On
top of that the list of predecessors of the block immediately after
the WHILE loop is emptied, but only one of the original edges will be
added back, which means that potentially several blocks that still
have it on their list of successors won't be on its list of
predecessors anymore, causing all sorts of hilarity due to the
inconsistency in the control flow graph.

The solution is to remove the code that's removing valid edges from
the CFG.  cfg_t::remove_block() will already clean up after itself.
The assert in bblock_t::combine_with() also needs to be removed since
we will be merging a block with multiple children into the first one
of them.

Found the issue on a hardware enabling branch originally, but
apparently somebody reproduced the same problem independently on
master in the meantime.

Fixes: d13bcdb3a9f ("i965/fs: Extend predicated break pass to predicate WHILE.")
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=111009
Cc: jiradet.jd@gmail.com
Cc: Sergii Romantsov <sergii.romantsov@globallogic.com>
Cc: Matt Turner <mattst88@gmail.com>
Cc: mesa-stable@lists.freedesktop.org
Tested-by: Paul Chelombitko <qamonstergl@gmail.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
src/intel/compiler/brw_cfg.cpp
src/intel/compiler/brw_predicated_break.cpp

index 600b428a492d0ab3b05929e48f737e30c8dd8781..6c40889088d4c3a11a872a24d6c53d93669aaaf8 100644 (file)
@@ -128,9 +128,6 @@ void
 bblock_t::combine_with(bblock_t *that)
 {
    assert(this->can_combine_with(that));
-   foreach_list_typed (bblock_link, link, link, &this->children) {
-      assert(link->block == that);
-   }
    foreach_list_typed (bblock_link, link, link, &that->parents) {
       assert(link->block == this);
    }
index 607715dace4e0271ed06cd7aba255af3c9d7fa24..e60052f36084e06c044ad5fcca92c379ce9d0ea5 100644 (file)
@@ -128,14 +128,8 @@ opt_predicated_break(backend_shader *s)
          while_inst->predicate = jump_inst->predicate;
          while_inst->predicate_inverse = !jump_inst->predicate_inverse;
 
-         earlier_block->children.make_empty();
-         earlier_block->add_successor(s->cfg->mem_ctx, while_block);
-
          assert(earlier_block->can_combine_with(while_block));
          earlier_block->combine_with(while_block);
-
-         earlier_block->next()->parents.make_empty();
-         earlier_block->add_successor(s->cfg->mem_ctx, earlier_block->next());
       }
 
       progress = true;