Skip to content

[mlir][spirv][webgpu] Add lowering of IAddCarry to IAdd #68495

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
Oct 19, 2023

Conversation

inbelic
Copy link
Contributor

@inbelic inbelic commented Oct 7, 2023

WebGPU does not currently support extended arithmetic, this is an issue when we want to lower from SPIR-V. This commit adds a pattern to transform and emulate spirv.IAddCarry with spirv.IAdd operations

Fixes #65154

@inbelic
Copy link
Contributor Author

inbelic commented Oct 7, 2023

@kuhar @antiagainst I will ping you here for a request to review for a SPIR-V related change. No rush, I understand you are both busy, just before I forget to do so :)

@kuhar kuhar requested review from antiagainst and kuhar October 8, 2023 01:13
Copy link
Member

@kuhar kuhar left a comment

Choose a reason for hiding this comment

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

Thanks for taking a stab at this! I think we can simplify the code, but do let me know if I missed something there.

Copy link
Member

@kuhar kuhar left a comment

Choose a reason for hiding this comment

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

Nice, thanks for the changes.

Could you also add a runtime integration test under https://github.com/llvm/llvm-project/tree/main/mlir/test/mlir-vulkan-runner to make sure we are getting the expected results?

WebGPU does not currently support extended arithmetic, this is an issue
when we want to lower from SPIR-V. This commit adds a pattern to
transform and emulate spirv.IAddCarry with spirv.IAdd operations

Fixes llvm#65154
- inline the lowerAddCarry function to make it clearer that we check
  that each integer is of i32

- switch the computation of the carry to reduce instructions and
  simplify
- clarify description comment
- add integration test for the vulkan runner
@inbelic inbelic force-pushed the inbelic/lower-add-carry branch from eeccf0a to 9ed4b59 Compare October 12, 2023 18:27
@inbelic
Copy link
Contributor Author

inbelic commented Oct 12, 2023

Rebased and force pushed to hopefully remedy the code_formatter error.
I added an integration test, but it is only done by eye. I am not sure how one can test it locally? Is there documentation for the possible ways to test with the mlir-vulkan-runner?

@kuhar
Copy link
Member

kuhar commented Oct 13, 2023

Rebased and force pushed to hopefully remedy the code_formatter error. I added an integration test, but it is only done by eye. I am not sure how one can test it locally? Is there documentation for the possible ways to test with the mlir-vulkan-runner?

You need to set these two in cmake:

      -DMLIR_INCLUDE_INTEGRATION_TESTS=1 \
      -DMLIR_ENABLE_VULKAN_RUNNER=1 \

@kuhar
Copy link
Member

kuhar commented Oct 13, 2023

The runner test fails with:

******************** TEST 'MLIR :: mlir-vulkan-runner/iaddcarry_extended.mlir' FAILED ********************
Exit Code: 2

Command Output (stdout):
--
# RUN: at line 4
mlir-vulkan-runner /home/jakub/llvm/llvm-project/mlir/test/mlir-vulkan-runner/iaddcarry_extended.mlir   --shared-libs=/home/jakub/llvm/build/relass/lib/libvulkan-runtime-wrappers.so,/home/jakub/llvm/build/relass/lib/libmlir_runner_utils.so   --entry-point-result=void | /home/jakub/llvm/build/relass/bin/FileCheck /home/jakub/llvm/llvm-project/mlir/test/mlir-vulkan-runner/iaddcarry_extended.mlir
# executed command: mlir-vulkan-runner /home/jakub/llvm/llvm-project/mlir/test/mlir-vulkan-runner/iaddcarry_extended.mlir --shared-libs=/home/jakub/llvm/build/relass/lib/libvulkan-runtime-wrappers.so,/home/jakub/llvm/build/relass/lib/libmlir_runner_utils.so --entry-point-result=void
# .---command stderr------------
# | loc("/home/jakub/llvm/llvm-project/mlir/test/mlir-vulkan-runner/iaddcarry_extended.mlir":25:59): error: expected ','
# | could not parse the input IR
# `-----------------------------
# error: command failed with exit status: 1
# executed command: /home/jakub/llvm/build/relass/bin/FileCheck /home/jakub/llvm/llvm-project/mlir/test/mlir-vulkan-runner/iaddcarry_extended.mlir
# .---command stderr------------
# | FileCheck error: '<stdin>' is empty.
# | FileCheck command line:  /home/jakub/llvm/build/relass/bin/FileCheck /home/jakub/llvm/llvm-project/mlir/test/mlir-vulkan-runner/iaddcarry_extended.mlir
# `-----------------------------
# error: command failed with exit status: 2

@kuhar
Copy link
Member

kuhar commented Oct 13, 2023

@inbelic I made the test type check and compile but it doesn't give the expected output: kuhar@d20f576

I changed the i8 memrefs to i32 because the type of both iadd_carry results will be the same on the spir-v side anyway, and it doesn't require spir-v capabilities for i8 types. This extends out test coverage to vulkan implementations that don't expose these, e.g., swiftshader.

@inbelic
Copy link
Contributor Author

inbelic commented Oct 14, 2023

@kuhar Awesome thanks. Have got the runner test locally and also get the wrong behaviour when using the negative minimum integers for the input. I believe this is because the Signedness is set for the integer type. While arith.addui_extended and spirv.IAddCarry will interpret the bits as unsigned, spirv.IAddOp does not and that is why it does not provide our desired behaviour to overflow when we add 1 to it. All of this to say, that if you set -2^31-1 to 2^32-1 instead, then we have the expected behaviour.

However, imo it should be that the negative number is interpreted as an unsigned integer and then we unfortunately will need to use a different solution.

@kuhar
Copy link
Member

kuhar commented Oct 14, 2023

@inbelic Signed and unsigned integer addition is the same operation, that's why there's a single addi instead of addui/addsi. When we embed constants in the IR and print it back the interpretation is signed and we see negative numbers, but it doesn't matter -- it's the same bitpattern as for the unsigned result.

Therefore, addui_extended/IAddCarry both implement signless addition, and the carry bit corresponds to the unsigned overflow bit.

- use int32 to reduce required capabilities of testing environments
- updated test values with the expected behaviour
@inbelic
Copy link
Contributor Author

inbelic commented Oct 18, 2023

Resolved my confusion. Updated the test cases with your suggested changes and updated the expected values and inputs.

Copy link
Member

@kuhar kuhar left a comment

Choose a reason for hiding this comment

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

LGTM. I ran the integration tests on my machine and everything passed. Thanks!

@kuhar kuhar merged commit 6ddc03d into llvm:main Oct 19, 2023
@kuhar
Copy link
Member

kuhar commented Oct 19, 2023

@inbelic I went ahead and merged the code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[mlir][spirv] Add patterns to convert spirv.IAddCarry to spirv.IAdd
3 participants