diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2021-01-19 19:32:10 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-19 16:32:10 -0800 |
commit | a4d1b53ff3374a5d7843b0a879a7908334d5bb46 (patch) | |
tree | 6bc7c3fd1ca8850f5fbba27ee850b98343306656 | |
parent | 0f212dfc69306688afa5057e3179aed5af3edc85 (diff) | |
download | binaryen-a4d1b53ff3374a5d7843b0a879a7908334d5bb46.tar.gz binaryen-a4d1b53ff3374a5d7843b0a879a7908334d5bb46.tar.bz2 binaryen-a4d1b53ff3374a5d7843b0a879a7908334d5bb46.zip |
Prototype additional f64x2 conversions (#3501)
As proposed in https://github.com/WebAssembly/simd/pull/383, with opcodes
coordinated with the WIP V8 prototype.
-rwxr-xr-x | scripts/gen-s-parser.py | 7 | ||||
-rw-r--r-- | src/gen-s-parser.inc | 94 | ||||
-rw-r--r-- | src/ir/cost.h | 6 | ||||
-rw-r--r-- | src/passes/Print.cpp | 18 | ||||
-rw-r--r-- | src/wasm-binary.h | 7 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 6 | ||||
-rw-r--r-- | src/wasm.h | 7 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 24 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 24 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 6 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 6 | ||||
-rw-r--r-- | test/simd.wast | 30 | ||||
-rw-r--r-- | test/simd.wast.from-wast | 30 | ||||
-rw-r--r-- | test/simd.wast.fromBinary | 30 | ||||
-rw-r--r-- | test/simd.wast.fromBinary.noDebugInfo | 30 | ||||
-rw-r--r-- | test/spec/simd.wast | 1 |
16 files changed, 303 insertions, 23 deletions
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py index f9ff903fc..ae19596d5 100755 --- a/scripts/gen-s-parser.py +++ b/scripts/gen-s-parser.py @@ -516,6 +516,13 @@ instructions = [ ("i16x8.extadd_pairwise_i8x16_u", "makeUnary(s, UnaryOp::ExtAddPairwiseUVecI8x16ToI16x8)"), ("i32x4.extadd_pairwise_i16x8_s", "makeUnary(s, UnaryOp::ExtAddPairwiseSVecI16x8ToI32x4)"), ("i32x4.extadd_pairwise_i16x8_u", "makeUnary(s, UnaryOp::ExtAddPairwiseUVecI16x8ToI32x4)"), + ("f64x2.convert_low_i32x4_s", "makeUnary(s, UnaryOp::ConvertLowSVecI32x4ToVecF64x2)"), + ("f64x2.convert_low_i32x4_u", "makeUnary(s, UnaryOp::ConvertLowUVecI32x4ToVecF64x2)"), + ("i32x4.trunc_sat_f64x2_zero_s", "makeUnary(s, UnaryOp::TruncSatZeroSVecF64x2ToVecI32x4)"), + ("i32x4.trunc_sat_f64x2_zero_u", "makeUnary(s, UnaryOp::TruncSatZeroUVecF64x2ToVecI32x4)"), + ("f32x4.demote_f64x2_zero", "makeUnary(s, UnaryOp::DemoteZeroVecF64x2ToVecF32x4)"), + ("f64x2.promote_low_f32x4", "makeUnary(s, UnaryOp::PromoteLowVecF32x4ToVecF64x2)"), + # prefetch instructions ("prefetch.t", "makePrefetch(s, PrefetchOp::PrefetchTemporal)"), ("prefetch.nt", "makePrefetch(s, PrefetchOp::PrefetchNontemporal)"), diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index bb07d81ca..1b48eca24 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -320,9 +320,17 @@ switch (op[0]) { default: goto parse_error; } } - case 'd': - if (strcmp(op, "f32x4.div") == 0) { return makeBinary(s, BinaryOp::DivVecF32x4); } - goto parse_error; + case 'd': { + switch (op[7]) { + case 'e': + if (strcmp(op, "f32x4.demote_f64x2_zero") == 0) { return makeUnary(s, UnaryOp::DemoteZeroVecF64x2ToVecF32x4); } + goto parse_error; + case 'i': + if (strcmp(op, "f32x4.div") == 0) { return makeBinary(s, BinaryOp::DivVecF32x4); } + goto parse_error; + default: goto parse_error; + } + } case 'e': { switch (op[7]) { case 'q': @@ -608,13 +616,29 @@ switch (op[0]) { if (strcmp(op, "f64x2.ceil") == 0) { return makeUnary(s, UnaryOp::CeilVecF64x2); } goto parse_error; case 'o': { - switch (op[20]) { - case 's': - if (strcmp(op, "f64x2.convert_i64x2_s") == 0) { return makeUnary(s, UnaryOp::ConvertSVecI64x2ToVecF64x2); } - goto parse_error; - case 'u': - if (strcmp(op, "f64x2.convert_i64x2_u") == 0) { return makeUnary(s, UnaryOp::ConvertUVecI64x2ToVecF64x2); } - goto parse_error; + switch (op[14]) { + case 'i': { + switch (op[20]) { + case 's': + if (strcmp(op, "f64x2.convert_i64x2_s") == 0) { return makeUnary(s, UnaryOp::ConvertSVecI64x2ToVecF64x2); } + goto parse_error; + case 'u': + if (strcmp(op, "f64x2.convert_i64x2_u") == 0) { return makeUnary(s, UnaryOp::ConvertUVecI64x2ToVecF64x2); } + goto parse_error; + default: goto parse_error; + } + } + case 'l': { + switch (op[24]) { + case 's': + if (strcmp(op, "f64x2.convert_low_i32x4_s") == 0) { return makeUnary(s, UnaryOp::ConvertLowSVecI32x4ToVecF64x2); } + goto parse_error; + case 'u': + if (strcmp(op, "f64x2.convert_low_i32x4_u") == 0) { return makeUnary(s, UnaryOp::ConvertLowUVecI32x4ToVecF64x2); } + goto parse_error; + default: goto parse_error; + } + } default: goto parse_error; } } @@ -689,12 +713,20 @@ switch (op[0]) { } } 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); } + switch (op[7]) { + case 'm': { + 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 'r': + if (strcmp(op, "f64x2.promote_low_f32x4") == 0) { return makeUnary(s, UnaryOp::PromoteLowVecF32x4ToVecF64x2); } goto parse_error; default: goto parse_error; } @@ -1752,13 +1784,29 @@ switch (op[0]) { } } case 't': { - switch (op[22]) { - case 's': - if (strcmp(op, "i32x4.trunc_sat_f32x4_s") == 0) { return makeUnary(s, UnaryOp::TruncSatSVecF32x4ToVecI32x4); } - goto parse_error; - case 'u': - if (strcmp(op, "i32x4.trunc_sat_f32x4_u") == 0) { return makeUnary(s, UnaryOp::TruncSatUVecF32x4ToVecI32x4); } - goto parse_error; + switch (op[17]) { + case '3': { + switch (op[22]) { + case 's': + if (strcmp(op, "i32x4.trunc_sat_f32x4_s") == 0) { return makeUnary(s, UnaryOp::TruncSatSVecF32x4ToVecI32x4); } + goto parse_error; + case 'u': + if (strcmp(op, "i32x4.trunc_sat_f32x4_u") == 0) { return makeUnary(s, UnaryOp::TruncSatUVecF32x4ToVecI32x4); } + goto parse_error; + default: goto parse_error; + } + } + case '6': { + switch (op[27]) { + case 's': + if (strcmp(op, "i32x4.trunc_sat_f64x2_zero_s") == 0) { return makeUnary(s, UnaryOp::TruncSatZeroSVecF64x2ToVecI32x4); } + goto parse_error; + case 'u': + if (strcmp(op, "i32x4.trunc_sat_f64x2_zero_u") == 0) { return makeUnary(s, UnaryOp::TruncSatZeroUVecF64x2ToVecI32x4); } + goto parse_error; + default: goto parse_error; + } + } default: goto parse_error; } } diff --git a/src/ir/cost.h b/src/ir/cost.h index 4424f2e00..7f8e39e1b 100644 --- a/src/ir/cost.h +++ b/src/ir/cost.h @@ -228,6 +228,12 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, Index> { case WidenHighSVecI32x4ToVecI64x2: case WidenLowUVecI32x4ToVecI64x2: case WidenHighUVecI32x4ToVecI64x2: + case ConvertLowSVecI32x4ToVecF64x2: + case ConvertLowUVecI32x4ToVecF64x2: + case TruncSatZeroSVecF64x2ToVecI32x4: + case TruncSatZeroUVecF64x2ToVecI32x4: + case DemoteZeroVecF64x2ToVecF32x4: + case PromoteLowVecF32x4ToVecF64x2: ret = 1; break; case InvalidUnary: diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index b6da29861..0696ea4ec 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -1080,6 +1080,24 @@ struct PrintExpressionContents case WidenHighUVecI32x4ToVecI64x2: o << "i64x2.widen_high_i32x4_u"; break; + case ConvertLowSVecI32x4ToVecF64x2: + o << "f64x2.convert_low_i32x4_s"; + break; + case ConvertLowUVecI32x4ToVecF64x2: + o << "f64x2.convert_low_i32x4_u"; + break; + case TruncSatZeroSVecF64x2ToVecI32x4: + o << "i32x4.trunc_sat_f64x2_zero_s"; + break; + case TruncSatZeroUVecF64x2ToVecI32x4: + o << "i32x4.trunc_sat_f64x2_zero_u"; + break; + case DemoteZeroVecF64x2ToVecF32x4: + o << "f32x4.demote_f64x2_zero"; + break; + case PromoteLowVecF32x4ToVecF64x2: + o << "f64x2.promote_low_f32x4"; + break; case InvalidUnary: WASM_UNREACHABLE("unvalid unary operator"); } diff --git a/src/wasm-binary.h b/src/wasm-binary.h index bda793216..c1d2a2b6d 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -973,6 +973,13 @@ enum ASTNodes { I64x2ExtMulLowUI32x4 = 0xd6, I64x2ExtMulHighUI32x4 = 0xd7, + F64x2ConvertLowSI32x4 = 0x53, + F64x2ConvertLowUI32x4 = 0x54, + I32x4TruncSatZeroSF64x2 = 0x55, + I32x4TruncSatZeroUF64x2 = 0x56, + F32x4DemoteZeroF64x2 = 0x57, + F64x2PromoteLowF32x4 = 0x69, + // prefetch opcodes PrefetchT = 0xc5, diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 2636b20f2..9fc9734eb 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -562,6 +562,12 @@ public: case WidenHighSVecI32x4ToVecI64x2: case WidenLowUVecI32x4ToVecI64x2: case WidenHighUVecI32x4ToVecI64x2: + case ConvertLowSVecI32x4ToVecF64x2: + case ConvertLowUVecI32x4ToVecF64x2: + case TruncSatZeroSVecF64x2ToVecI32x4: + case TruncSatZeroUVecF64x2ToVecI32x4: + case DemoteZeroVecF64x2ToVecF32x4: + case PromoteLowVecF32x4ToVecF64x2: WASM_UNREACHABLE("unimp"); case InvalidUnary: WASM_UNREACHABLE("invalid unary op"); diff --git a/src/wasm.h b/src/wasm.h index eeccd7be0..dd15ea7ad 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -216,6 +216,13 @@ enum UnaryOp { WidenLowUVecI32x4ToVecI64x2, WidenHighUVecI32x4ToVecI64x2, + ConvertLowSVecI32x4ToVecF64x2, + ConvertLowUVecI32x4ToVecF64x2, + TruncSatZeroSVecF64x2ToVecI32x4, + TruncSatZeroUVecF64x2ToVecI32x4, + DemoteZeroVecF64x2ToVecF32x4, + PromoteLowVecF32x4ToVecF64x2, + InvalidUnary }; diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index bf2e4afef..eea0a9c21 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -5037,6 +5037,30 @@ bool WasmBinaryBuilder::maybeVisitSIMDUnary(Expression*& out, uint32_t code) { curr = allocator.alloc<Unary>(); curr->op = WidenHighUVecI32x4ToVecI64x2; break; + case BinaryConsts::F64x2ConvertLowSI32x4: + curr = allocator.alloc<Unary>(); + curr->op = ConvertLowSVecI32x4ToVecF64x2; + break; + case BinaryConsts::F64x2ConvertLowUI32x4: + curr = allocator.alloc<Unary>(); + curr->op = ConvertLowUVecI32x4ToVecF64x2; + break; + case BinaryConsts::I32x4TruncSatZeroSF64x2: + curr = allocator.alloc<Unary>(); + curr->op = TruncSatZeroSVecF64x2ToVecI32x4; + break; + case BinaryConsts::I32x4TruncSatZeroUF64x2: + curr = allocator.alloc<Unary>(); + curr->op = TruncSatZeroUVecF64x2ToVecI32x4; + break; + case BinaryConsts::F32x4DemoteZeroF64x2: + curr = allocator.alloc<Unary>(); + curr->op = DemoteZeroVecF64x2ToVecF32x4; + break; + case BinaryConsts::F64x2PromoteLowF32x4: + curr = allocator.alloc<Unary>(); + curr->op = PromoteLowVecF32x4ToVecF64x2; + break; default: return false; } diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index c96ceabb6..b0e000719 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -1186,6 +1186,30 @@ void BinaryInstWriter::visitUnary(Unary* curr) { o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I64x2WidenHighUI32x4); break; + case ConvertLowSVecI32x4ToVecF64x2: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::F64x2ConvertLowSI32x4); + break; + case ConvertLowUVecI32x4ToVecF64x2: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::F64x2ConvertLowUI32x4); + break; + case TruncSatZeroSVecF64x2ToVecI32x4: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I32x4TruncSatZeroSF64x2); + break; + case TruncSatZeroUVecF64x2ToVecI32x4: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I32x4TruncSatZeroUF64x2); + break; + case DemoteZeroVecF64x2ToVecF32x4: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::F32x4DemoteZeroF64x2); + break; + case PromoteLowVecF32x4ToVecF64x2: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::F64x2PromoteLowF32x4); + break; case InvalidUnary: WASM_UNREACHABLE("invalid unary op"); } diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 064a151c3..e7055a8b0 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -1890,6 +1890,12 @@ void FunctionValidator::visitUnary(Unary* curr) { case WidenHighSVecI32x4ToVecI64x2: case WidenLowUVecI32x4ToVecI64x2: case WidenHighUVecI32x4ToVecI64x2: + case ConvertLowSVecI32x4ToVecF64x2: + case ConvertLowUVecI32x4ToVecF64x2: + case TruncSatZeroSVecF64x2ToVecI32x4: + case TruncSatZeroUVecF64x2ToVecI32x4: + case DemoteZeroVecF64x2ToVecF32x4: + case PromoteLowVecF32x4ToVecF64x2: shouldBeEqual(curr->type, Type(Type::v128), curr, "expected v128 type"); shouldBeEqual( curr->value->type, Type(Type::v128), curr, "expected v128 operand"); diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index 55b03c228..52d2af0c6 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -813,6 +813,12 @@ void Unary::finalize() { case WidenHighSVecI32x4ToVecI64x2: case WidenLowUVecI32x4ToVecI64x2: case WidenHighUVecI32x4ToVecI64x2: + case ConvertLowSVecI32x4ToVecF64x2: + case ConvertLowUVecI32x4ToVecF64x2: + case TruncSatZeroSVecF64x2ToVecI32x4: + case TruncSatZeroUVecF64x2ToVecI32x4: + case DemoteZeroVecF64x2ToVecF32x4: + case PromoteLowVecF32x4ToVecF64x2: type = Type::v128; break; case AnyTrueVecI8x16: diff --git a/test/simd.wast b/test/simd.wast index 515268859..a171c5398 100644 --- a/test/simd.wast +++ b/test/simd.wast @@ -1406,4 +1406,34 @@ (local.get $0) ) ) + (func $f64x2.convert_low_i32x4_s (param $0 v128) (result v128) + (f64x2.convert_low_i32x4_s + (local.get $0) + ) + ) + (func $f64x2.convert_low_i32x4_u (param $0 v128) (result v128) + (f64x2.convert_low_i32x4_u + (local.get $0) + ) + ) + (func $i32x4.trunc_sat_f64x2_zero_s (param $0 v128) (result v128) + (i32x4.trunc_sat_f64x2_zero_s + (local.get $0) + ) + ) + (func $i32x4.trunc_sat_f64x2_zero_u (param $0 v128) (result v128) + (i32x4.trunc_sat_f64x2_zero_u + (local.get $0) + ) + ) + (func $f32x4.demote_f64x2_zero (param $0 v128) (result v128) + (f32x4.demote_f64x2_zero + (local.get $0) + ) + ) + (func $f64x2.promote_low_f32x4 (param $0 v128) (result v128) + (f64x2.promote_low_f32x4 + (local.get $0) + ) + ) ) diff --git a/test/simd.wast.from-wast b/test/simd.wast.from-wast index 158de7664..223191c18 100644 --- a/test/simd.wast.from-wast +++ b/test/simd.wast.from-wast @@ -1424,4 +1424,34 @@ (local.get $0) ) ) + (func $f64x2.convert_low_i32x4_s (param $0 v128) (result v128) + (f64x2.convert_low_i32x4_s + (local.get $0) + ) + ) + (func $f64x2.convert_low_i32x4_u (param $0 v128) (result v128) + (f64x2.convert_low_i32x4_u + (local.get $0) + ) + ) + (func $i32x4.trunc_sat_f64x2_zero_s (param $0 v128) (result v128) + (i32x4.trunc_sat_f64x2_zero_s + (local.get $0) + ) + ) + (func $i32x4.trunc_sat_f64x2_zero_u (param $0 v128) (result v128) + (i32x4.trunc_sat_f64x2_zero_u + (local.get $0) + ) + ) + (func $f32x4.demote_f64x2_zero (param $0 v128) (result v128) + (f32x4.demote_f64x2_zero + (local.get $0) + ) + ) + (func $f64x2.promote_low_f32x4 (param $0 v128) (result v128) + (f64x2.promote_low_f32x4 + (local.get $0) + ) + ) ) diff --git a/test/simd.wast.fromBinary b/test/simd.wast.fromBinary index c78c23572..1c0b12493 100644 --- a/test/simd.wast.fromBinary +++ b/test/simd.wast.fromBinary @@ -1424,5 +1424,35 @@ (local.get $0) ) ) + (func $f64x2.convert_low_i32x4_s (param $0 v128) (result v128) + (f64x2.convert_low_i32x4_s + (local.get $0) + ) + ) + (func $f64x2.convert_low_i32x4_u (param $0 v128) (result v128) + (f64x2.convert_low_i32x4_u + (local.get $0) + ) + ) + (func $i32x4.trunc_sat_f64x2_zero_s (param $0 v128) (result v128) + (i32x4.trunc_sat_f64x2_zero_s + (local.get $0) + ) + ) + (func $i32x4.trunc_sat_f64x2_zero_u (param $0 v128) (result v128) + (i32x4.trunc_sat_f64x2_zero_u + (local.get $0) + ) + ) + (func $f32x4.demote_f64x2_zero (param $0 v128) (result v128) + (f32x4.demote_f64x2_zero + (local.get $0) + ) + ) + (func $f64x2.promote_low_f32x4 (param $0 v128) (result v128) + (f64x2.promote_low_f32x4 + (local.get $0) + ) + ) ) diff --git a/test/simd.wast.fromBinary.noDebugInfo b/test/simd.wast.fromBinary.noDebugInfo index 8655975db..3feb5a7b4 100644 --- a/test/simd.wast.fromBinary.noDebugInfo +++ b/test/simd.wast.fromBinary.noDebugInfo @@ -1424,5 +1424,35 @@ (local.get $0) ) ) + (func $250 (param $0 v128) (result v128) + (f64x2.convert_low_i32x4_s + (local.get $0) + ) + ) + (func $251 (param $0 v128) (result v128) + (f64x2.convert_low_i32x4_u + (local.get $0) + ) + ) + (func $252 (param $0 v128) (result v128) + (i32x4.trunc_sat_f64x2_zero_s + (local.get $0) + ) + ) + (func $253 (param $0 v128) (result v128) + (i32x4.trunc_sat_f64x2_zero_u + (local.get $0) + ) + ) + (func $254 (param $0 v128) (result v128) + (f32x4.demote_f64x2_zero + (local.get $0) + ) + ) + (func $255 (param $0 v128) (result v128) + (f64x2.promote_low_f32x4 + (local.get $0) + ) + ) ) diff --git a/test/spec/simd.wast b/test/spec/simd.wast index 968a3e553..87bbb96cb 100644 --- a/test/spec/simd.wast +++ b/test/spec/simd.wast @@ -265,6 +265,7 @@ (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))) ) +;; TODO: Additional f64x2 conversions if specified ;; Basic v128 manipulation (assert_return (invoke "v128.load" (i32.const 128)) (v128.const i8x16 87 65 83 77 83 73 77 68 71 79 69 83 70 65 83 84)) |