Skip to content
This repository has been archived by the owner on Jan 29, 2025. It is now read-only.

unreachable!() hit when running strange code emitted by spirv-opt #939

Closed
khyperia opened this issue Jun 2, 2021 · 1 comment
Closed

Comments

@khyperia
Copy link

khyperia commented Jun 2, 2021

When talking with @jimblandy about naga's expression/statement representation, I wondered how naga handles SPIR-V control flow that does something like a multi-level break.

I remembered that spirv-opt emits a strange code pattern when inlining a function with a return statement nested inside control flow: it wraps the inlined function in a switch (0) { default: { the function's code } }, and any return statement of the inlined function branches to the end of the switch statement. SPIR-V allows skipping over merge blocks (pretty insane if you ask me, but that's how it is), kinda like a multi-level break, so this is valid.

So, I wrote up a GLSL example with a return statement in some control flow in an inlined function, threw it through glslang and spirv-opt, took the spir-v binary and pushed it through naga with my silly wgpu test app, and naga panicked.

thread 'main' panicked at 'internal error: entered unreachable code: Expression [15] is already cached!', C:\Users\khype\.cargo\registry\src\github.com-1ecc6299db9ec823\naga-0.4.2\src\back\spv\writer.rs:2380:9

I'm on Windows, if that's relevant. The GLSL and SPIR-V shader binary can be played with on shader-playground, although I've included both below for convenience. The SPIR-V binary passes spirv-val. (The shader-playground link does have a "download binary" button, though, so you don't have to go through the trouble of assembling it)

#version 460

layout (location = 1) in float thingy;
layout (location = 0) out float fragColor;

float f() {
    if (thingy > 1) {
        if (thingy > 2) {
            return 1;
        }
    }
    return 2;
}

void main()
{
	fragColor = f();
}
Disassembled SPIR-V, click to expand
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 10
; Bound: 56
; Schema: 0
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %main "main" %thingy %fragColor
               OpExecutionMode %main OriginUpperLeft
               OpSource GLSL 460
               OpName %main "main"
               OpName %thingy "thingy"
               OpName %fragColor "fragColor"
               OpDecorate %thingy Location 1
               OpDecorate %fragColor Location 0
       %void = OpTypeVoid
          %3 = OpTypeFunction %void
      %float = OpTypeFloat 32
%_ptr_Input_float = OpTypePointer Input %float
     %thingy = OpVariable %_ptr_Input_float Input
    %float_1 = OpConstant %float 1
       %bool = OpTypeBool
    %float_2 = OpConstant %float 2
%_ptr_Output_float = OpTypePointer Output %float
  %fragColor = OpVariable %_ptr_Output_float Output
       %uint = OpTypeInt 32 0
     %uint_0 = OpConstant %uint 0
       %main = OpFunction %void None %3
          %5 = OpLabel
               OpSelectionMerge %53 None
               OpSwitch %uint_0 %44
         %44 = OpLabel
         %45 = OpLoad %float %thingy
         %46 = OpFOrdGreaterThan %bool %45 %float_1
               OpSelectionMerge %52 None
               OpBranchConditional %46 %47 %52
         %47 = OpLabel
         %49 = OpFOrdGreaterThan %bool %45 %float_2
               OpSelectionMerge %51 None
               OpBranchConditional %49 %50 %51
         %50 = OpLabel
               OpBranch %53
         %51 = OpLabel
               OpBranch %52
         %52 = OpLabel
               OpBranch %53
         %53 = OpLabel
         %55 = OpPhi %float %float_1 %50 %float_2 %52
               OpStore %fragColor %55
               OpReturn
               OpFunctionEnd
@khyperia
Copy link
Author

khyperia commented Jun 2, 2021

shoot, my bad! I was testing on wgpu's most recent release, but it looks like this was fixed in naga's master.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant