Skip to content

[spirv-opt] OpLoads are not de-duplicated for Images #6414

@alister-chowdhury

Description

@alister-chowdhury

In a similar vein to #6412

Buffer<float>    in_data;
RWBuffer<float>  data_out;

[numthreads(1, 1, 1)]
void test_0(uint index : SV_DispatchThreadID)
{
    data_out[0] = in_data[0];
    data_out[1] = in_data[0];
}

Becomes:

; SPIR-V
; Version: 1.0
; Generator: Google spiregg; 0
; Bound: 24
; Schema: 0
               OpCapability Shader
               OpCapability SampledBuffer
               OpCapability ImageBuffer
               OpMemoryModel Logical GLSL450
               OpEntryPoint GLCompute %1 "test_0"
               OpExecutionMode %1 LocalSize 1 1 1
               OpDecorate %3 DescriptorSet 0
               OpDecorate %3 Binding 0
               OpDecorate %5 DescriptorSet 0
               OpDecorate %5 Binding 1
       %uint = OpTypeInt 32 0
     %uint_0 = OpConstant %uint 0
     %uint_1 = OpConstant %uint 1
      %float = OpTypeFloat 32
          %2 = OpTypeImage %float Buffer 2 0 0 1 R32f
%_ptr_UniformConstant_2 = OpTypePointer UniformConstant %2
          %4 = OpTypeImage %float Buffer 2 0 0 2 R32f
%_ptr_UniformConstant_4 = OpTypePointer UniformConstant %4
       %void = OpTypeVoid
         %13 = OpTypeFunction %void
    %v4float = OpTypeVector %float 4
          %3 = OpVariable %_ptr_UniformConstant_2 UniformConstant
          %5 = OpVariable %_ptr_UniformConstant_4 UniformConstant
          %1 = OpFunction %void None %13
         %15 = OpLabel
         %16 = OpLoad %2 %3
         %17 = OpImageFetch %v4float %16 %uint_0 None
         %18 = OpCompositeExtract %float %17 0
         %19 = OpLoad %4 %5
               OpImageWrite %19 %uint_0 %18 None
         %20 = OpLoad %2 %3
         %21 = OpImageFetch %v4float %20 %uint_0 None
         %22 = OpCompositeExtract %float %21 0
         %23 = OpLoad %4 %5
               OpImageWrite %23 %uint_1 %22 None
               OpReturn
               OpFunctionEnd

Has:

         %19 = OpLoad %4 %5
         %20 = OpLoad %2 %3

Despite:

          %2 = OpTypeImage %float Buffer 2 0 0 1 R32f

In ValueNumberTable::IsReadOnlyVariable, sampled images are handled:

  if (address_def->opcode() == spv::Op::OpLoad) {
    const analysis::Type* address_type =
        context()->get_type_mgr()->GetType(address_def->type_id());
    if (address_type->AsSampledImage() != nullptr) {
      const auto* image_type =
          address_type->AsSampledImage()->image_type()->AsImage();
      return image_type->sampled() == 1;
    }
  }

But it looks like regular images are not.

Additionally, the load itself is forced unique by:

  // A load that yields an image, sampler, or sampled image must remain in
  // the same basic block.  So assign it its own value number.
  if (inst->IsLoad()) {
    switch (context()->get_def_use_mgr()->GetDef(inst->type_id())->opcode()) {
      case spv::Op::OpTypeSampledImage:
      case spv::Op::OpTypeImage:
      case spv::Op::OpTypeSampler:
        return assign_new_number(inst);
      default:
        break;
    }
  }

Which could probably be relaxed to some degree by including the basic-block.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions