-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[WebAssembly] Fix inline assembly with vector types #146574
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
[WebAssembly] Fix inline assembly with vector types #146574
Conversation
This commit fixes using inline assembly with v128 results. Previously this failed with an internal assertion about a failure to legalize a `CopyFromReg` where the source register was typed `v8f16`. It looks like the type used for the destination register was whatever was listed first in the `def V128 : WebAssemblyRegClass` listing, so the types were shuffled around to have a default-supported type. A small test was added as well which failed to generate previously and should now pass in generation. This test passed on LLVM 18 additionally and regressed by accident in llvm#93228 which was first included in LLVM 19.
@llvm/pr-subscribers-backend-webassembly Author: Alex Crichton (alexcrichton) ChangesThis commit fixes using inline assembly with v128 results. Previously this failed with an internal assertion about a failure to legalize a A small test was added as well which failed to generate previously and should now pass in generation. This test passed on LLVM 18 additionally and regressed by accident in #93228 which was first included in LLVM 19. Full diff: https://github.com/llvm/llvm-project/pull/146574.diff 2 Files Affected:
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td
index 17889dacc868c..31a33c1e7365b 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td
@@ -64,8 +64,8 @@ def I32 : WebAssemblyRegClass<[i32], 32, (add FP32, SP32, I32_0)>;
def I64 : WebAssemblyRegClass<[i64], 64, (add FP64, SP64, I64_0)>;
def F32 : WebAssemblyRegClass<[f32], 32, (add F32_0)>;
def F64 : WebAssemblyRegClass<[f64], 64, (add F64_0)>;
-def V128 : WebAssemblyRegClass<[v8f16, v4f32, v2f64, v2i64, v4i32, v16i8,
- v8i16],
+def V128 : WebAssemblyRegClass<[v2i64, v4i32, v16i8, v8i16,
+ v8f16, v4f32, v2f64],
128, (add V128_0)>;
def FUNCREF : WebAssemblyRegClass<[funcref], 0, (add FUNCREF_0)>;
def EXTERNREF : WebAssemblyRegClass<[externref], 0, (add EXTERNREF_0)>;
diff --git a/llvm/test/CodeGen/WebAssembly/inline-asm.ll b/llvm/test/CodeGen/WebAssembly/inline-asm.ll
index 4462cfb7aa0c4..c378fd953a555 100644
--- a/llvm/test/CodeGen/WebAssembly/inline-asm.ll
+++ b/llvm/test/CodeGen/WebAssembly/inline-asm.ll
@@ -129,7 +129,18 @@ entry:
ret i32 %ret
}
+; CHECK-LABEL: v128_load
+; CHECK: local.get 0
+; CHECK-NEXT: v128.load 0
+; CHECK-NEXT: local.set 1
+define <4 x i32> @v128_load(ptr %v) #1 {
+entry:
+ %0 = tail call <4 x i32> asm "local.get $1\0Av128.load 0\0Alocal.set $0", "=r,r"(ptr %v)
+ ret <4 x i32> %0
+}
+
attributes #0 = { nounwind }
+attributes #1 = { "target-features"="+simd128" }
!0 = !{i32 47}
!1 = !{i32 145}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
@sunfishcode would you be ok merging for me? I'm unable to do so myself. |
This commit is a refinement of WebAssembly#586 to use inline assembly to perform vector loads instead of using a C-defined load. This is done to avoid UB in LLVM where C cannot read either before or after an allocation. When `strlen` is not inlined, as it currently isn't, then there's not really any reasonable path that a compiler could prove that a load was out-of-bounds so this is issue is unlikely in practice, but it nevertheless is still UB. In the future the eventual goal is to move these SIMD routines into header files to avoid needing multiple builds of libc itself, and in such a situation inlining is indeed possible and a compiler would be capable of much more easily seeing the UB which could cause problems. Inline assembly unfortunately doesn't work with vector output parameters on Clang 19 and Clang 20 due to an ICE. This was fixed in llvm/llvm-project#146574 for Clang 21, but it means that the SIMD routines are now excluded with Clang 19 and Clang 20 to avoid compilation errors there.
This commit is a refinement of #586 to use inline assembly to perform vector loads instead of using a C-defined load. This is done to avoid UB in LLVM where C cannot read either before or after an allocation. When `strlen` is not inlined, as it currently isn't, then there's not really any reasonable path that a compiler could prove that a load was out-of-bounds so this is issue is unlikely in practice, but it nevertheless is still UB. In the future the eventual goal is to move these SIMD routines into header files to avoid needing multiple builds of libc itself, and in such a situation inlining is indeed possible and a compiler would be capable of much more easily seeing the UB which could cause problems. Inline assembly unfortunately doesn't work with vector output parameters on Clang 19 and Clang 20 due to an ICE. This was fixed in llvm/llvm-project#146574 for Clang 21, but it means that the SIMD routines are now excluded with Clang 19 and Clang 20 to avoid compilation errors there.
@sunfishcode this is very shortterm, but there is a llvm-20.1.8 release planed for Tuesday - maybe you're able to cherry pick this fix into the llvm-20.x branch on such a short notice? upstream announcement: https://discourse.llvm.org/t/llvm-20-1-8-plans/87207 |
/cherry-pick a8a9a7f |
/pull-request #147409 |
This commit fixes using inline assembly with v128 results. Previously this failed with an internal assertion about a failure to legalize a `CopyFromReg` where the source register was typed `v8f16`. It looks like the type used for the destination register was whatever was listed first in the `def V128 : WebAssemblyRegClass` listing, so the types were shuffled around to have a default-supported type. A small test was added as well which failed to generate previously and should now pass in generation. This test passed on LLVM 18 additionally and regressed by accident in llvm#93228 which was first included in LLVM 19. (cherry picked from commit a8a9a7f)
Update from LLVM 20.1.1 to 20.1.8. This release contains various bug fixes and notably for wasi-sdk includes llvm/llvm-project#146574, which fixes inline asm vector operands.
Update from LLVM 20.1.1 to 20.1.8. This release contains various bug fixes and notably for wasi-sdk includes llvm/llvm-project#146574, which fixes inline asm vector operands.
This commit fixes using inline assembly with v128 results. Previously this failed with an internal assertion about a failure to legalize a
CopyFromReg
where the source register was typedv8f16
. It looks like the type used for the destination register was whatever was listed first in thedef V128 : WebAssemblyRegClass
listing, so the types were shuffled around to have a default-supported type.A small test was added as well which failed to generate previously and should now pass in generation. This test passed on LLVM 18 additionally and regressed by accident in #93228 which was first included in LLVM 19.