summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2020-03-20 16:31:16 -0700
committerGitHub <noreply@github.com>2020-03-20 16:31:16 -0700
commit03ae7fcbfc5cedefd25c2414616cb1d3f77ab51b (patch)
tree17f6a9148ffd659f870dfe5745383fb1507e4d42 /src/wasm
parent39fda77da51f83b200fc63bbfbc4dd2ccbfc2388 (diff)
downloadbinaryen-03ae7fcbfc5cedefd25c2414616cb1d3f77ab51b.tar.gz
binaryen-03ae7fcbfc5cedefd25c2414616cb1d3f77ab51b.tar.bz2
binaryen-03ae7fcbfc5cedefd25c2414616cb1d3f77ab51b.zip
SIMD integer abs and bitmask instructions (#2703)
Adds full support for the {i8x16,i16x8,i32x4}.abs instructions merged to the SIMD proposal in https://github.com/WebAssembly/simd/pull/128 as well as the {i8x16,i16x8,i32x4}.bitmask instructions proposed in https://github.com/WebAssembly/simd/pull/201.
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/literal.cpp34
-rw-r--r--src/wasm/wasm-binary.cpp24
-rw-r--r--src/wasm/wasm-stack.cpp21
-rw-r--r--src/wasm/wasm-validator.cpp17
-rw-r--r--src/wasm/wasm.cpp12
5 files changed, 96 insertions, 12 deletions
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index aa2acdcc1..b740ae520 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -565,9 +565,9 @@ Literal Literal::neg() const {
Literal Literal::abs() const {
switch (type.getSingle()) {
case Type::i32:
- return Literal(i32 & 0x7fffffff);
+ return Literal(std::abs(i32));
case Type::i64:
- return Literal(int64_t(i64 & 0x7fffffffffffffffULL));
+ return Literal(std::abs(i64));
case Type::f32:
return Literal(i32 & 0x7fffffff).castToF32();
case Type::f64:
@@ -1442,6 +1442,15 @@ Literal Literal::notV128() const {
ones.fill(0xff);
return xorV128(Literal(ones.data()));
}
+Literal Literal::absI8x16() const {
+ return unary<16, &Literal::getLanesSI8x16, &Literal::abs>(*this);
+}
+Literal Literal::absI16x8() const {
+ return unary<8, &Literal::getLanesSI16x8, &Literal::abs>(*this);
+}
+Literal Literal::absI32x4() const {
+ return unary<4, &Literal::getLanesI32x4, &Literal::abs>(*this);
+}
Literal Literal::negI8x16() const {
return unary<16, &Literal::getLanesUI8x16, &Literal::neg>(*this);
}
@@ -1519,24 +1528,45 @@ static Literal all_true(const Literal& val) {
return Literal(int32_t(1));
}
+template<int Lanes, LaneArray<Lanes> (Literal::*IntoLanes)() const>
+static Literal bitmask(const Literal& val) {
+ uint32_t result = 0;
+ LaneArray<Lanes> lanes = (val.*IntoLanes)();
+ for (size_t i = 0; i < Lanes; ++i) {
+ if (lanes[i].geti32() & (1 << 31)) {
+ result = result | (1 << i);
+ }
+ }
+ return Literal(result);
+}
+
Literal Literal::anyTrueI8x16() const {
return any_true<16, &Literal::getLanesUI8x16>(*this);
}
Literal Literal::allTrueI8x16() const {
return all_true<16, &Literal::getLanesUI8x16>(*this);
}
+Literal Literal::bitmaskI8x16() const {
+ return bitmask<16, &Literal::getLanesSI8x16>(*this);
+}
Literal Literal::anyTrueI16x8() const {
return any_true<8, &Literal::getLanesUI16x8>(*this);
}
Literal Literal::allTrueI16x8() const {
return all_true<8, &Literal::getLanesUI16x8>(*this);
}
+Literal Literal::bitmaskI16x8() const {
+ return bitmask<8, &Literal::getLanesSI16x8>(*this);
+}
Literal Literal::anyTrueI32x4() const {
return any_true<4, &Literal::getLanesI32x4>(*this);
}
Literal Literal::allTrueI32x4() const {
return all_true<4, &Literal::getLanesI32x4>(*this);
}
+Literal Literal::bitmaskI32x4() const {
+ return bitmask<4, &Literal::getLanesI32x4>(*this);
+}
Literal Literal::anyTrueI64x2() const {
return any_true<2, &Literal::getLanesI64x2>(*this);
}
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 9fe046c27..dbd644a17 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -4053,6 +4053,10 @@ bool WasmBinaryBuilder::maybeVisitSIMDUnary(Expression*& out, uint32_t code) {
curr = allocator.alloc<Unary>();
curr->op = NotVec128;
break;
+ case BinaryConsts::I8x16Abs:
+ curr = allocator.alloc<Unary>();
+ curr->op = AbsVecI8x16;
+ break;
case BinaryConsts::I8x16Neg:
curr = allocator.alloc<Unary>();
curr->op = NegVecI8x16;
@@ -4065,6 +4069,14 @@ bool WasmBinaryBuilder::maybeVisitSIMDUnary(Expression*& out, uint32_t code) {
curr = allocator.alloc<Unary>();
curr->op = AllTrueVecI8x16;
break;
+ case BinaryConsts::I8x16Bitmask:
+ curr = allocator.alloc<Unary>();
+ curr->op = BitmaskVecI8x16;
+ break;
+ case BinaryConsts::I16x8Abs:
+ curr = allocator.alloc<Unary>();
+ curr->op = AbsVecI16x8;
+ break;
case BinaryConsts::I16x8Neg:
curr = allocator.alloc<Unary>();
curr->op = NegVecI16x8;
@@ -4077,6 +4089,14 @@ bool WasmBinaryBuilder::maybeVisitSIMDUnary(Expression*& out, uint32_t code) {
curr = allocator.alloc<Unary>();
curr->op = AllTrueVecI16x8;
break;
+ case BinaryConsts::I16x8Bitmask:
+ curr = allocator.alloc<Unary>();
+ curr->op = BitmaskVecI16x8;
+ break;
+ case BinaryConsts::I32x4Abs:
+ curr = allocator.alloc<Unary>();
+ curr->op = AbsVecI32x4;
+ break;
case BinaryConsts::I32x4Neg:
curr = allocator.alloc<Unary>();
curr->op = NegVecI32x4;
@@ -4089,6 +4109,10 @@ bool WasmBinaryBuilder::maybeVisitSIMDUnary(Expression*& out, uint32_t code) {
curr = allocator.alloc<Unary>();
curr->op = AllTrueVecI32x4;
break;
+ case BinaryConsts::I32x4Bitmask:
+ curr = allocator.alloc<Unary>();
+ curr->op = BitmaskVecI32x4;
+ break;
case BinaryConsts::I64x2Neg:
curr = allocator.alloc<Unary>();
curr->op = NegVecI64x2;
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 3c162a9d5..9b5dc3f22 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -899,6 +899,9 @@ void BinaryInstWriter::visitUnary(Unary* curr) {
case NotVec128:
o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::V128Not);
break;
+ case AbsVecI8x16:
+ o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I8x16Abs);
+ break;
case NegVecI8x16:
o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I8x16Neg);
break;
@@ -910,6 +913,13 @@ void BinaryInstWriter::visitUnary(Unary* curr) {
o << int8_t(BinaryConsts::SIMDPrefix)
<< U32LEB(BinaryConsts::I8x16AllTrue);
break;
+ case BitmaskVecI8x16:
+ o << int8_t(BinaryConsts::SIMDPrefix)
+ << U32LEB(BinaryConsts::I8x16Bitmask);
+ break;
+ case AbsVecI16x8:
+ o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I16x8Abs);
+ break;
case NegVecI16x8:
o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I16x8Neg);
break;
@@ -921,6 +931,13 @@ void BinaryInstWriter::visitUnary(Unary* curr) {
o << int8_t(BinaryConsts::SIMDPrefix)
<< U32LEB(BinaryConsts::I16x8AllTrue);
break;
+ case BitmaskVecI16x8:
+ o << int8_t(BinaryConsts::SIMDPrefix)
+ << U32LEB(BinaryConsts::I16x8Bitmask);
+ break;
+ case AbsVecI32x4:
+ o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I32x4Abs);
+ break;
case NegVecI32x4:
o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I32x4Neg);
break;
@@ -932,6 +949,10 @@ void BinaryInstWriter::visitUnary(Unary* curr) {
o << int8_t(BinaryConsts::SIMDPrefix)
<< U32LEB(BinaryConsts::I32x4AllTrue);
break;
+ case BitmaskVecI32x4:
+ o << int8_t(BinaryConsts::SIMDPrefix)
+ << U32LEB(BinaryConsts::I32x4Bitmask);
+ break;
case NegVecI64x2:
o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I64x2Neg);
break;
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 1db8ed7c0..984c25b3f 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -1689,6 +1689,9 @@ void FunctionValidator::visitUnary(Unary* curr) {
curr->value->type, Type(Type::f64), curr, "expected f64 splat value");
break;
case NotVec128:
+ case AbsVecI8x16:
+ case AbsVecI16x8:
+ case AbsVecI32x4:
case NegVecI8x16:
case NegVecI16x8:
case NegVecI32x4:
@@ -1720,17 +1723,17 @@ void FunctionValidator::visitUnary(Unary* curr) {
curr->value->type, Type(Type::v128), curr, "expected v128 operand");
break;
case AnyTrueVecI8x16:
- case AllTrueVecI8x16:
case AnyTrueVecI16x8:
- case AllTrueVecI16x8:
case AnyTrueVecI32x4:
- case AllTrueVecI32x4:
case AnyTrueVecI64x2:
+ case AllTrueVecI8x16:
+ case AllTrueVecI16x8:
+ case AllTrueVecI32x4:
case AllTrueVecI64x2:
- shouldBeEqual(curr->type,
- Type(Type::i32),
- curr,
- "expected boolean reduction to have i32 type");
+ case BitmaskVecI8x16:
+ case BitmaskVecI16x8:
+ case BitmaskVecI32x4:
+ shouldBeEqual(curr->type, Type(Type::i32), curr, "expected i32 type");
shouldBeEqual(
curr->value->type, Type(Type::v128), curr, "expected v128 operand");
break;
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index 35fa8b5c5..6f7ea4f86 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -737,6 +737,9 @@ void Unary::finalize() {
case SplatVecF32x4:
case SplatVecF64x2:
case NotVec128:
+ case AbsVecI8x16:
+ case AbsVecI16x8:
+ case AbsVecI32x4:
case NegVecI8x16:
case NegVecI16x8:
case NegVecI32x4:
@@ -766,13 +769,16 @@ void Unary::finalize() {
type = Type::v128;
break;
case AnyTrueVecI8x16:
- case AllTrueVecI8x16:
case AnyTrueVecI16x8:
- case AllTrueVecI16x8:
case AnyTrueVecI32x4:
- case AllTrueVecI32x4:
case AnyTrueVecI64x2:
+ case AllTrueVecI8x16:
+ case AllTrueVecI16x8:
+ case AllTrueVecI32x4:
case AllTrueVecI64x2:
+ case BitmaskVecI8x16:
+ case BitmaskVecI16x8:
+ case BitmaskVecI32x4:
type = Type::i32;
break;