Skip to content

Commit 0678ad2

Browse files
committed
Implement the Relaxed SIMD proposal
1 parent aae7098 commit 0678ad2

File tree

11 files changed

+339
-49
lines changed

11 files changed

+339
-49
lines changed

wasm/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ This changelog summarizes major changes to the WebAssembly engine implemented in
66

77
* Updated developer metadata of Maven artifacts.
88
* Deprecated the `--wasm.AsyncParsingBinarySize` and `--wasm.AsyncParsingStackSize` options. These options no longer have any effect and will be removed in a future release.
9+
* Implemented the [Relaxed SIMD](https://github.com/WebAssembly/relaxed-simd) proposal. This feature can be enabled with the options `--wasm.RelaxedSIMD`.
910

1011
## Version 24.1.0
1112

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/BinaryParser.java

+39-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -57,6 +57,7 @@
5757
import static org.graalvm.wasm.WasmType.NULL_TYPE;
5858
import static org.graalvm.wasm.WasmType.V128_TYPE;
5959
import static org.graalvm.wasm.WasmType.VOID_TYPE;
60+
import static org.graalvm.wasm.constants.Bytecode.vectorOpcodeToBytecode;
6061
import static org.graalvm.wasm.constants.Sizes.MAX_MEMORY_64_DECLARATION_SIZE;
6162
import static org.graalvm.wasm.constants.Sizes.MAX_MEMORY_DECLARATION_SIZE;
6263
import static org.graalvm.wasm.constants.Sizes.MAX_TABLE_DECLARATION_SIZE;
@@ -1827,6 +1828,9 @@ private void readNumericInstructions(ParserState state, int opcode) {
18271828
checkSIMDSupport();
18281829
int vectorOpcode = readUnsignedInt32();
18291830
state.addVectorFlag();
1831+
if (vectorOpcode > 0xFF) {
1832+
checkRelaxedSIMDSupport(vectorOpcode);
1833+
}
18301834
switch (vectorOpcode) {
18311835
case Instructions.VECTOR_V128_LOAD:
18321836
load(state, V128_TYPE, 128, longMultiResult);
@@ -1839,7 +1843,7 @@ private void readNumericInstructions(ParserState state, int opcode) {
18391843
case Instructions.VECTOR_V128_LOAD32X2_S:
18401844
case Instructions.VECTOR_V128_LOAD32X2_U:
18411845
load(state, V128_TYPE, 64, longMultiResult);
1842-
state.addExtendedMemoryInstruction(vectorOpcode, (int) longMultiResult[0], longMultiResult[1], module.memoryHasIndexType64((int) longMultiResult[0]));
1846+
state.addExtendedMemoryInstruction(vectorOpcodeToBytecode(vectorOpcode), (int) longMultiResult[0], longMultiResult[1], module.memoryHasIndexType64((int) longMultiResult[0]));
18431847
break;
18441848
case Instructions.VECTOR_V128_LOAD8_SPLAT:
18451849
load(state, V128_TYPE, 8, longMultiResult);
@@ -1969,7 +1973,7 @@ private void readNumericInstructions(ParserState state, int opcode) {
19691973
state.popChecked(V128_TYPE);
19701974
state.popChecked(V128_TYPE);
19711975
state.push(V128_TYPE);
1972-
state.addInstruction(vectorOpcode, indices);
1976+
state.addInstruction(Bytecode.VECTOR_I8X16_SHUFFLE, indices);
19731977
break;
19741978
}
19751979
case Instructions.VECTOR_I8X16_EXTRACT_LANE_S:
@@ -1987,7 +1991,7 @@ private void readNumericInstructions(ParserState state, int opcode) {
19871991
}
19881992
state.popChecked(V128_TYPE);
19891993
state.push(shape.getUnpackedType());
1990-
state.addVectorLaneInstruction(vectorOpcode, laneIndex);
1994+
state.addVectorLaneInstruction(vectorOpcodeToBytecode(vectorOpcode), laneIndex);
19911995
break;
19921996
}
19931997
case Instructions.VECTOR_I8X16_REPLACE_LANE:
@@ -2004,7 +2008,7 @@ private void readNumericInstructions(ParserState state, int opcode) {
20042008
state.popChecked(shape.getUnpackedType());
20052009
state.popChecked(V128_TYPE);
20062010
state.push(V128_TYPE);
2007-
state.addVectorLaneInstruction(vectorOpcode, laneIndex);
2011+
state.addVectorLaneInstruction(vectorOpcodeToBytecode(vectorOpcode), laneIndex);
20082012
break;
20092013
}
20102014
case Instructions.VECTOR_I8X16_SPLAT:
@@ -2016,7 +2020,7 @@ private void readNumericInstructions(ParserState state, int opcode) {
20162020
Vector128Shape shape = Vector128Shape.ofInstruction(vectorOpcode);
20172021
state.popChecked(shape.getUnpackedType());
20182022
state.push(V128_TYPE);
2019-
state.addInstruction(vectorOpcode);
2023+
state.addInstruction(vectorOpcodeToBytecode(vectorOpcode));
20202024
break;
20212025
}
20222026
case Instructions.VECTOR_V128_ANY_TRUE:
@@ -2030,7 +2034,7 @@ private void readNumericInstructions(ParserState state, int opcode) {
20302034
case Instructions.VECTOR_I64X2_BITMASK:
20312035
state.popChecked(V128_TYPE);
20322036
state.push(I32_TYPE);
2033-
state.addInstruction(vectorOpcode);
2037+
state.addInstruction(vectorOpcodeToBytecode(vectorOpcode));
20342038
break;
20352039
case Instructions.VECTOR_V128_NOT:
20362040
case Instructions.VECTOR_I8X16_ABS:
@@ -2082,9 +2086,13 @@ private void readNumericInstructions(ParserState state, int opcode) {
20822086
case Instructions.VECTOR_F64X2_CONVERT_LOW_I32X4_U:
20832087
case Instructions.VECTOR_F32X4_DEMOTE_F64X2_ZERO:
20842088
case Instructions.VECTOR_F64X2_PROMOTE_LOW_F32X4:
2089+
case Instructions.VECTOR_I32X4_RELAXED_TRUNC_F32X4_S:
2090+
case Instructions.VECTOR_I32X4_RELAXED_TRUNC_F32X4_U:
2091+
case Instructions.VECTOR_I32X4_RELAXED_TRUNC_F64X2_S_ZERO:
2092+
case Instructions.VECTOR_I32X4_RELAXED_TRUNC_F64X2_U_ZERO:
20852093
state.popChecked(V128_TYPE);
20862094
state.push(V128_TYPE);
2087-
state.addInstruction(vectorOpcode);
2095+
state.addInstruction(vectorOpcodeToBytecode(vectorOpcode));
20882096
break;
20892097
case Instructions.VECTOR_I8X16_SWIZZLE:
20902098
case Instructions.VECTOR_I8X16_EQ:
@@ -2206,10 +2214,17 @@ private void readNumericInstructions(ParserState state, int opcode) {
22062214
case Instructions.VECTOR_F64X2_MAX:
22072215
case Instructions.VECTOR_F64X2_PMIN:
22082216
case Instructions.VECTOR_F64X2_PMAX:
2217+
case Instructions.VECTOR_I8X16_RELAXED_SWIZZLE:
2218+
case Instructions.VECTOR_F32X4_RELAXED_MIN:
2219+
case Instructions.VECTOR_F32X4_RELAXED_MAX:
2220+
case Instructions.VECTOR_F64X2_RELAXED_MIN:
2221+
case Instructions.VECTOR_F64X2_RELAXED_MAX:
2222+
case Instructions.VECTOR_I16X8_RELAXED_Q15MULR_S:
2223+
case Instructions.VECTOR_I16X8_RELAXED_DOT_I8X16_I7X16_S:
22092224
state.popChecked(V128_TYPE);
22102225
state.popChecked(V128_TYPE);
22112226
state.push(V128_TYPE);
2212-
state.addInstruction(vectorOpcode);
2227+
state.addInstruction(vectorOpcodeToBytecode(vectorOpcode));
22132228
break;
22142229
case Instructions.VECTOR_I8X16_SHL:
22152230
case Instructions.VECTOR_I8X16_SHR_S:
@@ -2226,14 +2241,23 @@ private void readNumericInstructions(ParserState state, int opcode) {
22262241
state.popChecked(I32_TYPE);
22272242
state.popChecked(V128_TYPE);
22282243
state.push(V128_TYPE);
2229-
state.addInstruction(vectorOpcode);
2244+
state.addInstruction(vectorOpcodeToBytecode(vectorOpcode));
22302245
break;
22312246
case Instructions.VECTOR_V128_BITSELECT:
2247+
case Instructions.VECTOR_F32X4_RELAXED_MADD:
2248+
case Instructions.VECTOR_F32X4_RELAXED_NMADD:
2249+
case Instructions.VECTOR_F64X2_RELAXED_MADD:
2250+
case Instructions.VECTOR_F64X2_RELAXED_NMADD:
2251+
case Instructions.VECTOR_I8X16_RELAXED_LANESELECT:
2252+
case Instructions.VECTOR_I16X8_RELAXED_LANESELECT:
2253+
case Instructions.VECTOR_I32X4_RELAXED_LANESELECT:
2254+
case Instructions.VECTOR_I64X2_RELAXED_LANESELECT:
2255+
case Instructions.VECTOR_I32X4_RELAXED_DOT_I8X16_I7X16_ADD_S:
22322256
state.popChecked(V128_TYPE);
22332257
state.popChecked(V128_TYPE);
22342258
state.popChecked(V128_TYPE);
22352259
state.push(V128_TYPE);
2236-
state.addInstruction(vectorOpcode);
2260+
state.addInstruction(vectorOpcodeToBytecode(vectorOpcode));
22372261
break;
22382262
default:
22392263
fail(Failure.UNSPECIFIED_MALFORMED, "Unknown opcode: 0xFD 0x%02x", vectorOpcode);
@@ -2271,6 +2295,10 @@ private void checkSIMDSupport() {
22712295
checkContextOption(wasmContext.getContextOptions().supportSIMD(), "Vector instructions are not enabled (opcode: 0x%02x)", Instructions.VECTOR);
22722296
}
22732297

2298+
private void checkRelaxedSIMDSupport(int vectorOpcode) {
2299+
checkContextOption(wasmContext.getContextOptions().supportRelaxedSIMD(), "Relaxed vector instructions are not enabled (opcode: 0x%02x 0x%x)", Instructions.VECTOR, vectorOpcode);
2300+
}
2301+
22742302
private void store(ParserState state, byte type, int n, long[] result) {
22752303
int alignHint = readAlignHint(n);
22762304
final int memoryIndex = readMemoryIndexFromAlignHint(alignHint);

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmContextOptions.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -58,6 +58,7 @@ public class WasmContextOptions {
5858
@CompilationFinal private boolean unsafeMemory;
5959
@CompilationFinal private boolean threads;
6060
@CompilationFinal private boolean simd;
61+
@CompilationFinal private boolean relaxedSimd;
6162

6263
@CompilationFinal private boolean memoryOverheadMode;
6364
@CompilationFinal private boolean constantRandomGet;
@@ -86,6 +87,7 @@ private void setOptionValues() {
8687
this.threads = readBooleanOption(WasmOptions.Threads);
8788
this.unsafeMemory = readBooleanOption(WasmOptions.UseUnsafeMemory);
8889
this.simd = readBooleanOption(WasmOptions.SIMD);
90+
this.relaxedSimd = readBooleanOption(WasmOptions.RelaxedSIMD);
8991
this.memoryOverheadMode = readBooleanOption(WasmOptions.MemoryOverheadMode);
9092
this.constantRandomGet = readBooleanOption(WasmOptions.WasiConstantRandomGet);
9193
this.debugCompDirectory = readStringOption(WasmOptions.DebugCompDirectory);
@@ -149,6 +151,10 @@ public boolean supportSIMD() {
149151
return simd;
150152
}
151153

154+
public boolean supportRelaxedSIMD() {
155+
return relaxedSimd;
156+
}
157+
152158
public boolean memoryOverheadMode() {
153159
return memoryOverheadMode;
154160
}
@@ -173,6 +179,7 @@ public int hashCode() {
173179
hash = 53 * hash + (this.multiMemory ? 1 : 0);
174180
hash = 53 * hash + (this.unsafeMemory ? 1 : 0);
175181
hash = 53 * hash + (this.simd ? 1 : 0);
182+
hash = 53 * hash + (this.relaxedSimd ? 1 : 0);
176183
hash = 53 * hash + (this.memoryOverheadMode ? 1 : 0);
177184
hash = 53 * hash + (this.constantRandomGet ? 1 : 0);
178185
hash = 53 * hash + (this.debugCompDirectory.hashCode());
@@ -221,6 +228,9 @@ public boolean equals(Object obj) {
221228
if (this.simd != other.simd) {
222229
return false;
223230
}
231+
if (this.relaxedSimd != other.relaxedSimd) {
232+
return false;
233+
}
224234
if (this.memoryOverheadMode != other.memoryOverheadMode) {
225235
return false;
226236
}

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmOptions.java

+4
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ public enum ConstantsStorePolicy {
109109
category = OptionCategory.EXPERT, stability = OptionStability.EXPERIMENTAL, usageSyntax = "true|false") //
110110
public static final OptionKey<Boolean> SIMD = new OptionKey<>(true);
111111

112+
@Option(help = "Enable support for the relaxed vector instructions", //
113+
category = OptionCategory.EXPERT, stability = OptionStability.EXPERIMENTAL, usageSyntax = "true|false") //
114+
public static final OptionKey<Boolean> RelaxedSIMD = new OptionKey<>(false);
115+
112116
@Option(help = "In this mode memories and tables are not initialized.", category = OptionCategory.INTERNAL, stability = OptionStability.EXPERIMENTAL, usageSyntax = "false|true") //
113117
public static final OptionKey<Boolean> MemoryOverheadMode = new OptionKey<>(false);
114118

0 commit comments

Comments
 (0)