[llvm] [WebAssembly] Enable simd128 when relaxed-simd is set in AsmPrinter (PR #99803)
Heejin Ahn via llvm-commits
llvm-commits at lists.llvm.org
Sun Jul 21 01:10:31 PDT 2024
https://github.com/aheejin created https://github.com/llvm/llvm-project/pull/99803
Even though in `Subtarget` we defined `SIMDLevel` as a number so `hasRelaxedSIMD` automatically means `hasSIMD128`, https://github.com/llvm/llvm-project/blob/0caf0c93e759816663af52e8632d1c3953dbc715/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h#L36-L40 https://github.com/llvm/llvm-project/blob/0caf0c93e759816663af52e8632d1c3953dbc715/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h#L107
specifying only `relaxed-simd` feature on a program that needs `simd128` instructions to compile fails, because of this query in `AsmPrinter`: https://github.com/llvm/llvm-project/blob/d0d05aec3b6792136a9f75eb85dd2ea66005ae12/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp#L644-L645
This `verifyInstructionPredicates` function (and other functions called by this function) is generated by
https://github.com/llvm/llvm-project/blob/main/llvm/utils/TableGen/InstrInfoEmitter.cpp, and looks like this (you can check it in the
`lib/Target/WebAssembly/WebAssemblyGenInstrInfo.inc` in your build directory):
```cpp
void verifyInstructionPredicates(
unsigned Opcode, const FeatureBitset &Features) {
FeatureBitset AvailableFeatures = computeAvailableFeatures(Features);
FeatureBitset RequiredFeatures = computeRequiredFeatures(Opcode);
FeatureBitset MissingFeatures =
(AvailableFeatures & RequiredFeatures) ^
RequiredFeatures;
...
}
```
And `computeAvailableFeatures` there is just a set query, like this:
```cpp
inline FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) {
FeatureBitset Features;
if (FB[WebAssembly::FeatureAtomics])
Features.set(Feature_HasAtomicsBit);
if (FB[WebAssembly::FeatureBulkMemory])
Features.set(Feature_HasBulkMemoryBit);
if (FB[WebAssembly::FeatureExceptionHandling])
Features.set(Feature_HasExceptionHandlingBit);
...
```
So this is how currently `HasSIMD128` is defined:
https://github.com/llvm/llvm-project/blob/0caf0c93e759816663af52e8632d1c3953dbc715/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td#L79-L81
The things being checked in this `computeAvailableFeatures`, and in turn in `AsmPrinter`, are `AssemblerPredicate`s. These only check which bits are set in the features set and are different from `Predicate`s, which can call `Subtarget` functions like `Subtarget->hasSIMD128()`.
But apparently we can use `all_of` and `any_of` directives in `AssemblerPredicate`, and we can make `simd128`'s `AssemblerPredicate` set in `relaxed-simd` is set by the condition as an 'or' of the two.
Fixes #98502.
>From ac2cb407e7b9a7dcb2652c5328f20f1a743c7197 Mon Sep 17 00:00:00 2001
From: Heejin Ahn <aheejin at gmail.com>
Date: Sun, 21 Jul 2024 07:39:29 +0000
Subject: [PATCH] [WebAssembly] Enable simd128 when relaxed-simd is set in
AsmPrinter
Even though in `Subtarget` we defined `SIMDLevel` as a number so
`hasRelaxedSIMD` automatically means `hasSIMD128`,
https://github.com/llvm/llvm-project/blob/0caf0c93e759816663af52e8632d1c3953dbc715/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h#L36-L40
https://github.com/llvm/llvm-project/blob/0caf0c93e759816663af52e8632d1c3953dbc715/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h#L107
specifying only `relaxed-simd` feature on a program that needs `simd128`
instructions to compile fails, because of this query in `AsmPrinter`:
https://github.com/llvm/llvm-project/blob/d0d05aec3b6792136a9f75eb85dd2ea66005ae12/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp#L644-L645
This `verifyInstructionPredicates` function (and other functions called
by this function) is generated by
https://github.com/llvm/llvm-project/blob/main/llvm/utils/TableGen/InstrInfoEmitter.cpp,
and looks like this (you can check it in the
`lib/Target/WebAssembly/WebAssemblyGenInstrInfo.inc` in your build
directory):
```cpp
void verifyInstructionPredicates(
unsigned Opcode, const FeatureBitset &Features) {
FeatureBitset AvailableFeatures = computeAvailableFeatures(Features);
FeatureBitset RequiredFeatures = computeRequiredFeatures(Opcode);
FeatureBitset MissingFeatures =
(AvailableFeatures & RequiredFeatures) ^
RequiredFeatures;
...
}
```
And `computeAvailableFeatures` there is just a set query, like this:
```cpp
inline FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) {
FeatureBitset Features;
if (FB[WebAssembly::FeatureAtomics])
Features.set(Feature_HasAtomicsBit);
if (FB[WebAssembly::FeatureBulkMemory])
Features.set(Feature_HasBulkMemoryBit);
if (FB[WebAssembly::FeatureExceptionHandling])
Features.set(Feature_HasExceptionHandlingBit);
...
```
So this is how currently `HasSIMD128` is defined:
https://github.com/llvm/llvm-project/blob/0caf0c93e759816663af52e8632d1c3953dbc715/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td#L79-L81
The things being checked in this `computeAvailableFeatures`, and in turn
in `AsmPrinter`, are `AssemblerPredicate`s. These only check which
bits are set in the features set and are different from `Predicate`s,
which can call `Subtarget` functions like `Subtarget->hasSIMD128()`.
But apparently we can use `all_of` and `any_of` directives in
`AssemblerPredicate`, and we can make `simd128`'s `AssemblerPredicate`
set in `relaxed-simd` is set by the condition as an 'or' of the two.
Fixes #98502.
---
.../WebAssembly/WebAssemblyInstrInfo.td | 2 +-
.../test/CodeGen/WebAssembly/simd-asm-pred.ll | 24 +++++++++++++++++++
2 files changed, 25 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/WebAssembly/simd-asm-pred.ll
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
index 3d37eb2fa27bc..bb36ce7650183 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
@@ -78,7 +78,7 @@ def HasSignExt :
def HasSIMD128 :
Predicate<"Subtarget->hasSIMD128()">,
- AssemblerPredicate<(all_of FeatureSIMD128), "simd128">;
+ AssemblerPredicate<(any_of FeatureSIMD128, FeatureRelaxedSIMD), "simd128">;
def HasTailCall :
Predicate<"Subtarget->hasTailCall()">,
diff --git a/llvm/test/CodeGen/WebAssembly/simd-asm-pred.ll b/llvm/test/CodeGen/WebAssembly/simd-asm-pred.ll
new file mode 100644
index 0000000000000..f022c3e745125
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/simd-asm-pred.ll
@@ -0,0 +1,24 @@
+; RUN: llc < %s -verify-machineinstrs -mattr=+relaxed-simd | FileCheck %s
+
+; Test that setting "relaxed-simd" target feature set also implies 'simd128' in
+; AssemblerPredicate, which is used to verify instructions in AsmPrinter.
+
+target triple = "wasm32-unknown-unknown"
+
+declare <2 x i64> @llvm.wasm.relaxed.laneselect.v2i64(<2 x i64>, <2 x i64>, <2 x i64>)
+
+; The compiled result of this function uses LOCAL_GET_V128, which is predicated
+; on the 'simd128' feature. We should be able to compile this when only
+; 'relaxed-simd' is set, which implies 'simd128'.
+define <2 x i64> @test(<2 x i64>, <2 x i64>, <2 x i64>) #0 {
+; CHECK-LABEL: test:
+; CHECK: .functype test (v128, v128, v128) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: local.get 2
+; CHECK-NEXT: i64x2.relaxed_laneselect
+start:
+ %_4 = tail call <2 x i64> @llvm.wasm.relaxed.laneselect.v2i64(<2 x i64> %0, <2 x i64> %1, <2 x i64> %2) #3
+ ret <2 x i64> %_4
+}
More information about the llvm-commits
mailing list