Skip to content

Commit e861714

Browse files
committed
[Wasm SIMD] Typed array index
Ensure that loads and stores use the index directly, without skewing it based on alignment. Add test entries. Rename m182 -> v128 in affected test files. Fixes #6259
1 parent 6fb4764 commit e861714

File tree

7 files changed

+67
-45
lines changed

7 files changed

+67
-45
lines changed

lib/Backend/IRBuilderAsmJs.cpp

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6748,13 +6748,11 @@ IRBuilderAsmJs::BuildAsmSimdTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, u
67486748
IRType type = TySimd128F4;
67496749
Js::RegSlot valueRegSlot = GetRegSlotFromSimd128Reg(value);
67506750

6751-
IR::RegOpnd * maskedOpnd = nullptr;
6752-
IR::Instr * maskInstr = nullptr;
6751+
IR::RegOpnd * addrOpnd = nullptr;
67536752

67546753
Js::OpCode op = GetSimdOpcode(newOpcode);
67556754
ValueType arrayType;
67566755
bool isLd = false, isConst = false;
6757-
uint32 mask = 0;
67586756

67596757
switch (newOpcode)
67606758
{
@@ -6936,7 +6934,6 @@ IRBuilderAsmJs::BuildAsmSimdTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, u
69366934
{
69376935
#define ARRAYBUFFER_VIEW(name, align, RegType, MemType, irSuffix) \
69386936
case Js::ArrayBufferView::TYPE_##name: \
6939-
mask = ARRAYBUFFER_VIEW_MASK(align); \
69406937
arrayType = ValueType::GetObject(ObjectType::##irSuffix##Array); \
69416938
break;
69426939
#include "Language/AsmJsArrayBufferViews.h"
@@ -6949,18 +6946,7 @@ IRBuilderAsmJs::BuildAsmSimdTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, u
69496946
{
69506947

69516948
Js::RegSlot indexRegSlot = GetRegSlotFromIntReg(slotIndex);
6952-
6953-
if (mask)
6954-
{
6955-
// AND_I4 index, mask
6956-
maskedOpnd = IR::RegOpnd::New(TyUint32, m_func);
6957-
maskInstr = IR::Instr::New(Js::OpCode::And_I4, maskedOpnd, BuildSrcOpnd(indexRegSlot, TyInt32), IR::IntConstOpnd::New(mask, TyUint32, m_func), m_func);
6958-
6959-
}
6960-
else
6961-
{
6962-
maskedOpnd = BuildSrcOpnd(indexRegSlot, TyInt32);
6963-
}
6949+
addrOpnd = BuildSrcOpnd(indexRegSlot, TyInt32);
69646950
}
69656951

69666952
IR::Instr * instr = nullptr;
@@ -6976,11 +6962,11 @@ IRBuilderAsmJs::BuildAsmSimdTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, u
69766962
regOpnd->SetValueType(ValueType::Simd);
69776963
if (!isConst)
69786964
{
6979-
Assert(maskedOpnd);
6965+
Assert(addrOpnd);
69806966
// Js::OpCodeAsmJs::Simd128_LdArr_I4:
69816967
// Js::OpCodeAsmJs::Simd128_LdArr_F4:
69826968
// Js::OpCodeAsmJs::Simd128_LdArr_D2:
6983-
indirOpnd = IR::IndirOpnd::New(baseOpnd, maskedOpnd, type, m_func);
6969+
indirOpnd = IR::IndirOpnd::New(baseOpnd, addrOpnd, type, m_func);
69846970
}
69856971
else
69866972
{
@@ -6997,11 +6983,11 @@ IRBuilderAsmJs::BuildAsmSimdTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, u
69976983
regOpnd->SetValueType(ValueType::Simd);
69986984
if (!isConst)
69996985
{
7000-
Assert(maskedOpnd);
6986+
Assert(addrOpnd);
70016987
// Js::OpCodeAsmJs::Simd128_StArr_I4:
70026988
// Js::OpCodeAsmJs::Simd128_StArr_F4:
70036989
// Js::OpCodeAsmJs::Simd128_StArr_D2:
7004-
indirOpnd = IR::IndirOpnd::New(baseOpnd, maskedOpnd, type, m_func);
6990+
indirOpnd = IR::IndirOpnd::New(baseOpnd, addrOpnd, type, m_func);
70056991
}
70066992
else
70076993
{
@@ -7016,10 +7002,6 @@ IRBuilderAsmJs::BuildAsmSimdTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, u
70167002
Assert(dataWidth >= 4 && dataWidth <= 16);
70177003
instr->dataWidth = dataWidth;
70187004
indirOpnd->SetOffset(simdOffset);
7019-
if (maskInstr)
7020-
{
7021-
AddInstr(maskInstr, offset);
7022-
}
70237005
AddInstr(instr, offset);
70247006

70257007
}

test/wasm.simd/loadTests.js

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ function testLoadOpsForType(funcname, module, laneValues, expectedResults, start
1717
const instance = new WebAssembly.Instance(module, { "dummy" : { "memory" : memObj } }).exports;
1818

1919
let intArray = new Int32Array (memObj.buffer);
20+
let int8Array = new Int8Array (memObj.buffer);
2021

2122
let forEachTestPosition = (action) => {
2223

@@ -60,12 +61,19 @@ function testLoadOpsForType(funcname, module, laneValues, expectedResults, start
6061
}
6162
}
6263

63-
check(0, "instance.m128_load4", MEM_SIZE_IN_BYTES - 32);
64-
check(0, "instance.m128_load4", MEM_SIZE_IN_BYTES - 16);
65-
check("Access index is out of range", "instance.m128_load4", MEM_SIZE_IN_BYTES - 8);
66-
check("Access index is out of range", "instance.m128_load4", MEM_SIZE_IN_BYTES - 4);
67-
check("Access index is out of range", "instance.m128_load4_offset", 0xFFFFFFFC);
68-
check("Access index is out of range", "instance.m128_load4_offset", -1);
64+
check(0, "instance.v128_load4", MEM_SIZE_IN_BYTES - 32);
65+
check(0, "instance.v128_load4", MEM_SIZE_IN_BYTES - 16);
66+
check("Access index is out of range", "instance.v128_load4", MEM_SIZE_IN_BYTES - 8);
67+
check("Access index is out of range", "instance.v128_load4", MEM_SIZE_IN_BYTES - 4);
68+
check("Access index is out of range", "instance.v128_load4_offset", 0xFFFFFFFC);
69+
check("Access index is out of range", "instance.v128_load4_offset", -1);
70+
// Verify read at "odd" index
71+
int8Array[0] = 1;
72+
int8Array[1] = 0;
73+
int8Array[2] = 0;
74+
int8Array[3] = 0;
75+
int8Array[4] = 0;
76+
check(0, "instance.v128_load4", 1);
6977

7078
}
7179

@@ -76,7 +84,7 @@ const laneValues = [0xAAAAAAAA, 0xFFFFFFFF, 0X80000000, 0x90A762A6];
7684
const expectedResults = [16, 32, 1, 14]; //i32.popcnt
7785
const startPositions = [0, 5, 11, 17];
7886

79-
testLoadOpsForType("m128_load_test", module, laneValues, expectedResults, startPositions);
87+
testLoadOpsForType("v128_load_test", module, laneValues, expectedResults, startPositions);
8088

8189
if (passed) {
8290
print("Passed");

test/wasm.simd/loads.wasm

0 Bytes
Binary file not shown.

test/wasm.simd/loads.wast

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66
(module
77
(import "dummy" "memory" (memory 1))
88

9-
(func (export "m128_load4") (param $x i32) (result i32)
9+
(func (export "v128_load4") (param $x i32) (result i32)
1010
(i32x4.extract_lane 0 (v128.load offset=0 (get_local $x)))
1111
)
1212

13-
(func (export "m128_load4_offset") (param $x i32) (result i32)
13+
(func (export "v128_load4_offset") (param $x i32) (result i32)
1414
(i32x4.extract_lane 0 (v128.load offset=16 (get_local $x)))
1515
)
1616

17-
(func (export "m128_load_test") (param $x i32) (local v128)
17+
(func (export "v128_load_test") (param $x i32) (local v128)
1818
(set_local 1 (v128.load offset=0 (get_local $x)))
1919
(i32.store offset=0 (get_local $x) (i32.popcnt (i32x4.extract_lane 0 (get_local 1))))
2020
(set_local 1 (v128.load offset=0 (get_local $x)))

test/wasm.simd/storeTests.js

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const module = new WebAssembly.Module(readbuffer('stores.wasm'));
3535
let memObj = new WebAssembly.Memory({initial:INITIAL_SIZE});
3636
const instance = new WebAssembly.Instance(module, { "dummy" : { "memory" : memObj } }).exports;
3737
let intArray = new Int32Array (memObj.buffer);
38+
let byteArray = new Uint8Array (memObj.buffer);
3839

3940
let testStore = function (funcname, ...expected) {
4041

@@ -51,18 +52,43 @@ let testStore = function (funcname, ...expected) {
5152
}
5253

5354

54-
testStore("m128_store4", 777, 888, 999, 1111);
55-
testStore("m128_store4", -1, 0, 0, -1);
56-
testStore("m128_store4", -1, -1, -1, -1);
55+
testStore("v128_store4", 777, 888, 999, 1111);
56+
testStore("v128_store4", -1, 0, 0, -1);
57+
testStore("v128_store4", -1, -1, -1, -1);
5758

59+
for (let i = 0; i < 18; i++) {
60+
byteArray[i] = 0;
61+
}
62+
63+
// Check that v128 store does not overrun value boundaries
64+
instance.v128_store_i32x4(1, 0x01020304);
65+
66+
assertEquals(0, byteArray[0]);
67+
assertEquals(4, byteArray[1]);
68+
assertEquals(3, byteArray[2]);
69+
assertEquals(2, byteArray[3]);
70+
assertEquals(1, byteArray[4]);
71+
assertEquals(4, byteArray[5]);
72+
assertEquals(3, byteArray[6]);
73+
assertEquals(2, byteArray[7]);
74+
assertEquals(1, byteArray[8]);
75+
assertEquals(4, byteArray[9]);
76+
assertEquals(3, byteArray[10]);
77+
assertEquals(2, byteArray[11]);
78+
assertEquals(1, byteArray[12]);
79+
assertEquals(4, byteArray[13]);
80+
assertEquals(3, byteArray[14]);
81+
assertEquals(2, byteArray[15]);
82+
assertEquals(1, byteArray[16]);
83+
assertEquals(0, byteArray[17]);
5884

5985
const MEM_SIZE_IN_BYTES = 1024 * 64;
60-
check("RangeError", "instance.m128_store4", MEM_SIZE_IN_BYTES - 12, 777, 888, 999, 1111);
61-
check("RangeError", "instance.m128_store4", MEM_SIZE_IN_BYTES - 8, 777, 888, 999, 1111);
62-
check("RangeError", "instance.m128_store4", MEM_SIZE_IN_BYTES - 4, 777, 888, 999, 1111);
63-
check("RangeError", "instance.m128_store4_offset", -1, 777, 888, 999, 1111);
64-
check("RangeError", "instance.m128_store4_offset", 0xFFFFFFFC, 777, 888, 999, 1111);
65-
check(undefined, "instance.m128_store4", MEM_SIZE_IN_BYTES - 16, 777, 888, 999, 1111);
86+
check("RangeError", "instance.v128_store4", MEM_SIZE_IN_BYTES - 12, 777, 888, 999, 1111);
87+
check("RangeError", "instance.v128_store4", MEM_SIZE_IN_BYTES - 8, 777, 888, 999, 1111);
88+
check("RangeError", "instance.v128_store4", MEM_SIZE_IN_BYTES - 4, 777, 888, 999, 1111);
89+
check("RangeError", "instance.v128_store4_offset", -1, 777, 888, 999, 1111);
90+
check("RangeError", "instance.v128_store4_offset", 0xFFFFFFFC, 777, 888, 999, 1111);
91+
check(undefined, "instance.v128_store4", MEM_SIZE_IN_BYTES - 16, 777, 888, 999, 1111);
6692

6793
if (passed) {
6894
print("Passed");

test/wasm.simd/stores.wasm

38 Bytes
Binary file not shown.

test/wasm.simd/stores.wast

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,19 @@
66
(module
77
(import "dummy" "memory" (memory 1))
88

9-
(func (export "m128_store4") (param i32 i32 i32 i32 i32) (local v128)
9+
(func (export "v128_store4") (param i32 i32 i32 i32 i32) (local v128)
1010
(set_local 5 (v128.load offset=0 (i32.const 16)))
1111
(v128.store offset=0 (get_local 0) (get_local 5))
1212
)
1313

14-
(func (export "m128_store4_offset") (param i32 i32 i32 i32 i32) (local v128)
14+
(func (export "v128_store4_offset") (param i32 i32 i32 i32 i32) (local v128)
1515
(set_local 5 (v128.load offset=0 (i32.const 16)))
1616
(v128.store offset=16 (get_local 0) (get_local 5))
1717
)
18+
(func
19+
(export "v128_store_i32x4")
20+
(param $index i32)
21+
(param $value i32)
22+
(v128.store align=4 (get_local $index) (i32x4.splat (get_local $value)))
23+
)
1824
)

0 commit comments

Comments
 (0)