glsl2: Refactor a bit of ir_if_return for the next changes.
authorEric Anholt <eric@anholt.net>
Thu, 29 Jul 2010 19:15:04 +0000 (12:15 -0700)
committerEric Anholt <eric@anholt.net>
Thu, 29 Jul 2010 22:19:37 +0000 (15:19 -0700)
src/glsl/ir_if_return.cpp

index bfb52e7e6844ad674daf5ccb1d34e0ad02f2bb36..8b8ff85d8209548302af39ca7e8e6b358f4ddb44 100644 (file)
@@ -54,11 +54,39 @@ do_if_return(exec_list *instructions)
 {
    ir_if_return_visitor v;
 
-   visit_list_elements(&v, instructions);
+   do {
+      v.progress = false;
+      visit_list_elements(&v, instructions);
+   } while (v.progress);
 
    return v.progress;
 }
 
+/**
+ * Removes any instructions after a (unconditional) return, since they will
+ * never be executed.
+ */
+static void
+truncate_after_instruction(ir_instruction *ir)
+{
+   while (!ir->get_next()->is_tail_sentinel())
+      ((ir_instruction *)ir->get_next())->remove();
+}
+
+/**
+ * Returns an ir_instruction of the first ir_return in the exec_list, or NULL.
+ */
+static ir_return *
+find_return_in_block(exec_list *instructions)
+{
+   foreach_iter(exec_list_iterator, iter, *instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      if (ir->ir_type == ir_type_return)
+        return (ir_return *)ir;
+   }
+
+   return NULL;
+}
 
 ir_visitor_status
 ir_if_return_visitor::visit_enter(ir_if *ir)
@@ -66,32 +94,16 @@ ir_if_return_visitor::visit_enter(ir_if *ir)
    ir_return *then_return = NULL;
    ir_return *else_return = NULL;
 
-   /* Try to find a return statement on both sides. */
-   foreach_iter(exec_list_iterator, then_iter, ir->then_instructions) {
-      ir_instruction *then_ir = (ir_instruction *)then_iter.get();
-      then_return = then_ir->as_return();
-      if (then_return)
-        break;
-   }
-   if (!then_return)
-      return visit_continue;
-
-   foreach_iter(exec_list_iterator, else_iter, ir->else_instructions) {
-      ir_instruction *else_ir = (ir_instruction *)else_iter.get();
-      else_return = else_ir->as_return();
-      if (else_return)
-        break;
-   }
-   if (!else_return)
+   then_return = find_return_in_block(&ir->then_instructions);
+   else_return = find_return_in_block(&ir->else_instructions);
+   if (!then_return || !else_return)
       return visit_continue;
 
    /* Trim off any trailing instructions after the return statements
     * on both sides.
     */
-   while (then_return->get_next()->get_next())
-      ((ir_instruction *)then_return->get_next())->remove();
-   while (else_return->get_next()->get_next())
-      ((ir_instruction *)else_return->get_next())->remove();
+   truncate_after_instruction(then_return);
+   truncate_after_instruction(else_return);
 
    this->progress = true;