KhronosGroup / SPIRV-Tools

Apache License 2.0
1.05k stars 549 forks source link

opt: segfault in spvtools::utils::IntrusiveNodeBase<spvtools::opt::Instruction>::NextNode() _ZNK8spvtools5utils17IntrusiveNodeBaseINS_3opt11InstructionEE8NextNodeEv #2747

Closed paulthomson closed 4 years ago

paulthomson commented 5 years ago

bug_report.zip

Issue found using GraphicsFuzz.

Tool versions:

To reproduce:

glslangValidator -V shader.frag -o shader.frag.spv

spirv-opt shader.frag.spv -o temp.spv --validate-after-all --eliminate-dead-branches --merge-return --eliminate-dead-branches --merge-blocks --inline-entry-points-exhaustive --eliminate-dead-inserts --inline-entry-points-exhaustive --ccp --eliminate-dead-branches --private-to-local --combine-access-chains --eliminate-dead-branches --merge-blocks --eliminate-dead-inserts --simplify-instructions

The following shader files are included in the attached archive, some of which are also shown inline below:

0_glsl/shader.frag:

#version 310 es
precision highp float;

vec3 computePoint()
{
 discard;
 return vec3(1.0);
}
void main()
{
 computePoint();
 if(false)
  {
  }
 if(gl_FragCoord.x < 0.0)
  {
   return;
  }
 computePoint();
}

1_spirv_asm/shader.frag.asm:

; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 7
; Bound: 35
; Schema: 0
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %4 "main" %23
               OpExecutionMode %4 OriginUpperLeft
               OpSource ESSL 310
               OpName %4 "main"
               OpName %9 "computePoint("
               OpName %23 "gl_FragCoord"
               OpDecorate %23 BuiltIn FragCoord
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeVector %6 3
          %8 = OpTypeFunction %7
         %12 = OpConstant %6 1
         %13 = OpConstantComposite %7 %12 %12 %12
         %17 = OpTypeBool
         %18 = OpConstantFalse %17
         %21 = OpTypeVector %6 4
         %22 = OpTypePointer Input %21
         %23 = OpVariable %22 Input
         %24 = OpTypeInt 32 0
         %25 = OpConstant %24 0
         %26 = OpTypePointer Input %6
         %29 = OpConstant %6 0
          %4 = OpFunction %2 None %3
          %5 = OpLabel
         %16 = OpFunctionCall %7 %9
               OpSelectionMerge %20 None
               OpBranchConditional %18 %19 %20
         %19 = OpLabel
               OpBranch %20
         %20 = OpLabel
         %27 = OpAccessChain %26 %23 %25
         %28 = OpLoad %6 %27
         %30 = OpFOrdLessThan %17 %28 %29
               OpSelectionMerge %32 None
               OpBranchConditional %30 %31 %32
         %31 = OpLabel
               OpReturn
         %32 = OpLabel
         %34 = OpFunctionCall %7 %9
               OpReturn
               OpFunctionEnd
          %9 = OpFunction %7 None %8
         %10 = OpLabel
               OpKill
               OpFunctionEnd
paulthomson commented 5 years ago

I ran this on a newer build of spirv-opt and the error changed:

error: line 37: OpLoopMerge must immediately precede either an OpBranch or OpBranchConditional instruction. OpLoopMerge must be the second-to-last instruction in its block.
  OpLoopMerge %35 %38 None

error: line 0: Validation failed after pass inline-entry-points-exhaustive

The following SPIR-V is the issue I think:

         %36 = OpLabel
               OpLoopMerge %35 %38 None
               OpKill

I am not sure if the original issue was fixed (intentionally or otherwise), or is just evading reproduction due to other changes.

s-perron commented 4 years ago

Fixed by #2842 I believe.