<div dir="ltr">This extremely slow compilation is not actually an infinite loop.<br>But the compile time does increase with every unrolled loop step in the shader.<br>The time to complete is 2^N, where N is the number of loop iterations.<br><br>The call to<br> (*rvalue)->accept(this);<br>in ir_constant_folding_visitor::handle_rvalue is key to this.<br>Dropping that call for the case when rvalue is not a constant makes compilation<br>finish very quickly.  And for at least this shader it produces exactly the<br>same results.  Constant folding is done very effectively for the y and z channels.<br><br>But the x channel still produces a series of adds of constants instead of one add with the sum.<br>That is a separate issue that could still be investigated.<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Sep 11, 2014 at 1:53 PM, Mike Stroyan <span dir="ltr"><<a href="mailto:mike@lunarg.com" target="_blank">mike@lunarg.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div><div><div>I have looked at this problem quite a bit but never got to the bottom of it.<br>This problem really started to show with commit 857f3a6 - "glsl: Ignore loop-too-large heuristic if there's bad variable indexing."<br>That commit makes many more loops unroll.<br>Here is another example piglit shader_runner test that shows the problem.<br>Changing the value of LOOP_COUNT and running this with "time shader_runner -auto"<br>shows that the compile time doubles each time the loop count is incremented by one.<br></div><div>Large values may seem to take forever.  But they do eventually finish.<br></div>Loop counts over 32 will still prevent unrolling and avoid the slow compile.<br><br></div>A key part of the problem is the assignment to "col.rgb" in your shader or  "tmpvar_3.xyz" in this shader.<br></div>The operation on only some channels results in splitting the vec4 into one temporary per channel.<br>This comment from src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp is telling.<br> 27│  * If a vector is only ever referenced by its components, then<br> 28│  * split those components out to individual variables so they can be<br> 29│  * handled normally by other optimization passes.<br><br>brw_do_vector_splitting creates the flattening_tmp_y and flattening_tmp_z temporaries.<br></div>Operations on one of the channels are optimized quickly.<br></div>But the other two channels are handled badly.<br>The operations on the first channel prevent the same simplification of the expressions for the other two channels.<br><br>Changing ir_vector_splitting_visitor::visit_leave to use "writemask = 1 << i;" instead of "writemask = 1;"<br>in the "if (lhs)" case makes the y and z channels get handled like the x channel.<br>That results in something like<br>      (assign  (y) (var_ref flattening_tmp_y)  (expression float * (swiz y (var_ref texture2D_retval) )(var_ref channel_expressions@8114) ) )<br>It is very fast to compile, but produces bad code that hangs the GPU.<br>It is putting the y channel float value into a non-existent "y" channel of a simple float temporary, then later reading the real x channel.<br><div><div><div><div><div><br>[require]<br>GLSL >= 1.10<br><br>[vertex shader]<br>#version 120<br>attribute vec2 Tex0;<br>attribute vec3 Position;<br>void main ()<br>{<br>  vec4 inPos_1;<br>  inPos_1.xy = Position.xy;<br>  inPos_1.z = 1.00000;<br>  inPos_1.w = 1.00000;<br>  gl_Position = inPos_1;<br>  vec4 tmpvar_2;<br>  <a href="http://tmpvar_2.zw" target="_blank">tmpvar_2.zw</a> = vec2(0.00000, 0.00000);<br>  tmpvar_2.xy = Tex0;<br>  gl_TexCoord[0] = tmpvar_2;<br>}<br><br>[fragment shader]<br>#version 120<br>#define LOOP_COUNT 25<br>uniform sampler2D u_sampler;<br>void main ()<br>{<br>  vec2 tmpvar_1;<br>  tmpvar_1 = gl_TexCoord[0].xy;<br>  vec4 tmpvar_3;<br>  tmpvar_3 = vec4(0.00000, 0.00000, 0.00000, 1.00000);<br>  float weighting_5[LOOP_COUNT];<br>  for (int i = 0; i < LOOP_COUNT; i++) {<br>    float tmpvar_10;<br>    tmpvar_10 = ((float(int(abs ((float(i) - 15.0))))) / 15.0000);<br>    float tmpvar_11;<br>    tmpvar_11 = exp ((-(tmpvar_10) * tmpvar_10));<br>    weighting_5[i] = tmpvar_11;<br>  };<br>  for (int k = 0; k < LOOP_COUNT; k++) {<br>    tmpvar_3.xyz += (texture2D (u_sampler, tmpvar_1).xyz * weighting_5[k]);<br>  };<br>  gl_FragData[0] = tmpvar_3;<br>}<br><br>[test]<br>draw rect -1 -1 2 2<br>probe rgb 1 1 0.0 0.0 0.0<br><br></div></div></div></div></div></div><div class="gmail_extra"><div><div class="h5"><br><div class="gmail_quote">On Thu, Sep 11, 2014 at 2:02 AM, Iago Toral Quiroga <span dir="ltr"><<a href="mailto:itoral@igalia.com" target="_blank">itoral@igalia.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
I have been looking into this bug:<br>
<br>
Compiling of shader gets stuck in infinite loop<br>
<a href="https://bugs.freedesktop.org/show_bug.cgi?id=78468" target="_blank">https://bugs.freedesktop.org/show_bug.cgi?id=78468</a><br>
<br>
Although this occurs at link time when the Intel driver has run some of<br>
its specific lowering passes, it looks like the problem could hit other<br>
drivers if the right conditions are met, as the actual problem happens<br>
inside common optimization passes.<br>
<br>
I reproduced the problem with a very simple shader like this:<br>
<br>
uniform sampler2D tex;<br>
out vec4 FragColor;<br>
void main()<br>
{<br>
   vec4 col = texture(tex, vec2(0, 0));<br>
   for (int i=0; i<30; i++)<br>
      col += vec4(0.1, 0.1, 0.1, 0.1);<br>
   col = vec4(col.rgb / 2.0, col.a);<br>
   FragColor = col;<br>
}<br>
<br>
and for this shader, I traced the problem down to the fact that<br>
do_tree_grafting() is generating instructions like this:<br>
<br>
(assign  (x) (var_ref flattening_tmp_y@116)  (expression float * (swiz x<br>
(expression float + (swiz x (expression float + (swiz x (expression<br>
float + (swiz x (expression float + (swiz x (expression float + (swiz x<br>
(expression float + (swiz x (expression float + (swiz x (expression<br>
float + (swiz x (expression float + (swiz x (expression float + (swiz x<br>
(expression float + (swiz x (expression float + (swiz x (expression<br>
float + (swiz x (expression float + (swiz x (expression float + (swiz x<br>
(expression float + (swiz x (expression float + (swiz x (expression<br>
float + (swiz x (expression float + (swiz x (expression float + (swiz x<br>
(expression float + (swiz x (expression float + (swiz x (expression<br>
float + (swiz x (expression float + (swiz x (expression float + (swiz x<br>
(expression float + (swiz x (expression float + (swiz x (expression<br>
float + (swiz x (expression float + (var_ref col_y) (constant float<br>
(0.100000)) ) )(constant float (0.100000)) ) )(constant float<br>
(0.100000)) ) )(constant float (0.100000)) ) )(constant float<br>
(0.100000)) ) )(constant float (0.100000)) ) )(constant float<br>
(0.100000)) ) )(constant float (0.100000)) ) )(constant float<br>
(0.100000)) ) )(constant float (0.100000)) ) )(constant float<br>
(0.100000)) ) )(constant float (0.100000)) ) )(constant float<br>
(0.100000)) ) )(constant float (0.100000)) ) )(constant float<br>
(0.100000)) ) )(constant float (0.100000)) ) )(constant float<br>
(0.100000)) ) )(constant float (0.100000)) ) )(constant float<br>
(0.100000)) ) )(constant float (0.100000)) ) )(constant float<br>
(0.100000)) ) )(constant float (0.100000)) ) )(constant float<br>
(0.100000)) ) )(constant float (0.100000)) ) )(constant float<br>
(0.100000)) ) )(constant float (0.100000)) ) )(constant float<br>
(0.100000)) ) )(constant float (0.100000)) ) )(constant float<br>
(0.100000)) ) )(constant float (0.500000)) ) )<br>
<br>
And when we feed these to do_constant_folding() it takes forever to<br>
finish. For this shader in particular, removing the tree grafting pass<br>
from do_common_optimization eliminates the problem.<br>
<br>
Notice that small, seemingly irrelevant changes to the shader code, can<br>
make it so that this never happens. For example, if we initialize 'col'<br>
to something like vec4(0,0,0,0) instead of using the texture function,<br>
or we remove the division by 2.0 in the last assignment to 'col', these<br>
instructions are never produced and the shader compiles okay.<br>
<br>
The number of iterations in the loop is also important, if we have too<br>
many we do not unroll the loop and the problem never happens, if we have<br>
too few, rather than generating a super large tree of expressions like<br>
above, we generate something like this and the problem, again, does not<br>
happen: (notice how it adds 0.1 nine times to make 0.9 rather than<br>
chaining 9 add expressions for 10 iterations of the loop):<br>
<br>
(assign  (x) (var_ref flattening_tmp_y)  (expression float * (expression<br>
float + (constant float (0.900000)) (var_ref col_y) ) (constant float<br>
(0.500000)) ) )<br>
<br>
So it seems that whether we generate a huge chunk of expressions or not<br>
is subject to a number of factors, but when the right conditions are met<br>
we can generate code that can stall compilation forever.<br>
<br>
Reading what tree grafting is supposed to do, this does not seem to be<br>
an unexpected result though, so I wonder what would be the right way to<br>
fix this. It would look like we would want to do whatever we are doing<br>
when we only have a few iterations in the loop, but I don't know why we<br>
generate different code in that case and I am not familiar enough with<br>
all the optimization and lowering passes to assess what would make sense<br>
to do here... so, any suggestions?<br>
<br>
Iago<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank">mesa-dev@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev" target="_blank">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</blockquote></div><br><br clear="all"><br></div></div><span class="HOEnZb"><font color="#888888">-- <br><br> Mike Stroyan - Software Architect<br> LunarG, Inc.  - The Graphics Experts<br> Cell:  <a href="tel:%28970%29%20219-7905" value="+19702197905" target="_blank">(970) 219-7905</a><br> Email: Mike@LunarG.com<br> Website: <a href="http://www.lunarg.com" target="_blank">http://www.lunarg.com</a>
</font></span></div>
</blockquote></div><br><br clear="all"><br>-- <br><br> Mike Stroyan - Software Architect<br> LunarG, Inc.  - The Graphics Experts<br> Cell:  (970) 219-7905<br> Email: Mike@LunarG.com<br> Website: <a href="http://www.lunarg.com">http://www.lunarg.com</a>
</div>