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>
Previously, when visiting a variable dereference, loop analysis would
only consider its effect on the innermost enclosing loop. As a
result, when encountering a loop like this:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
...
i = 2;
}
}
it would incorrectly conclude that the outer loop ran three times.
Fixes piglit test "vs-inner-loop-modifies-outer-loop-var.shader_test".
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This function is about to get more complex.
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This gives the compiler the chance to inline and not export class symbols
even in the absence of LTO. Saves about 60kb on disk.
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@.intel.com>
The is_loop_terminator() function was asserting that the following
kind of if statement could never occur:
if (...) { } else { }
(presumably based on the assumption that such an if statement would be
eliminated by previous optimization stages). But that isn't the
case--it's possible that previous optimization stages might simplify
more complex code down to this empty if statement, in which case it
won't be eliminated until the next time through the optimization loop.
So is_loop_terminator() needs to handle it. Fortunately it's easy to
handle--it's not a loop terminator because it does nothing.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=64330
CC: mesa-stable@lists.freedesktop.org
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Previously the loop_state was allocated in the loop_analysis
constructor, but not freed in the (nonexistent) destructor. Moving
the allocation of the loop_state makes this code appear less sketchy.
Either way, there is no actual leak. The loop_state is freed by the
single caller of analyze_loop_variables.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Cc: Dave Airlie <airlied@freedesktop.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=57753
Function calls may have side effects that alter variables used inside
the loop. In the fragment shader, they may even terminate the shader.
This means our analysis about loop-constant or induction variables may
be completely wrong.
In general it's impossible to determine whether they actually do or not
(due to the halting problem), so we'd need to perform conservative
static analysis. For now, it's not worth the complexity: most functions
will be inlined, at which point we can unroll them successfully.
Fixes Piglit tests:
- shaders/glsl-fs-unroll-out-param
- shaders/glsl-fs-unroll-side-effect
NOTE: This is a candidate for release branches.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Since this was talloced off of NULL instead of the compile state, it
was a real leak over the course of the program. Noticed with
valgrind --leak-check=full --show-reachable=yes. We should really
change these passes to generally get the compile context as an argument
so simple mistakes like this stop mattering.
Returning early with visit_continue_with_parent prevented the
then-statements and else-statements of if-statements such as the
following from being processed:
if (some_var) { ... } else { ... }
Fixes piglit test case glsl-fs-loop-nested-if and bugzilla #30030.
The places where constant_expression_value are still used in loop
analysis are places where a new expression tree is created and
constant folding won't have happened. This is used, for example, when
we try to determine the maximal loop iteration count.
Based on review comments by Eric. "...rely on constant folding to
have done its job, instead of going all through the subtree again when
it wasn't a constant."