Skip to content
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

Implement prototype v128.load{32,64}_zero instructions #3011

Merged
merged 2 commits into from
Aug 3, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions scripts/gen-s-parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,8 @@
("i32x4.load16x4_u", "makeSIMDLoad(s, SIMDLoadOp::LoadExtUVec16x4ToVecI32x4)"),
("i64x2.load32x2_s", "makeSIMDLoad(s, SIMDLoadOp::LoadExtSVec32x2ToVecI64x2)"),
("i64x2.load32x2_u", "makeSIMDLoad(s, SIMDLoadOp::LoadExtUVec32x2ToVecI64x2)"),
("v128.load32_zero", "makeSIMDLoad(s, SIMDLoadOp::Load32Zero)"),
("v128.load64_zero", "makeSIMDLoad(s, SIMDLoadOp::Load64Zero)"),
("i8x16.narrow_i16x8_s", "makeBinary(s, BinaryOp::NarrowSVecI16x8ToVecI8x16)"),
("i8x16.narrow_i16x8_u", "makeBinary(s, BinaryOp::NarrowUVecI16x8ToVecI8x16)"),
("i16x8.narrow_i32x4_s", "makeBinary(s, BinaryOp::NarrowSVecI32x4ToVecI16x8)"),
Expand Down
1 change: 1 addition & 0 deletions src/binaryen-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,7 @@ BINARYEN_API BinaryenOp BinaryenLoadExtSVec16x4ToVecI32x4(void);
BINARYEN_API BinaryenOp BinaryenLoadExtUVec16x4ToVecI32x4(void);
BINARYEN_API BinaryenOp BinaryenLoadExtSVec32x2ToVecI64x2(void);
BINARYEN_API BinaryenOp BinaryenLoadExtUVec32x2ToVecI64x2(void);
// TODO: Add Load{32,64}Zero to C and JS APIs once merged to proposal
BINARYEN_API BinaryenOp BinaryenNarrowSVecI16x8ToVecI8x16(void);
BINARYEN_API BinaryenOp BinaryenNarrowUVecI16x8ToVecI8x16(void);
BINARYEN_API BinaryenOp BinaryenNarrowSVecI32x4ToVecI16x8(void);
Expand Down
17 changes: 14 additions & 3 deletions src/gen-s-parser.inc
Original file line number Diff line number Diff line change
Expand Up @@ -2676,9 +2676,20 @@ switch (op[0]) {
case 'c':
if (strcmp(op, "v128.const") == 0) { return makeConst(s, Type::v128); }
goto parse_error;
case 'l':
if (strcmp(op, "v128.load") == 0) { return makeLoad(s, Type::v128, /*isAtomic=*/false); }
goto parse_error;
case 'l': {
switch (op[9]) {
case '\0':
if (strcmp(op, "v128.load") == 0) { return makeLoad(s, Type::v128, /*isAtomic=*/false); }
goto parse_error;
case '3':
if (strcmp(op, "v128.load32_zero") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load32Zero); }
goto parse_error;
case '6':
if (strcmp(op, "v128.load64_zero") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load64Zero); }
goto parse_error;
default: goto parse_error;
}
}
case 'n':
if (strcmp(op, "v128.not") == 0) { return makeUnary(s, UnaryOp::NotVec128); }
goto parse_error;
Expand Down
6 changes: 6 additions & 0 deletions src/passes/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,12 @@ struct PrintExpressionContents
case LoadExtUVec32x2ToVecI64x2:
o << "i64x2.load32x2_u";
break;
case Load32Zero:
o << "v128.load32_zero";
break;
case Load64Zero:
o << "v128.load64_zero";
break;
}
restoreNormalColor(o);
if (curr->offset) {
Expand Down
4 changes: 4 additions & 0 deletions src/tools/fuzzing.h
Original file line number Diff line number Diff line change
Expand Up @@ -2544,6 +2544,7 @@ class TranslateToFuzzReader {
}

Expression* makeSIMDLoad() {
// TODO: add Load{32,64}Zero if merged to proposal
SIMDLoadOp op = pick(LoadSplatVec8x16,
LoadSplatVec16x8,
LoadSplatVec32x4,
Expand Down Expand Up @@ -2575,6 +2576,9 @@ class TranslateToFuzzReader {
case LoadExtUVec32x2ToVecI64x2:
align = pick(1, 2, 4, 8);
break;
case Load32Zero:
case Load64Zero:
WASM_UNREACHABLE("Unexpected SIMD loads");
}
Expression* ptr = makePointer();
return builder.makeSIMDLoad(op, offset, align, ptr);
Expand Down
7 changes: 5 additions & 2 deletions src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -888,8 +888,11 @@ enum ASTNodes {
F32x4ConvertSI32x4 = 0xfa,
F32x4ConvertUI32x4 = 0xfb,

F32x4QFMA = 0xfc,
F32x4QFMS = 0xfd,
V128Load32Zero = 0xfc,
V128Load64Zero = 0xfd,

F32x4QFMA = 0xb4,
Copy link
Contributor

@MaxGraey MaxGraey Aug 1, 2020

Choose a reason for hiding this comment

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

0xb4 already used for I32x4DotSVecI16x8:
https://github.com/WebAssembly/binaryen/blob/master/src/wasm-binary.h#L836

Is it correct?

F32x4QFMS = 0xd4,
F64x2QFMA = 0xfe,
F64x2QFMS = 0xff,

Expand Down
22 changes: 22 additions & 0 deletions src/wasm-interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -1238,6 +1238,7 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
Flow visitSIMDLoad(SIMDLoad* curr) { WASM_UNREACHABLE("unimp"); }
Flow visitSIMDLoadSplat(SIMDLoad* curr) { WASM_UNREACHABLE("unimp"); }
Flow visitSIMDLoadExtend(SIMDLoad* curr) { WASM_UNREACHABLE("unimp"); }
Flow visitSIMDLoadZero(SIMDLoad* curr) { WASM_UNREACHABLE("unimp"); }
Flow visitPop(Pop* curr) { WASM_UNREACHABLE("unimp"); }
Flow visitRefNull(RefNull* curr) {
NOTE_ENTER("RefNull");
Expand Down Expand Up @@ -2174,6 +2175,9 @@ template<typename GlobalManager, typename SubType> class ModuleInstanceBase {
case LoadExtSVec32x2ToVecI64x2:
case LoadExtUVec32x2ToVecI64x2:
return visitSIMDLoadExtend(curr);
case Load32Zero:
case Load64Zero:
return visitSIMDLoadZero(curr);
}
WASM_UNREACHABLE("invalid op");
}
Expand Down Expand Up @@ -2266,6 +2270,24 @@ template<typename GlobalManager, typename SubType> class ModuleInstanceBase {
}
WASM_UNREACHABLE("invalid op");
}
Flow visitSIMDLoadZero(SIMDLoad* curr) {
Flow flow = this->visit(curr->ptr);
if (flow.breaking()) {
return flow;
}
NOTE_EVAL1(flow);
Address src = instance.getFinalAddress(
curr, flow.getSingleValue(), curr->op == Load32Zero ? 32 : 64);
auto zero =
Literal::makeSingleZero(curr->op == Load32Zero ? Type::i32 : Type::i64);
if (curr->op == Load32Zero) {
auto val = Literal(instance.externalInterface->load32u(src));
return Literal(std::array<Literal, 4>{{val, zero, zero, zero}});
} else {
auto val = Literal(instance.externalInterface->load64u(src));
return Literal(std::array<Literal, 2>{{val, zero}});
}
}
Flow visitHost(Host* curr) {
NOTE_ENTER("Host");
switch (curr->op) {
Expand Down
4 changes: 3 additions & 1 deletion src/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,9 @@ enum SIMDLoadOp {
LoadExtSVec16x4ToVecI32x4,
LoadExtUVec16x4ToVecI32x4,
LoadExtSVec32x2ToVecI64x2,
LoadExtUVec32x2ToVecI64x2
LoadExtUVec32x2ToVecI64x2,
Load32Zero,
Load64Zero
};

enum SIMDTernaryOp { Bitselect, QFMAF32x4, QFMSF32x4, QFMAF64x2, QFMSF64x2 };
Expand Down
8 changes: 8 additions & 0 deletions src/wasm/wasm-binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4598,6 +4598,14 @@ bool WasmBinaryBuilder::maybeVisitSIMDLoad(Expression*& out, uint32_t code) {
curr = allocator.alloc<SIMDLoad>();
curr->op = LoadExtUVec32x2ToVecI64x2;
break;
case BinaryConsts::V128Load32Zero:
curr = allocator.alloc<SIMDLoad>();
curr->op = Load32Zero;
break;
case BinaryConsts::V128Load64Zero:
curr = allocator.alloc<SIMDLoad>();
curr->op = Load64Zero;
break;
default:
return false;
}
Expand Down
2 changes: 2 additions & 0 deletions src/wasm/wasm-s-parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1528,6 +1528,7 @@ Expression* SExpressionWasmBuilder::makeSIMDLoad(Element& s, SIMDLoadOp op) {
defaultAlign = 2;
break;
case LoadSplatVec32x4:
case Load32Zero:
defaultAlign = 4;
break;
case LoadSplatVec64x2:
Expand All @@ -1537,6 +1538,7 @@ Expression* SExpressionWasmBuilder::makeSIMDLoad(Element& s, SIMDLoadOp op) {
case LoadExtUVec16x4ToVecI32x4:
case LoadExtSVec32x2ToVecI64x2:
case LoadExtUVec32x2ToVecI64x2:
case Load64Zero:
defaultAlign = 8;
break;
}
Expand Down
6 changes: 6 additions & 0 deletions src/wasm/wasm-stack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,12 @@ void BinaryInstWriter::visitSIMDLoad(SIMDLoad* curr) {
case LoadExtUVec32x2ToVecI64x2:
o << U32LEB(BinaryConsts::I64x2LoadExtUVec32x2);
break;
case Load32Zero:
o << U32LEB(BinaryConsts::V128Load32Zero);
break;
case Load64Zero:
o << U32LEB(BinaryConsts::V128Load64Zero);
break;
}
assert(curr->align);
emitMemoryAccess(curr->align, /*(unused) bytes=*/0, curr->offset);
Expand Down
2 changes: 2 additions & 0 deletions src/wasm/wasm-validator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,7 @@ void FunctionValidator::visitSIMDLoad(SIMDLoad* curr) {
case LoadSplatVec8x16:
case LoadSplatVec16x8:
case LoadSplatVec32x4:
case Load32Zero:
memAlignType = Type::i32;
break;
case LoadSplatVec64x2:
Expand All @@ -1148,6 +1149,7 @@ void FunctionValidator::visitSIMDLoad(SIMDLoad* curr) {
case LoadExtUVec16x4ToVecI32x4:
case LoadExtSVec32x2ToVecI64x2:
case LoadExtUVec32x2ToVecI64x2:
case Load64Zero:
memAlignType = Type::i64;
break;
}
Expand Down
2 changes: 2 additions & 0 deletions src/wasm/wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,7 @@ Index SIMDLoad::getMemBytes() {
case LoadSplatVec16x8:
return 2;
case LoadSplatVec32x4:
case Load32Zero:
return 4;
case LoadSplatVec64x2:
case LoadExtSVec8x8ToVecI16x8:
Expand All @@ -637,6 +638,7 @@ Index SIMDLoad::getMemBytes() {
case LoadExtUVec16x4ToVecI32x4:
case LoadExtSVec32x2ToVecI64x2:
case LoadExtUVec32x2ToVecI64x2:
case Load64Zero:
return 8;
}
WASM_UNREACHABLE("unexpected op");
Expand Down
10 changes: 10 additions & 0 deletions test/simd.wast
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,16 @@
(local.get $0)
)
)
(func $v128.load32_zero (param $0 i32) (result v128)
(v128.load32_zero
(local.get $0)
)
)
(func $v128.load64_zero (param $0 i32) (result v128)
(v128.load64_zero
(local.get $0)
)
)
(func $v8x16.swizzle (param $0 v128) (param $1 v128) (result v128)
(v8x16.swizzle
(local.get $0)
Expand Down
12 changes: 11 additions & 1 deletion test/simd.wast.from-wast
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
(type $v128_v128_=>_v128 (func (param v128 v128) (result v128)))
(type $v128_=>_v128 (func (param v128) (result v128)))
(type $v128_=>_i32 (func (param v128) (result i32)))
(type $v128_i32_=>_v128 (func (param v128 i32) (result v128)))
(type $i32_=>_v128 (func (param i32) (result v128)))
(type $v128_i32_=>_v128 (func (param v128 i32) (result v128)))
(type $none_=>_v128 (func (result v128)))
(type $v128_v128_v128_=>_v128 (func (param v128 v128 v128) (result v128)))
(type $i32_v128_=>_none (func (param i32 v128)))
Expand Down Expand Up @@ -1160,6 +1160,16 @@
(local.get $0)
)
)
(func $v128.load32_zero (param $0 i32) (result v128)
(v128.load32_zero
(local.get $0)
)
)
(func $v128.load64_zero (param $0 i32) (result v128)
(v128.load64_zero
(local.get $0)
)
)
(func $v8x16.swizzle (param $0 v128) (param $1 v128) (result v128)
(v8x16.swizzle
(local.get $0)
Expand Down
16 changes: 14 additions & 2 deletions test/simd.wast.fromBinary
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
(type $v128_v128_=>_v128 (func (param v128 v128) (result v128)))
(type $v128_=>_v128 (func (param v128) (result v128)))
(type $v128_=>_i32 (func (param v128) (result i32)))
(type $v128_i32_=>_v128 (func (param v128 i32) (result v128)))
(type $i32_=>_v128 (func (param i32) (result v128)))
(type $v128_i32_=>_v128 (func (param v128 i32) (result v128)))
(type $none_=>_v128 (func (result v128)))
(type $v128_v128_v128_=>_v128 (func (param v128 v128 v128) (result v128)))
(type $i32_v128_=>_none (func (param i32 v128)))
Expand Down Expand Up @@ -896,8 +896,10 @@
)
)
(func $f32x4.qfma (param $0 v128) (param $1 v128) (param $2 v128) (result v128)
(f32x4.qfma
(drop
Copy link
Member

Choose a reason for hiding this comment

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

Is this correct change?

(local.get $0)
)
(i32x4.dot_i16x8_s
(local.get $1)
(local.get $2)
)
Expand Down Expand Up @@ -1160,6 +1162,16 @@
(local.get $0)
)
)
(func $v128.load32_zero (param $0 i32) (result v128)
(v128.load32_zero
(local.get $0)
)
)
(func $v128.load64_zero (param $0 i32) (result v128)
(v128.load64_zero
(local.get $0)
)
)
(func $v8x16.swizzle (param $0 v128) (param $1 v128) (result v128)
(v8x16.swizzle
(local.get $0)
Expand Down
18 changes: 15 additions & 3 deletions test/simd.wast.fromBinary.noDebugInfo
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
(type $v128_v128_=>_v128 (func (param v128 v128) (result v128)))
(type $v128_=>_v128 (func (param v128) (result v128)))
(type $v128_=>_i32 (func (param v128) (result i32)))
(type $v128_i32_=>_v128 (func (param v128 i32) (result v128)))
(type $i32_=>_v128 (func (param i32) (result v128)))
(type $v128_i32_=>_v128 (func (param v128 i32) (result v128)))
(type $none_=>_v128 (func (result v128)))
(type $v128_v128_v128_=>_v128 (func (param v128 v128 v128) (result v128)))
(type $i32_v128_=>_none (func (param i32 v128)))
Expand Down Expand Up @@ -896,8 +896,10 @@
)
)
(func $156 (param $0 v128) (param $1 v128) (param $2 v128) (result v128)
(f32x4.qfma
(drop
(local.get $0)
)
(i32x4.dot_i16x8_s
(local.get $1)
(local.get $2)
)
Expand Down Expand Up @@ -1160,7 +1162,17 @@
(local.get $0)
)
)
(func $205 (param $0 v128) (param $1 v128) (result v128)
(func $205 (param $0 i32) (result v128)
(v128.load32_zero
(local.get $0)
)
)
(func $206 (param $0 i32) (result v128)
(v128.load64_zero
(local.get $0)
)
)
(func $207 (param $0 v128) (param $1 v128) (result v128)
(v8x16.swizzle
(local.get $0)
(local.get $1)
Expand Down
4 changes: 4 additions & 0 deletions test/spec/simd.wast
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@
(func (export "i32x4.load16x4_s") (param $0 i32) (result v128) (i32x4.load16x4_s (local.get $0)))
(func (export "i64x2.load32x2_u") (param $0 i32) (result v128) (i64x2.load32x2_u (local.get $0)))
(func (export "i64x2.load32x2_s") (param $0 i32) (result v128) (i64x2.load32x2_s (local.get $0)))
(func (export "v128.load32_zero") (param $0 i32) (result v128) (v128.load32_zero (local.get $0)))
(func (export "v128.load64_zero") (param $0 i32) (result v128) (v128.load64_zero (local.get $0)))
(func (export "v8x16.swizzle") (param $0 v128) (param $1 v128) (result v128) (v8x16.swizzle (local.get $0) (local.get $1)))
)

Expand Down Expand Up @@ -944,6 +946,8 @@
(assert_return (invoke "i32x4.load16x4_u" (i32.const 256)) (v128.const i32x4 0x00009080 0x0000b0a0 0x0000d0c0 0x0000f0e0))
(assert_return (invoke "i64x2.load32x2_s" (i32.const 256)) (v128.const i64x2 0xffffffffb0a09080 0xfffffffff0e0d0c0))
(assert_return (invoke "i64x2.load32x2_u" (i32.const 256)) (v128.const i64x2 0x00000000b0a09080 0x00000000f0e0d0c0))
(assert_return (invoke "v128.load32_zero" (i32.const 256)) (v128.const i32x4 0xb0a09080 0 0 0))
(assert_return (invoke "v128.load64_zero" (i32.const 256)) (v128.const i64x2 0xf0e0d0c0b0a09080 0))
(assert_return
(invoke "v8x16.swizzle"
(v128.const i8x16 0xf0 0xf1 0xf2 0xf3 0xf4 0xf5 0xf6 0xf7 0xf8 0xf9 0xfa 0xfb 0xfc 0xfd 0xfe 0xff)
Expand Down