i965/blorp: Reduce the size of vertex buffer
[mesa.git] / src / mesa / drivers / dri / i965 / brw_dead_control_flow.cpp
index 03f838dd9ae6ebc0ed89bc42844c882aca12d6d9..114dc6cb21240da5f3982160d27f8a2c151ac9d0 100644 (file)
 /* Look for and eliminate dead control flow:
  *
  *   - if/endif
- *   . else in else/endif
- *   - if/else/endif
+ *   - else in else/endif
+ *   - then in if/else/endif
  */
 bool
-dead_control_flow_eliminate(backend_visitor *v)
+dead_control_flow_eliminate(backend_shader *s)
 {
    bool progress = false;
 
-   foreach_block_safe (block, v->cfg) {
-      bblock_t *if_block = NULL, *else_block = NULL, *endif_block = block;
-      bool found = false;
+   foreach_block_safe (block, s->cfg) {
+      bblock_t *prev_block = block->prev();
 
-      /* ENDIF instructions, by definition, can only be found at the start of
-       * basic blocks.
-       */
-      backend_instruction *endif_inst = endif_block->start();
-      if (endif_inst->opcode != BRW_OPCODE_ENDIF)
+      if (!prev_block)
          continue;
 
-      backend_instruction *if_inst = NULL, *else_inst = NULL;
-      backend_instruction *prev_inst = endif_block->prev()->end();
-      if (prev_inst->opcode == BRW_OPCODE_ELSE) {
-         else_inst = prev_inst;
-         else_block = endif_block->prev();
-         found = true;
+      backend_instruction *const inst = block->start();
+      backend_instruction *const prev_inst = prev_block->end();
 
-         if (else_block->start_ip == else_block->end_ip)
-            prev_inst = else_block->prev()->end();
-      }
+      /* ENDIF instructions, by definition, can only be found at the start of
+       * basic blocks.
+       */
+      if (inst->opcode == BRW_OPCODE_ENDIF &&
+          prev_inst->opcode == BRW_OPCODE_ELSE) {
+         bblock_t *const else_block = prev_block;
+         backend_instruction *const else_inst = prev_inst;
 
-      if (prev_inst->opcode == BRW_OPCODE_IF) {
-         if_inst = prev_inst;
-         if_block = else_block != NULL ? else_block->prev()
-                                       : endif_block->prev();
-         found = true;
-      } else {
-         /* Don't remove the ENDIF if we didn't find a dead IF. */
-         endif_inst = NULL;
-      }
+         else_inst->remove(else_block);
+         progress = true;
+      } else if (inst->opcode == BRW_OPCODE_ENDIF &&
+                 prev_inst->opcode == BRW_OPCODE_IF) {
+         bblock_t *const endif_block = block;
+         bblock_t *const if_block = prev_block;
+         backend_instruction *const endif_inst = inst;
+         backend_instruction *const if_inst = prev_inst;
 
-      if (found) {
          bblock_t *earlier_block = NULL, *later_block = NULL;
 
-         if (if_inst) {
-            if (if_block->start_ip == if_block->end_ip) {
-               earlier_block = if_block->prev();
-            } else {
-               earlier_block = if_block;
-            }
-            if_inst->remove(if_block);
+         if (if_block->start_ip == if_block->end_ip) {
+            earlier_block = if_block->prev();
+         } else {
+            earlier_block = if_block;
          }
+         if_inst->remove(if_block);
 
-         if (else_inst) {
-            else_inst->remove(else_block);
-         }
-
-         if (endif_inst) {
-            if (endif_block->start_ip == endif_block->end_ip) {
-               later_block = endif_block->next();
-            } else {
-               later_block = endif_block;
-            }
-            endif_inst->remove(endif_block);
+         if (endif_block->start_ip == endif_block->end_ip) {
+            later_block = endif_block->next();
+         } else {
+            later_block = endif_block;
          }
+         endif_inst->remove(endif_block);
 
          assert((earlier_block == NULL) == (later_block == NULL));
          if (earlier_block && earlier_block->can_combine_with(later_block)) {
@@ -110,12 +95,25 @@ dead_control_flow_eliminate(backend_visitor *v)
             }
          }
 
+         progress = true;
+      } else if (inst->opcode == BRW_OPCODE_ELSE &&
+                 prev_inst->opcode == BRW_OPCODE_IF) {
+         bblock_t *const else_block = block;
+         backend_instruction *const if_inst = prev_inst;
+         backend_instruction *const else_inst = inst;
+
+         /* Since the else-branch is becoming the new then-branch, the
+          * condition has to be inverted.
+          */
+         if_inst->predicate_inverse = !if_inst->predicate_inverse;
+         else_inst->remove(else_block);
+
          progress = true;
       }
    }
 
    if (progress)
-      v->invalidate_live_intervals();
+      s->invalidate_live_intervals();
 
    return progress;
 }