glsl: Fix handling of function calls inside nested loops.
authorPaul Berry <stereotype441@gmail.com>
Thu, 28 Nov 2013 19:06:43 +0000 (11:06 -0800)
committerPaul Berry <stereotype441@gmail.com>
Mon, 9 Dec 2013 18:54:20 +0000 (10:54 -0800)
Previously, when visiting an ir_call, loop analysis would only mark
the innermost enclosing loop as containing a call.  As a result, when
encountering a loop like this:

    for (i = 0; i < 3; i++) {
      for (int j = 0; j < 3; j++) {
        foo();
      }
    }

it would incorrectly conclude that the outer loop ran three times.
(This is not certain; if foo() modifies i, then the outer loop might
run more or fewer times).

Fixes piglit test "vs-call-in-nested-loop.shader_test".

Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
src/glsl/loop_analysis.cpp

index b423ad4a9c59e699041d92b34e627b08583dbe9c..c7f929590ab1e41497b398fff3c0b03995a6c4f7 100644 (file)
@@ -223,14 +223,14 @@ loop_analysis::visit(ir_loop_jump *ir)
 ir_visitor_status
 loop_analysis::visit_enter(ir_call *ir)
 {
-   /* If we're not somewhere inside a loop, there's nothing to do. */
-   if (this->state.is_empty())
-      return visit_continue;
-
-   loop_variable_state *const ls =
-      (loop_variable_state *) this->state.get_head();
+   /* Mark every loop that we're currently analyzing as containing an ir_call
+    * (even those at outer nesting levels).
+    */
+   foreach_list(node, &this->state) {
+      loop_variable_state *const ls = (loop_variable_state *) node;
+      ls->contains_calls = true;
+   }
 
-   ls->contains_calls = true;
    return visit_continue_with_parent;
 }