Commit Graph

24 Commits

Author SHA1 Message Date
Tapani Pälli ce83a6ec81 glsl: fix unreachable(!"") to unreachable("")
Correct error with commit 151fb1e where assert was renamed
to unreachable without removing ! from string argument.

Signed-off-by: Tapani Pälli <tapani.palli@intel.com>
Reviewed-by: Ilia Mirkin <imirkin@alum.mit.edu>
2015-03-30 08:16:00 +03:00
Brian Paul c16c719647 glsl: replace Elements() with ARRAY_SIZE()
Acked-by: Ilia Mirkin <imirkin@alum.mit.edu>
2015-03-02 08:55:30 -07:00
Dave Airlie 7aa3ffe2c5 glsl: Support double loop control
Signed-off-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Ilia Mirkin <imirkin@alum.mit.edu>
2015-02-19 00:28:34 -05:00
Tapani Pälli 151fb1e808 glsl: support unsigned increment in ir_loop controls
Current version can create ir_expression where operands have
different base type, patch adds support for unsigned type.

Signed-off-by: Tapani Pälli <tapani.palli@intel.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Tested-by: Michel Dänzer <michel.daenzer@amd.com>
https://bugs.freedesktop.org/show_bug.cgi?id=80880
2014-08-07 07:31:49 +03:00
Matt Turner 4d78446d78 glsl: Use typed foreach_in_list instead of foreach_list.
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2014-07-01 08:55:51 -07:00
Paul Berry 088494aa03 glsl/loops: Get rid of lower_bounded_loops and ir_loop::normative_bound.
Now that loop_controls no longer creates normatively bound loops,
there is no need for ir_loop::normative_bound or the
lower_bounded_loops pass.

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2013-12-09 10:55:09 -08:00
Paul Berry 7ea3baa64d glsl/loops: Stop creating normatively bound loops in loop_controls.
Previously, when loop_controls analyzed a loop and found that it had a
fixed bound (known at compile time), it would remove all of the loop
terminators and instead set the loop's normative_bound field to force
the loop to execute the correct number of times.

This made loop unrolling easy, but it had a serious disadvantage.
Since most GPU's don't have a native mechanism for executing a loop a
fixed number of times, in order to implement the normative bound, the
back-ends would have to synthesize a new loop induction variable.  As
a result, many loops wound up having two induction variables instead
of one.  This caused extra register pressure and unnecessary
instructions.

This patch modifies loop_controls so that it doesn't set the loop's
normative_bound anymore.  Instead it leaves one of the terminators in
the loop (the limiting terminator), so the back-end doesn't have to go
to any extra work to ensure the loop terminates at the right time.

This complicates loop unrolling slightly: when deciding whether a loop
can be unrolled, we have to account for the presence of the limiting
terminator.  And when we do unroll the loop, we have to remove the
limiting terminator first.

For an example of how this results in more efficient back end code,
consider the loop:

    for (int i = 0; i < 100; i++) {
      total += i;
    }

Previous to this patch, on i965, this loop would compile down to this
(vec4) native code:

          mov(8)       g4<1>.xD 0D
          mov(8)       g8<1>.xD 0D
    loop:
          cmp.ge.f0(8) null     g8<4;4,1>.xD 100D
    (+f0) if(8)
          break(8)
          endif(8)
          add(8)       g5<1>.xD g5<4;4,1>.xD g4<4;4,1>.xD
          add(8)       g8<1>.xD g8<4;4,1>.xD 1D
          add(8)       g4<1>.xD g4<4;4,1>.xD 1D
          while(8) loop

(notice that both g8 and g4 are loop induction variables; one is used
to terminate the loop, and the other is used to accumulate the total).

After this patch, the same loop compiles to:

          mov(8)       g4<1>.xD 0D
    loop:
          cmp.ge.f0(8) null     g4<4;4,1>.xD 100D
    (+f0) if(8)
          break(8)
          endif(8)
          add(8)       g5<1>.xD g5<4;4,1>.xD g4<4;4,1>.xD
          add(8)       g4<1>.xD g4<4;4,1>.xD 1D
          while(8) loop

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2013-12-09 10:55:06 -08:00
Paul Berry 4d844cfa56 glsl/loops: Get rid of loop_variable_state::max_iterations.
This value is now redundant with
loop_variable_state::limiting_terminator->iterations and
ir_loop::normative_bound.

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2013-12-09 10:55:03 -08:00
Paul Berry ffc29120c4 glsl/loops: Move some analysis from loop_controls to loop_analysis.
Previously, the sole responsibility of loop_analysis was to find all
the variables referenced in the loop that are either loop constant or
induction variables, and find all of the simple if statements that
might terminate the loop.  The remainder of the analysis necessary to
determine how many times a loop executed was performed by
loop_controls.

This patch makes loop_analysis also responsible for determining the
number of iterations after which each loop terminator will terminate
the loop, and for figuring out which terminator will terminate the
loop first (I'm calling this the "limiting terminator").

This will allow loop unrolling to make use of information that was
previously only visible from loop_controls, namely the identity of the
limiting terminator.

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2013-12-09 10:54:56 -08:00
Paul Berry 714e1b331e glsl/loops: Remove unnecessary list walk from loop_control_visitor.
When loop_control_visitor::visit_leave(ir_loop *) is analyzing a loop
terminator that acts on a certain ir_variable, it doesn't need to walk
the list of induction variables to find the loop_variable entry
corresponding to the variable.  It can just look it up in the
loop_variable_state hashtable and verify that the loop_variable entry
represents an induction variable.

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2013-12-09 10:54:49 -08:00
Paul Berry e00b93a1f7 glsl/loops: replace loop controls with a normative bound.
This patch replaces the ir_loop fields "from", "to", "increment",
"counter", and "cmp" with a single integer ("normative_bound") that
serves the same purpose.

I've used the name "normative_bound" to emphasize the fact that the
back-end is required to emit code to prevent the loop from running
more than normative_bound times.  (By contrast, an "informative" bound
would be a bound that is informational only).

Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2013-12-09 10:54:33 -08:00
Paul Berry d6eb4321d0 glsl: Fix inconsistent assumptions about ir_loop::counter.
The compiler back-ends (i965's fs_visitor and brw_visitor,
ir_to_mesa_visitor, and glsl_to_tgsi_visitor) assume that when
ir_loop::counter is non-null, it points to a fresh ir_variable that
should be used as the loop counter (as opposed to an ir_variable that
exists elsewhere in the instruction stream).

However, previous to this patch:

(1) loop_control_visitor did not create a new variable for
    ir_loop::counter; instead it re-used the existing ir_variable.
    This caused the loop counter to be double-incremented (once
    explicitly by the body of the loop, and once implicitly by
    ir_loop::increment).

(2) ir_clone did not clone ir_loop::counter properly, resulting in the
    cloned ir_loop pointing to the source ir_loop's counter.

(3) ir_hierarchical_visitor did not visit ir_loop::counter, resulting
    in the ir_variable being missed by reparenting.

Additionally, most optimization passes (e.g. loop unrolling) assume
that the variable mentioned by ir_loop::counter is not accessed in the
body of the loop (an assumption which (1) violates).

The combination of these factors caused a perfect storm in which the
code worked properly nearly all of the time: for loops that got
unrolled, (1) would introduce a double-increment, but loop unrolling
would fail to notice it (since it assumes that ir_loop::counter is not
accessed in the body of the loop), so it would unroll the loop the
correct number of times.  For loops that didn't get unrolled, (1)
would introduce a double-increment, but then later when the IR was
cloned for linking, (2) would prevent the loop counter from being
cloned properly, so it would look to further analysis stages like an
independent variable (and hence the double-increment would stop
occurring).  At the end of linking, (3) would prevent the loop counter
from being reparented, so it would still belong to the shader object
rather than the linked program object.  Provided that the client
program didn't delete the shader object, the memory would never get
reclaimed, and so the shader would function properly.

However, for loops that didn't get unrolled, if the client program did
delete the shader object, and the memory belonging to the loop counter
got re-used, this could cause a use-after-free bug, leading to a
crash.

This patch fixes loop_control_visitor, ir_clone, and
ir_hierarchical_visitor to treat ir_loop::counter the same way the
back-ends treat it: as a freshly allocated ir_variable that needs to
be visited and cloned independently of other ir_variables.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=72026

Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
2013-11-29 21:46:17 -08:00
Eric Anholt 10ef949424 glsl: Hide many classes local to individual .cpp files in anon namespaces.
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>
2013-09-23 12:45:22 -07:00
Paul Berry 09df6bb96d glsl: Fix loop bounds detection.
When analyzing a loop where the loop condition is expressed in the
non-standard order (e.g. "4 > i" instead of "i < 4"), we were
reversing the condition incorrectly, leading to a loop bound that was
off by 1.

Fixes piglit tests {vs,fs}-loop-bounds-unrolled.shader_test.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
2013-01-08 09:08:53 -08:00
Ian Romanick 497baf4e4a Use C-style system headers in C++ code to avoid issues with std:: namespace 2011-02-21 13:07:29 -08:00
Kenneth Graunke d3073f58c1 Convert everything from the talloc API to the ralloc API. 2011-01-31 10:17:09 -08:00
Aras Pranckevicius d67df5dd9d glsl: fix crash in loop analysis when some controls can't be determined
Fixes loop-07.frag.
2010-11-11 10:49:37 -08:00
Vinson Lee f20f2cc330 glsl: Fix 'format not a string literal and no format arguments' warning.
Fix the following GCC warning.
loop_controls.cpp: In function 'int calculate_iterations(ir_rvalue*, ir_rvalue*, ir_rvalue*, ir_expression_operation)':
loop_controls.cpp:88: warning: format not a string literal and no format arguments
2010-09-15 05:17:57 -07:00
Luca Barbieri 710d41131b loop_controls: fix analysis of already analyzed loops
The loop_controls pass didn't look at the counter values it put in ir_loop
on previous iterations, so while the first iteration worked, subsequent
ones couldn't determine max_iterations.
2010-09-13 13:03:10 -07:00
Ian Romanick f061524f07 glsl2: Use as_constant some places instead of constant_expression_value
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."
2010-09-03 11:55:22 -07:00
Ian Romanick de7c3fe31a glsl2: Add module to perform simple loop unrolling 2010-09-03 11:55:22 -07:00
Ian Romanick 3bcfafcf03 glsl2: Track the number of ir_loop_jump instructions that are in a loop 2010-09-03 11:55:22 -07:00
Ian Romanick 7850ce0a99 glsl2: Eliminate zero-iteration loops 2010-09-03 11:55:21 -07:00
Ian Romanick bfe3fbb38e glsl2: Add module to suss out loop control variables from loop analysis data
This is the next step on the road to loop unrolling
2010-09-03 11:55:21 -07:00