opened
caosdoar
username_0
Hello, 

I am using SPIRV-Cross to translate SPIRV code generated from OpenCL (with clspv) to Metal.

I found one of my compute shaders generating wrong data and I narrowed the problem to SPIRV-Cross generating wrong code for one of the loops. I am attaching a simplified version of the OpenCL shader, the SPIRV binary and disassembled files, and the Metal output generated by SPIRV-Cross.

[spirv-cross-bug-for.zip](https://github.com/KhronosGroup/SPIRV-Cross/files/5444227/spirv-cross-bug-for.zip)

Let me explain the problem. This is a piece of code of the simplified shader attached, only contains the loop that SPIRV-Cross is failing to generate:

```OpenCL
float maxh = data[0];
for (int i = 1; i < nbins; ++i)
{
    if (maxh < data[i]) maxh = data[i];
}
```

I am omitting here the SPIRV output generated by CLSPV, but the code seems correct for this simplified version, and indeed works fine on the original/full shader. 

Here is the Metal code generated by SPIRV-Cross for that loop:

```metal
float _75;
for (;;)
{
    _75 = (_70 < _15._m0[_71]) ? _15._m0[_71] : _70;
    if (!(_71 < 35u))
    {
        break;
    }
    else
    {
        _70 = _75;
        _71++;
        break; // Problem!
    }
}
```

It does not match perfectly, as some of the SPIRV instructions are executed as part of the previous loop, that you can find on the full shader. But I think is enough to understand the problem. The "break" on the else block should not be there, or should be a "continue".

After debugging the SPIRV-Cross execution I found for the conditional on that loop [CompilerGLSL::branch](https://github.com/KhronosGroup/SPIRV-Cross/blob/1a95017d114e408657d27301323f20525aca4108/spirv_glsl.cpp#L13241) enters the false block with the same BlockID for the "from" and "to" parameters. But it enters the second condition as "is_break(to)" returns true, so the later test "to_is_continue || from == to" is never checked, and it outputs a "break". I could fix the problem by just switching the order of this two conditions, but I don't know if the order is relevant for other cases.

Please, let me know if I can provide any more information or help in solving this issue.

Regards,
Oscar.
For branch bug: both branches break the loop
issue
created
HansKristian-Work
username_1
Wow, now that's one hell of an edge case, a block being a continue block, loop header AND break target at the same time :v Fortunately the fix is simple.
comment
created
caosdoar
username_0
Wow. That was a quick response and a quick fix.
Thank you!
comment
closed
HansKristian-Work
username_1
issue