diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2020-03-20 16:31:16 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-20 16:31:16 -0700 |
commit | 03ae7fcbfc5cedefd25c2414616cb1d3f77ab51b (patch) | |
tree | 17f6a9148ffd659f870dfe5745383fb1507e4d42 /src/wasm | |
parent | 39fda77da51f83b200fc63bbfbc4dd2ccbfc2388 (diff) | |
download | binaryen-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.cpp | 34 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 24 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 21 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 17 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 12 |
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; |