Skip to content

[SPIRV] Don't lower switch statements to OpSwitch #112056

@llvm-beanz

Description

@llvm-beanz

Description
OpSwitch even as defined with SPV_KHR_maximal_reconvergence, doesn't require converging on switch cases that have fall through.

The only way to get SPIR-V to implement switch statements that converge correctly is with OpBranch instead.

Steps to Reproduce

Given the following HLSL:

RWBuffer<int> value;

[numthreads(4, 1, 1)]
void main(uint3 threadID : SV_DispatchThreadID) {
  uint sum = 0;
  switch (value[threadID.x]) {
    case 0:
      sum += WaveActiveSum(1);
    default:
      sum += WaveActiveSum(10);
      break;
  }
  value[threadID.x] = sum;
}

CE

If given the input [ 0, 0, 1, 2], the computed output should be [ 42, 42, 40, 40 ].

Actual Behavior

Even with the KHR maximal reconvergence extension the OpSwitch is not guaranteed to converge the tangles between case 0 and the default case.

However, if instead these were generated as a chain of OpBranch statements, the control flow would converge at each new OpBranch, which would result in the correct tangle grouping.

The HLSL example above does not compile in Clang today due to missing features, a Clang example that is closer to compiling is https://godbolt.org/z/nbhbd8fdK.

Any switch with fallthrough cases that have behavior dependent on participating lanes converging will be undefined behavior if the SPIRV OpSwitch instruction is used, so we should just not generate it ever for HLSL.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions