diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2020-05-12 09:58:37 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-12 09:58:37 -0700 |
commit | 5930ada5bee7061d8063f2638cdb1cb25dce5292 (patch) | |
tree | b2386f4907ef5f3cd6b79bb9f07d1cc8f252968a /src | |
parent | a5a355747146d7725db7253478a028286dece715 (diff) | |
download | binaryen-5930ada5bee7061d8063f2638cdb1cb25dce5292.tar.gz binaryen-5930ada5bee7061d8063f2638cdb1cb25dce5292.tar.bz2 binaryen-5930ada5bee7061d8063f2638cdb1cb25dce5292.zip |
Implement pseudo-min/max SIMD instructions (#2847)
As specified in https://github.com/WebAssembly/simd/pull/122.
Diffstat (limited to 'src')
-rw-r--r-- | src/binaryen-c.cpp | 4 | ||||
-rw-r--r-- | src/binaryen-c.h | 4 | ||||
-rw-r--r-- | src/gen-s-parser.inc | 22 | ||||
-rw-r--r-- | src/ir/cost.h | 12 | ||||
-rw-r--r-- | src/js/binaryen.js-post.js | 16 | ||||
-rw-r--r-- | src/literal.h | 6 | ||||
-rw-r--r-- | src/passes/Print.cpp | 12 | ||||
-rw-r--r-- | src/wasm-binary.h | 4 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 8 | ||||
-rw-r--r-- | src/wasm.h | 4 | ||||
-rw-r--r-- | src/wasm/literal.cpp | 32 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 16 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 12 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 4 |
14 files changed, 156 insertions, 0 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index a64c46fbf..5f4ad2c40 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -681,6 +681,8 @@ BinaryenOp BinaryenMulVecF32x4(void) { return MulVecF32x4; } BinaryenOp BinaryenDivVecF32x4(void) { return DivVecF32x4; } BinaryenOp BinaryenMinVecF32x4(void) { return MinVecF32x4; } BinaryenOp BinaryenMaxVecF32x4(void) { return MaxVecF32x4; } +BinaryenOp BinaryenPMinVecF32x4(void) { return PMinVecF32x4; } +BinaryenOp BinaryenPMaxVecF32x4(void) { return PMaxVecF32x4; } BinaryenOp BinaryenAbsVecF64x2(void) { return AbsVecF64x2; } BinaryenOp BinaryenNegVecF64x2(void) { return NegVecF64x2; } BinaryenOp BinaryenSqrtVecF64x2(void) { return SqrtVecF64x2; } @@ -692,6 +694,8 @@ BinaryenOp BinaryenMulVecF64x2(void) { return MulVecF64x2; } BinaryenOp BinaryenDivVecF64x2(void) { return DivVecF64x2; } BinaryenOp BinaryenMinVecF64x2(void) { return MinVecF64x2; } BinaryenOp BinaryenMaxVecF64x2(void) { return MaxVecF64x2; } +BinaryenOp BinaryenPMinVecF64x2(void) { return PMinVecF64x2; } +BinaryenOp BinaryenPMaxVecF64x2(void) { return PMaxVecF64x2; } BinaryenOp BinaryenTruncSatSVecF32x4ToVecI32x4(void) { return TruncSatSVecF32x4ToVecI32x4; } diff --git a/src/binaryen-c.h b/src/binaryen-c.h index e460671b9..7a33a4c3c 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -541,6 +541,8 @@ BINARYEN_API BinaryenOp BinaryenMulVecF32x4(void); BINARYEN_API BinaryenOp BinaryenDivVecF32x4(void); BINARYEN_API BinaryenOp BinaryenMinVecF32x4(void); BINARYEN_API BinaryenOp BinaryenMaxVecF32x4(void); +BINARYEN_API BinaryenOp BinaryenPMinVecF32x4(void); +BINARYEN_API BinaryenOp BinaryenPMaxVecF32x4(void); BINARYEN_API BinaryenOp BinaryenAbsVecF64x2(void); BINARYEN_API BinaryenOp BinaryenNegVecF64x2(void); BINARYEN_API BinaryenOp BinaryenSqrtVecF64x2(void); @@ -552,6 +554,8 @@ BINARYEN_API BinaryenOp BinaryenMulVecF64x2(void); BINARYEN_API BinaryenOp BinaryenDivVecF64x2(void); BINARYEN_API BinaryenOp BinaryenMinVecF64x2(void); BINARYEN_API BinaryenOp BinaryenMaxVecF64x2(void); +BINARYEN_API BinaryenOp BinaryenPMinVecF64x2(void); +BINARYEN_API BinaryenOp BinaryenPMaxVecF64x2(void); BINARYEN_API BinaryenOp BinaryenTruncSatSVecF32x4ToVecI32x4(void); BINARYEN_API BinaryenOp BinaryenTruncSatUVecF32x4ToVecI32x4(void); BINARYEN_API BinaryenOp BinaryenTruncSatSVecF64x2ToVecI64x2(void); diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index 09a5070b9..351a3119f 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -338,6 +338,17 @@ switch (op[0]) { default: goto parse_error; } } + case 'p': { + switch (op[8]) { + case 'a': + if (strcmp(op, "f32x4.pmax") == 0) { return makeBinary(s, BinaryOp::PMaxVecF32x4); } + goto parse_error; + case 'i': + if (strcmp(op, "f32x4.pmin") == 0) { return makeBinary(s, BinaryOp::PMinVecF32x4); } + goto parse_error; + default: goto parse_error; + } + } case 'q': { switch (op[9]) { case 'a': @@ -619,6 +630,17 @@ switch (op[0]) { default: goto parse_error; } } + case 'p': { + switch (op[8]) { + case 'a': + if (strcmp(op, "f64x2.pmax") == 0) { return makeBinary(s, BinaryOp::PMaxVecF64x2); } + goto parse_error; + case 'i': + if (strcmp(op, "f64x2.pmin") == 0) { return makeBinary(s, BinaryOp::PMinVecF64x2); } + goto parse_error; + default: goto parse_error; + } + } case 'q': { switch (op[9]) { case 'a': diff --git a/src/ir/cost.h b/src/ir/cost.h index 2c503da02..8092d4ba2 100644 --- a/src/ir/cost.h +++ b/src/ir/cost.h @@ -687,6 +687,12 @@ struct CostAnalyzer : public Visitor<CostAnalyzer, Index> { case MaxVecF32x4: ret = 1; break; + case PMinVecF32x4: + ret = 1; + break; + case PMaxVecF32x4: + ret = 1; + break; case AddVecF64x2: ret = 1; break; @@ -705,6 +711,12 @@ struct CostAnalyzer : public Visitor<CostAnalyzer, Index> { case MaxVecF64x2: ret = 1; break; + case PMinVecF64x2: + ret = 1; + break; + case PMaxVecF64x2: + ret = 1; + break; case NarrowSVecI16x8ToVecI8x16: ret = 1; break; diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 1706d2b97..993f8c129 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -421,6 +421,8 @@ function initializeConstants() { 'DivVecF32x4', 'MinVecF32x4', 'MaxVecF32x4', + 'PMinVecF32x4', + 'PMaxVecF32x4', 'AbsVecF64x2', 'NegVecF64x2', 'SqrtVecF64x2', @@ -432,6 +434,8 @@ function initializeConstants() { 'DivVecF64x2', 'MinVecF64x2', 'MaxVecF64x2', + 'PMinVecF64x2', + 'PMaxVecF64x2', 'TruncSatSVecF32x4ToVecI32x4', 'TruncSatUVecF32x4ToVecI32x4', 'TruncSatSVecF64x2ToVecI64x2', @@ -1904,6 +1908,12 @@ function wrapModule(module, self) { 'max': function(left, right) { return Module['_BinaryenBinary'](module, Module['MaxVecF32x4'], left, right); }, + 'pmin': function(left, right) { + return Module['_BinaryenBinary'](module, Module['PMinVecF32x4'], left, right); + }, + 'pmax': function(left, right) { + return Module['_BinaryenBinary'](module, Module['PMaxVecF32x4'], left, right); + }, 'convert_i32x4_s': function(value) { return Module['_BinaryenUnary'](module, Module['ConvertSVecI32x4ToVecF32x4'], value); }, @@ -1973,6 +1983,12 @@ function wrapModule(module, self) { 'max': function(left, right) { return Module['_BinaryenBinary'](module, Module['MaxVecF64x2'], left, right); }, + 'pmin': function(left, right) { + return Module['_BinaryenBinary'](module, Module['PMinVecF64x2'], left, right); + }, + 'pmax': function(left, right) { + return Module['_BinaryenBinary'](module, Module['PMaxVecF64x2'], left, right); + }, 'convert_i64x2_s': function(value) { return Module['_BinaryenUnary'](module, Module['ConvertSVecI64x2ToVecF64x2'], value); }, diff --git a/src/literal.h b/src/literal.h index b21f08995..bba2b24d8 100644 --- a/src/literal.h +++ b/src/literal.h @@ -271,6 +271,8 @@ public: Literal min(const Literal& other) const; Literal max(const Literal& other) const; + Literal pmin(const Literal& other) const; + Literal pmax(const Literal& other) const; Literal copysign(const Literal& other) const; std::array<Literal, 16> getLanesSI8x16() const; @@ -424,6 +426,8 @@ public: Literal divF32x4(const Literal& other) const; Literal minF32x4(const Literal& other) const; Literal maxF32x4(const Literal& other) const; + Literal pminF32x4(const Literal& other) const; + Literal pmaxF32x4(const Literal& other) const; Literal absF64x2() const; Literal negF64x2() const; Literal sqrtF64x2() const; @@ -433,6 +437,8 @@ public: Literal divF64x2(const Literal& other) const; Literal minF64x2(const Literal& other) const; Literal maxF64x2(const Literal& other) const; + Literal pminF64x2(const Literal& other) const; + Literal pmaxF64x2(const Literal& other) const; Literal truncSatToSI32x4() const; Literal truncSatToUI32x4() const; Literal truncSatToSI64x2() const; diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 0839b3feb..3ed6edcb5 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -1337,6 +1337,12 @@ struct PrintExpressionContents case MaxVecF32x4: o << "f32x4.max"; break; + case PMinVecF32x4: + o << "f32x4.pmin"; + break; + case PMaxVecF32x4: + o << "f32x4.pmax"; + break; case AddVecF64x2: o << "f64x2.add"; break; @@ -1355,6 +1361,12 @@ struct PrintExpressionContents case MaxVecF64x2: o << "f64x2.max"; break; + case PMinVecF64x2: + o << "f64x2.pmin"; + break; + case PMaxVecF64x2: + o << "f64x2.pmax"; + break; case NarrowSVecI16x8ToVecI8x16: o << "i8x16.narrow_i16x8_s"; diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 1ee9253d0..7a2e33864 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -859,6 +859,8 @@ enum ASTNodes { F32x4Div = 0xe7, F32x4Min = 0xe8, F32x4Max = 0xe9, + F32x4PMin = 0xea, + F32x4PMax = 0xeb, F64x2Abs = 0xec, F64x2Neg = 0xed, @@ -869,6 +871,8 @@ enum ASTNodes { F64x2Div = 0xf3, F64x2Min = 0xf4, F64x2Max = 0xf5, + F64x2PMin = 0xf6, + F64x2PMax = 0xf7, I32x4TruncSatSF32x4 = 0xf8, I32x4TruncSatUF32x4 = 0xf9, diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 2841dc432..257a0670f 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -893,6 +893,10 @@ public: return left.minF32x4(right); case MaxVecF32x4: return left.maxF32x4(right); + case PMinVecF32x4: + return left.pminF32x4(right); + case PMaxVecF32x4: + return left.pmaxF32x4(right); case AddVecF64x2: return left.addF64x2(right); case SubVecF64x2: @@ -905,6 +909,10 @@ public: return left.minF64x2(right); case MaxVecF64x2: return left.maxF64x2(right); + case PMinVecF64x2: + return left.pminF64x2(right); + case PMaxVecF64x2: + return left.pmaxF64x2(right); case NarrowSVecI16x8ToVecI8x16: return left.narrowSToVecI8x16(right); diff --git a/src/wasm.h b/src/wasm.h index b9b06a92c..81f9f4ba0 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -400,12 +400,16 @@ enum BinaryOp { DivVecF32x4, MinVecF32x4, MaxVecF32x4, + PMinVecF32x4, + PMaxVecF32x4, AddVecF64x2, SubVecF64x2, MulVecF64x2, DivVecF64x2, MinVecF64x2, MaxVecF64x2, + PMinVecF64x2, + PMaxVecF64x2, // SIMD Conversion NarrowSVecI16x8ToVecI8x16, diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 33e53ca48..5ad82acaf 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -1321,6 +1321,26 @@ Literal Literal::max(const Literal& other) const { } } +Literal Literal::pmin(const Literal& other) const { + switch (type.getSingle()) { + case Type::f32: + case Type::f64: + return other.lt(*this).geti32() ? other : *this; + default: + WASM_UNREACHABLE("unexpected type"); + } +} + +Literal Literal::pmax(const Literal& other) const { + switch (type.getSingle()) { + case Type::f32: + case Type::f64: + return this->lt(other).geti32() ? other : *this; + default: + WASM_UNREACHABLE("unexpected type"); + } +} + Literal Literal::copysign(const Literal& other) const { // operate on bits directly, to avoid signalling bit being set on a float switch (type.getSingle()) { @@ -1958,6 +1978,12 @@ Literal Literal::minF32x4(const Literal& other) const { Literal Literal::maxF32x4(const Literal& other) const { return binary<4, &Literal::getLanesF32x4, &Literal::max>(*this, other); } +Literal Literal::pminF32x4(const Literal& other) const { + return binary<4, &Literal::getLanesF32x4, &Literal::pmin>(*this, other); +} +Literal Literal::pmaxF32x4(const Literal& other) const { + return binary<4, &Literal::getLanesF32x4, &Literal::pmax>(*this, other); +} Literal Literal::addF64x2(const Literal& other) const { return binary<2, &Literal::getLanesF64x2, &Literal::add>(*this, other); } @@ -1976,6 +2002,12 @@ Literal Literal::minF64x2(const Literal& other) const { Literal Literal::maxF64x2(const Literal& other) const { return binary<2, &Literal::getLanesF64x2, &Literal::max>(*this, other); } +Literal Literal::pminF64x2(const Literal& other) const { + return binary<2, &Literal::getLanesF64x2, &Literal::pmin>(*this, other); +} +Literal Literal::pmaxF64x2(const Literal& other) const { + return binary<2, &Literal::getLanesF64x2, &Literal::pmax>(*this, other); +} Literal Literal::dotSI16x8toI32x4(const Literal& other) const { LaneArray<8> lhs = getLanesSI16x8(); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index b3314134d..3181288f8 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -4009,6 +4009,14 @@ bool WasmBinaryBuilder::maybeVisitSIMDBinary(Expression*& out, uint32_t code) { curr = allocator.alloc<Binary>(); curr->op = MaxVecF32x4; break; + case BinaryConsts::F32x4PMin: + curr = allocator.alloc<Binary>(); + curr->op = PMinVecF32x4; + break; + case BinaryConsts::F32x4PMax: + curr = allocator.alloc<Binary>(); + curr->op = PMaxVecF32x4; + break; case BinaryConsts::F64x2Add: curr = allocator.alloc<Binary>(); curr->op = AddVecF64x2; @@ -4033,6 +4041,14 @@ bool WasmBinaryBuilder::maybeVisitSIMDBinary(Expression*& out, uint32_t code) { curr = allocator.alloc<Binary>(); curr->op = MaxVecF64x2; break; + case BinaryConsts::F64x2PMin: + curr = allocator.alloc<Binary>(); + curr->op = PMinVecF64x2; + break; + case BinaryConsts::F64x2PMax: + curr = allocator.alloc<Binary>(); + curr->op = PMaxVecF64x2; + break; case BinaryConsts::I8x16NarrowSI16x8: curr = allocator.alloc<Binary>(); curr->op = NarrowSVecI16x8ToVecI8x16; diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 48fe79fa1..a9415612d 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -1561,6 +1561,12 @@ void BinaryInstWriter::visitBinary(Binary* curr) { case MaxVecF32x4: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F32x4Max); break; + case PMinVecF32x4: + o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F32x4PMin); + break; + case PMaxVecF32x4: + o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F32x4PMax); + break; case AddVecF64x2: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F64x2Add); break; @@ -1579,6 +1585,12 @@ void BinaryInstWriter::visitBinary(Binary* curr) { case MaxVecF64x2: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F64x2Max); break; + case PMinVecF64x2: + o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F64x2PMin); + break; + case PMaxVecF64x2: + o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F64x2PMax); + break; case NarrowSVecI16x8ToVecI8x16: o << int8_t(BinaryConsts::SIMDPrefix) diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 1aee9a15d..f5e134dba 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -1455,12 +1455,16 @@ void FunctionValidator::visitBinary(Binary* curr) { case DivVecF32x4: case MinVecF32x4: case MaxVecF32x4: + case PMinVecF32x4: + case PMaxVecF32x4: case AddVecF64x2: case SubVecF64x2: case MulVecF64x2: case DivVecF64x2: case MinVecF64x2: case MaxVecF64x2: + case PMinVecF64x2: + case PMaxVecF64x2: case NarrowSVecI16x8ToVecI8x16: case NarrowUVecI16x8ToVecI8x16: case NarrowSVecI32x4ToVecI16x8: |