KhronosGroup / SPIRV-Tools

Apache License 2.0
1.04k stars 545 forks source link

Opt: optimized code fails to validate #2391

Closed paulthomson closed 5 years ago

paulthomson commented 5 years ago

Given the following glsl:

// shader.frag
#version 310 es

precision highp float;
precision highp int;

layout(set = 0, binding = 0) uniform buf0 {
  vec2 injectionSwitch;
};

layout(location=0) out vec4 _GLF_color;

bool s()
{
    if(true)
    {
        return false;
    }
}

float h(out vec4 p)
{
   float h = 0.0;
   for(
       int i = 0;
       i < 1;
       i ++
   )
    {
     if(gl_FragCoord.y >= 0.0)
      {
       do {
           h += 1.0;
           if (injectionSwitch.x >= 0.0) {
               break;
           }
       } while(s());
      }

    }
 if(h > 0.0)
  {
   p = vec4(1.0);
  }
  return 1.0;
}

void main()
{
 vec4 p = vec4(1.0);
 h(p);
 _GLF_color = p;
}

I do the following to get optimized and unoptimized spirv, and their disassembly:

glslangValidator -V shader.frag -o shader.frag.spv && \
spirv-val shader.frag.spv && \
spirv-dis shader.frag.spv -o shader.frag.asm && \
spirv-opt -O shader.frag.spv -o shader.frag.opt.spv && \
spirv-dis shader.frag.opt.spv -o shader.frag.opt.asm && \
spirv-val shader.frag.opt.spv

The final command fails:

spirv-val shader.frag.opt.spv 
error: line 60: Loop header 98[%98] is targeted by 0 back-edge blocks but the standard requires exactly one
  %98 = OpLabel

One of the loop headers does not have a back-edge.

I attach the files. shaders.zip

s-perron commented 5 years ago

The problem is that dead branch elimination is simplifying the back edge. There is code that is suppose to stop this from happening, but it assumes the back edge is in the continue block, which is not always the case.