Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix structured exit validation #3141

Merged
merged 2 commits into from
Jan 23, 2020
Merged

Conversation

alan-baker
Copy link
Contributor

Fixes #3139

  • If the header of the construct is also a merge block, jump to the
    associated header instead of the immediate dominator
  • new test

@alan-baker alan-baker self-assigned this Jan 16, 2020
Fixes KhronosGroup#3139

* If the header of the construct is also a merge block, jump to the
associated header instead of the immediate dominator
  * prevents spurious failures from unrelated constructs
* new test
Copy link
Contributor

@paulthomson paulthomson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. I think I get it now. The code for checking the exits from a selection:

  • Is happy if the exit is to the merge of the selection
  • Otherwise, it traverses the immediate dominator chain, looking for headers and checking if the exit is to one of the merges. It also tracks whether we have seen a switch, in which case breaking to a loop merge is no longer a valid exit. The test hits this last case incorrectly.

The test's selection construct's header is also a loop's merge block. But actually, I don't think this is the main issue. The main problem is that the immediate dominator of the selection header / loop merge is not the loop header, as you might expect, but the continue target, and this then leads us into the loop construct, instead of working our way through the outer constructs as we probably expect. The immediate dominator is a selection switch header. This does not help validate the exit, so we move on again, but we incorrectly track the fact that we have seen a switch in the outer constructs (but the switch is not actually an outer construct); the switch's merge block unexpectedly does not dominate the selection construct's header, which would otherwise prevent this. When we get to the relevant outer switch, it is too late because it seems like the exit is escaping an inner switch, so validation of the exit fails.

I think the fix only address the first block in the traversal. I believe the same issue could occur at any point in the traversal. Below is a test that I think fails, even with the fix. There may be more issues we could expose via the merge block -> continue target traversal. I wonder if this is the real issue. We are essentially traversing into a construct, which I guess is not what we want when traversing immediate dominators. Perhaps when we encounter a merge block, we should always then move to the associated header? And otherwise, go to the immediate dominator. The check for if we are at a merge block could be the first thing we do in the loop, so the first block in the traversal can simply remain as the header.

Test that I think fails:

; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 8
; Bound: 47
; Schema: 0
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %4 "main"
               OpExecutionMode %4 OriginUpperLeft
               OpSource ESSL 310
               OpName %4 "main"
               OpName %8 "i"
               OpDecorate %8 RelaxedPrecision
               OpDecorate %10 RelaxedPrecision
               OpDecorate %18 RelaxedPrecision
               OpDecorate %20 RelaxedPrecision
               OpDecorate %21 RelaxedPrecision
               OpDecorate %28 RelaxedPrecision
               OpDecorate %29 RelaxedPrecision
               OpDecorate %31 RelaxedPrecision
               OpDecorate %35 RelaxedPrecision
               OpDecorate %40 RelaxedPrecision
               OpDecorate %41 RelaxedPrecision
               OpDecorate %44 RelaxedPrecision
               OpDecorate %45 RelaxedPrecision
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeInt 32 1
          %7 = OpTypePointer Function %6
          %9 = OpConstant %6 0
         %19 = OpConstant %6 1
         %32 = OpConstant %6 100
         %33 = OpTypeBool
         %51 = OpConstantTrue %33
         %39 = OpConstant %6 2
         %43 = OpConstant %6 3
          %4 = OpFunction %2 None %3

          %5 = OpLabel
          %8 = OpVariable %7 Function
               OpStore %8 %9
         %10 = OpLoad %6 %8
               OpSelectionMerge %13 None
               OpSwitch %10 %12 0 %11

            %12 = OpLabel
            %44 = OpLoad %6 %8
            %45 = OpISub %6 %44 %43
                OpStore %8 %45
                OpBranch %13

            %11 = OpLabel
                OpBranch %14

            %14 = OpLabel
                OpLoopMerge %16 %17 None
                OpBranch %15

                %15 = OpLabel
                %18 = OpLoad %6 %8
                %20 = OpIAdd %6 %18 %19
                    OpStore %8 %20
                %21 = OpLoad %6 %8
                    OpSelectionMerge %25 None
                    OpSwitch %21 %24 1 %22 2 %23

                    %24 = OpLabel
                    %28 = OpLoad %6 %8
                    %29 = OpISub %6 %28 %19
                        OpStore %8 %29
                        OpBranch %25

                    %22 = OpLabel
                        OpBranch %17

                    %23 = OpLabel
                        OpBranch %25

                %25 = OpLabel
                    OpBranch %17

                %17 = OpLabel
                %31 = OpLoad %6 %8
                %34 = OpSGreaterThan %33 %31 %32
                    OpBranchConditional %34 %14 %16

            %16 = OpLabel
            %35 = OpLoad %6 %8
            %36 = OpSGreaterThan %33 %35 %32
                OpSelectionMerge %38 None
                OpBranchConditional %36 %37 %38

                %37 = OpLabel
                %40 = OpLoad %6 %8
                %41 = OpISub %6 %40 %39
                    OpStore %8 %41
                    OpSelectionMerge %50 None
                    OpBranchConditional %51 %52 %50

                    %52 = OpLabel
                    OpBranch %13

                
                %50 = OpLabel
                OpBranch %38

            %38 = OpLabel
                OpBranch %12

         %13 = OpLabel
               OpReturn
               OpFunctionEnd

@paulthomson
Copy link
Contributor

Here is another potentially interesting test case that I think still fails:

; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 7
; Bound: 27
; Schema: 0
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %4 "main"
               OpExecutionMode %4 OriginUpperLeft
               OpSource ESSL 310
               OpName %4 "main"
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeInt 32 1
          %7 = OpConstant %6 1
         %15 = OpTypeBool
         %16 = OpConstantTrue %15
         %17 = OpConstant %6 2
          %4 = OpFunction %2 None %3

          %5 = OpLabel
               OpSelectionMerge %9 None
               OpSwitch %7 %9 1 %8

            %8 = OpLabel
                  OpBranch %10

            %10 = OpLabel
                  OpLoopMerge %12 %13 None
                  OpBranch %11

                  %11 = OpLabel
                        OpSelectionMerge %20 None
                        OpSwitch %17 %19 2 %18

                        %19 = OpLabel
                              OpBranch %20

                        %18 = OpLabel
                              OpBranch %13

                  %20 = OpLabel
                        OpBranch %12

                  %13 = OpLabel
                        OpBranchConditional %16 %12 %10

            %12 = OpLabel
                  OpSelectionMerge %24 None
                  OpBranchConditional %16 %23 %24

                  %23 = OpLabel
                        OpBranch %9

            %24 = OpLabel
                  OpBranch %9

          %9 = OpLabel
               OpReturn
               OpFunctionEnd

@alan-baker
Copy link
Contributor Author

Thanks for the example. The first failed and second passed. I think I understand what you're saying. I will change the basic traversal logic to use the same logic as the first block for all transitions. That fixes the first example.

Copy link
Contributor

@paulthomson paulthomson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Yes, I somehow overlooked the fact that my suggestion was exactly what you had already done, except not just for the first block!

@alan-baker alan-baker merged commit 6729c4a into KhronosGroup:master Jan 23, 2020
@alan-baker alan-baker deleted the val-cfg-3139 branch January 23, 2020 23:04
dneto0 pushed a commit to dneto0/SPIRV-Tools that referenced this pull request Sep 14, 2024
Roll third_party/glslang/ 965bd4d..19ec0d2 (4 commits)

KhronosGroup/glslang@965bd4d...19ec0d2

$ git log 965bd4d..19ec0d2 --date=short --no-merges --format='%ad %ae %s'
2020-01-27 cepheus Build: Fix more build warnings caused by PR KhronosGroup#2038.
2020-01-26 cepheus Build warning: Fix KhronosGroup#2062, missing enum value in a switch.
2019-12-24 laddoc Add Tess machine dependent built-in variables initialization for GLES 3.2
2019-10-18 timo.suoranta Fixes for gcc 9 / -Werror=deprecated-copy

Roll third_party/googletest/ 8b4817e3d..10b1902d8 (6 commits)

google/googletest@8b4817e...10b1902

$ git log 8b4817e3d..10b1902d8 --date=short --no-merges --format='%ad %ae %s'
2020-01-21 absl-team Googletest export
2020-01-17 absl-team Googletest export
2020-01-16 absl-team Googletest export
2020-01-15 36923279+ivan1993br Remove exclusion of *-main and*-all targets
2020-01-12 hilmanbeyri Use IsReadableTypeName IsReadableTypeName in OfType function in gmock-matchers_test.cc
2020-01-12 hilmanbeyri fix unit test failure on NoShortCircuitOnFailure and DetectsFlakyShortCircuit when GTEST_HAS_RTTI is 1

Roll third_party/spirv-cross/ f9818f080..68bf0f824 (6 commits)

KhronosGroup/SPIRV-Cross@f9818f0...68bf0f8

$ git log f9818f080..68bf0f824 --date=short --no-merges --format='%ad %ae %s'
2020-01-27 post Compile fix on older compilers.
2020-01-27 post GLSL: Support GL_ARB_enchanced_layouts for XFB.
2020-01-25 cdavis MSL: Move inline uniform blocks to the end of the argument buffer.
2019-12-16 cdavis MSL: Support inline uniform blocks in argument buffers.
2020-01-23 post Make SmallVector noexcept.
2020-01-22 42098783+barath121 Typo at line 324

Roll third_party/spirv-headers/ 204cd13..dc77030 (2 commits)

KhronosGroup/SPIRV-Headers@204cd13...dc77030

$ git log 204cd13..dc77030 --date=short --no-merges --format='%ad %ae %s'
2020-01-20 dneto Fix the license to match LICENSE
2020-01-20 syoussefi Add BUILD.gn

Roll third_party/spirv-tools/ 323a81f..1b34410 (9 commits)

KhronosGroup/SPIRV-Tools@323a81f...1b34410

$ git log 323a81f..1b34410 --date=short --no-merges --format='%ad %ae %s'
2020-01-24 syoussefi Fix chromium build (KhronosGroup#3152)
2020-01-24 dneto Clarify mapping of target env to SPIR-V version (KhronosGroup#3150)
2020-01-24 greg Use dummy switch instead of dummy loop in MergeReturn pass. (KhronosGroup#3151)
2020-01-23 alanbaker Fix structured exit validation (KhronosGroup#3141)
2020-01-23 dneto Add spvParseVulkanEnv (KhronosGroup#3142)
2020-01-23 jaebaek Handle conflict between debug info and existing validation rule (KhronosGroup#3104)
2020-01-23 syoussefi Use spirv-headers' BUILD.gn (KhronosGroup#3148)
2020-01-23 syoussefi Roll external/spirv-headers/ af64a9e..dc77030 (4 commits) (KhronosGroup#3147)
2020-01-21 afdx spirv-fuzz: Refactoring and type-related fixes (KhronosGroup#3144)

Created with:
  roll-dep third_party/effcee third_party/glslang third_party/googletest third_party/re2 third_party/spirv-cross third_party/spirv-headers third_party/spirv-tools
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants