nir: fix opt_if_loop_last_continue()
authorTimothy Arceri <tarceri@itsqueeze.com>
Wed, 20 Mar 2019 11:59:40 +0000 (22:59 +1100)
committerTimothy Arceri <tarceri@itsqueeze.com>
Thu, 21 Mar 2019 22:58:18 +0000 (09:58 +1100)
Rather than skipping code that looked like this:

     loop {
        ...
        if (cond) {
           do_work_1();
           continue;
        } else {
           break;
        }
        do_work_2();
     }

Previously we would turn this into:

     loop {
        ...
        if (cond) {
           do_work_1();
           continue;
        } else {
           do_work_2();
           break;
        }
     }

This was clearly wrong. This change checks for this case and makes
sure we now leave it for nir_opt_dead_cf() to clean up.

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
src/compiler/nir/nir_opt_if.c

index bc128f79f3c92dd9114bf7b8863808f25bd88e0f..4d3183ed151bd1b7bba01553cc218fe493ed7a3d 100644 (file)
@@ -855,7 +855,8 @@ opt_if_loop_last_continue(nir_loop *loop)
    /* If both branches end in a continue do nothing, this should be handled
     * by nir_opt_dead_cf().
     */
-   if (then_ends_in_continue && else_ends_in_continue)
+   if ((then_ends_in_continue || nir_block_ends_in_break(then_block)) &&
+       (else_ends_in_continue || nir_block_ends_in_break(else_block)))
       return false;
 
    if (!then_ends_in_continue && !else_ends_in_continue)
@@ -872,15 +873,10 @@ opt_if_loop_last_continue(nir_loop *loop)
    nir_cf_list tmp;
    nir_cf_extract(&tmp, nir_after_cf_node(if_node),
                         nir_after_block(last_block));
-   if (then_ends_in_continue) {
-      nir_cursor last_blk_cursor = nir_after_cf_list(&nif->else_list);
-      nir_cf_reinsert(&tmp,
-                      nir_after_block_before_jump(last_blk_cursor.block));
-   } else {
-      nir_cursor last_blk_cursor = nir_after_cf_list(&nif->then_list);
-      nir_cf_reinsert(&tmp,
-                      nir_after_block_before_jump(last_blk_cursor.block));
-   }
+   if (then_ends_in_continue)
+      nir_cf_reinsert(&tmp, nir_after_cf_list(&nif->else_list));
+   else
+      nir_cf_reinsert(&tmp, nir_after_cf_list(&nif->then_list));
 
    /* In order to avoid running nir_lower_regs_to_ssa_impl() every time an if
     * opt makes progress we leave nir_opt_trivial_continues() to remove the