Skip to content

[OPT] prevent private_to_local_pass optimizing double pointer #6161

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

Merged
merged 4 commits into from
Jun 2, 2025

Conversation

heroseh
Copy link
Contributor

@heroseh heroseh commented May 31, 2025

Fixes #6156

before this fix the pass will optimize the following code:

  %v = OpVariable %_ptr_Private_uint Private %uint_0
%load_thread_local = OpFunction %void None %function_type__1561_
 %37 = OpLabel
 %31 = OpVariable %_ptr_Function__ptr_Private_uint Function
 %32 = OpVariable %_ptr_Function_uint Function
 %33 = OpVariable %_ptr_Function_uint Function
       OpStore %31 %v
 %34 = OpLoad %_ptr_Private_uint %31
 %35 = OpLoad %uint %34
       OpStore %32 %35
 %36 = OpLoad %uint %v
       OpStore %33 %36
       OpReturn
       OpFunctionEnd

to this:

%load_thread_local = OpFunction %void None %function_type__1561_
 %37 = OpLabel
  %v = OpVariable %_ptr_Function_uint Function %uint_0
 %31 = OpVariable %_ptr_Function__ptr_Private_uint Function
 %32 = OpVariable %_ptr_Function_uint Function
 %33 = OpVariable %_ptr_Function_uint Function
       OpStore %31 %v
       OpStore %32 %uint_0
       OpStore %33 %uint_0
       OpReturn
       OpFunctionEnd

resulting in the following error:

error: line 81: OpStore Pointer <id> '31[%31]'s type does not match Object <id> '47[%v]'s type.
  OpStore %31 %v

private_to_local_pass does not update the storage class of the double pointer %31 correctly. It currently doesn't have enough context to tell if %31 is later loaded from and used to store with. For now, just prevent the optimization if the address of the private variable is used as the object operand of the OpStore instruction.

with this commit, the spirv code is optimized to this:

%v = OpVariable %_ptr_Private_uint Private %uint_0
%load_thread_local = OpFunction %void None %function_type__1561_
         %37 = OpLabel
         %31 = OpVariable %_ptr_Function__ptr_Private_uint Function
         %32 = OpVariable %_ptr_Function_uint Function
         %33 = OpVariable %_ptr_Function_uint Function
               OpStore %31 %v
         %35 = OpLoad %uint %v
               OpStore %32 %35
         %36 = OpLoad %uint %v
               OpStore %33 %36
               OpReturn
               OpFunctionEnd

Fixes KhronosGroup#6156

before this fix the pass will optimize the following code:
```
  %v = OpVariable %_ptr_Private_uint Private %uint_0
%load_thread_local = OpFunction %void None %function_type__1561_
 %37 = OpLabel
 %31 = OpVariable %_ptr_Function__ptr_Private_uint Function
 %32 = OpVariable %_ptr_Function_uint Function
 %33 = OpVariable %_ptr_Function_uint Function
       OpStore %31 %v
 %34 = OpLoad %_ptr_Private_uint %31
 %35 = OpLoad %uint %34
       OpStore %32 %35
 %36 = OpLoad %uint %v
       OpStore %33 %36
       OpReturn
       OpFunctionEnd
```

to this:
```
%load_thread_local = OpFunction %void None %function_type__1561_
 %37 = OpLabel
  %v = OpVariable %_ptr_Function_uint Function %uint_0
 %31 = OpVariable %_ptr_Function__ptr_Private_uint Function
 %32 = OpVariable %_ptr_Function_uint Function
 %33 = OpVariable %_ptr_Function_uint Function
       OpStore %31 %v
       OpStore %32 %uint_0
       OpStore %33 %uint_0
       OpReturn
       OpFunctionEnd
```

resulting in the following error:
```
error: line 81: OpStore Pointer <id> '31[%31]'s type does not match Object <id> '47[%v]'s type.
  OpStore %31 %v

```

private_to_local_pass does not update the storage class of the double
pointer %31 correctly. It currently doesn't have enough context to tell
if %31 is later loaded from and used to store with. For now, just prevent
the optimization if the address of the private variable is used as the
object operand of the OpStore instruction.

with this commit, the spirv code is optimized to this:
```
%v = OpVariable %_ptr_Private_uint Private %uint_0
%load_thread_local = OpFunction %void None %function_type__1561_
         %37 = OpLabel
         %31 = OpVariable %_ptr_Function__ptr_Private_uint Function
         %32 = OpVariable %_ptr_Function_uint Function
         %33 = OpVariable %_ptr_Function_uint Function
               OpStore %31 %v
         %35 = OpLoad %uint %v
               OpStore %32 %35
         %36 = OpLoad %uint %v
               OpStore %33 %36
               OpReturn
               OpFunctionEnd
```
Copy link
Collaborator

@s-perron s-perron left a comment

Choose a reason for hiding this comment

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

The changes to the code look good. It just needs a test. Here is an example you can follow.

https://github.com/KhronosGroup/SPIRV-Tools/blob/main/test%2Fopt%2Fprivate_to_local_test.cpp#L176

@heroseh
Copy link
Contributor Author

heroseh commented Jun 1, 2025

I don't know why the tests failed with the previous code. Before when I made the test, I locally assembled the binary with spirv-as and done an spirv-opt & spirv-val over it but i guess i had to configured the tests to be more aggressive or something?
Anyway, I have changed them to reflect the example you linked to initially and googletest suite locally succeeds. Please let me know if anything is incorrect about it. Thanks!

Copy link
Collaborator

@s-perron s-perron left a comment

Choose a reason for hiding this comment

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

The test looks good now. I think you were doing a Match test with not checks in the source. I think that will fail.

@s-perron s-perron enabled auto-merge (squash) June 2, 2025 14:44
@s-perron s-perron merged commit 5b87767 into KhronosGroup:main Jun 2, 2025
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

spirv-opt: private_to_local_pass does not update OpVariable double pointer
3 participants