diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binaryen-c.cpp | 70 | ||||
-rw-r--r-- | src/binaryen-c.h | 22 | ||||
-rw-r--r-- | src/gen-s-parser.inc | 24 | ||||
-rw-r--r-- | src/ir/ExpressionAnalyzer.cpp | 2 | ||||
-rw-r--r-- | src/ir/ExpressionManipulator.cpp | 6 | ||||
-rw-r--r-- | src/ir/ReFinalize.cpp | 2 | ||||
-rw-r--r-- | src/ir/effects.h | 2 | ||||
-rw-r--r-- | src/ir/utils.h | 4 | ||||
-rw-r--r-- | src/js/binaryen.js-post.js | 29 | ||||
-rw-r--r-- | src/passes/DeadCodeElimination.cpp | 4 | ||||
-rw-r--r-- | src/passes/Print.cpp | 28 | ||||
-rw-r--r-- | src/tools/fuzzing.h | 19 | ||||
-rw-r--r-- | src/wasm-binary.h | 6 | ||||
-rw-r--r-- | src/wasm-builder.h | 15 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 22 | ||||
-rw-r--r-- | src/wasm-s-parser.h | 2 | ||||
-rw-r--r-- | src/wasm-stack.h | 12 | ||||
-rw-r--r-- | src/wasm-traversal.h | 28 | ||||
-rw-r--r-- | src/wasm.h | 17 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 38 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 12 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 21 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 12 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 12 | ||||
-rw-r--r-- | src/wasm2js.h | 2 |
25 files changed, 275 insertions, 136 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index cbaa513ac..b991f39fa 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -343,8 +343,8 @@ BinaryenExpressionId BinaryenSIMDReplaceId(void) { BinaryenExpressionId BinaryenSIMDShuffleId(void) { return Expression::Id::SIMDShuffleId; } -BinaryenExpressionId BinaryenSIMDBitselectId(void) { - return Expression::Id::SIMDBitselectId; +BinaryenExpressionId BinaryenSIMDTernaryId(void) { + return Expression::Id::SIMDTernaryId; } BinaryenExpressionId BinaryenSIMDShiftId(void) { return Expression::Id::SIMDShiftId; @@ -790,6 +790,7 @@ BinaryenOp BinaryenNotVec128(void) { return NotVec128; } BinaryenOp BinaryenAndVec128(void) { return AndVec128; } BinaryenOp BinaryenOrVec128(void) { return OrVec128; } BinaryenOp BinaryenXorVec128(void) { return XorVec128; } +BinaryenOp BinaryenBitselectVec128(void) { return Bitselect; } BinaryenOp BinaryenNegVecI8x16(void) { return NegVecI8x16; } BinaryenOp BinaryenAnyTrueVecI8x16(void) { return AnyTrueVecI8x16; } BinaryenOp BinaryenAllTrueVecI8x16(void) { return AllTrueVecI8x16; } @@ -836,6 +837,8 @@ BinaryenOp BinaryenSubVecI64x2(void) { return SubVecI64x2; } BinaryenOp BinaryenAbsVecF32x4(void) { return AbsVecF32x4; } BinaryenOp BinaryenNegVecF32x4(void) { return NegVecF32x4; } BinaryenOp BinaryenSqrtVecF32x4(void) { return SqrtVecF32x4; } +BinaryenOp BinaryenQFMAVecF32x4(void) { return QFMAF32x4; } +BinaryenOp BinaryenQFMSVecF32x4(void) { return QFMSF32x4; } BinaryenOp BinaryenAddVecF32x4(void) { return AddVecF32x4; } BinaryenOp BinaryenSubVecF32x4(void) { return SubVecF32x4; } BinaryenOp BinaryenMulVecF32x4(void) { return MulVecF32x4; } @@ -845,6 +848,8 @@ BinaryenOp BinaryenMaxVecF32x4(void) { return MaxVecF32x4; } BinaryenOp BinaryenAbsVecF64x2(void) { return AbsVecF64x2; } BinaryenOp BinaryenNegVecF64x2(void) { return NegVecF64x2; } BinaryenOp BinaryenSqrtVecF64x2(void) { return SqrtVecF64x2; } +BinaryenOp BinaryenQFMAVecF64x2(void) { return QFMAF64x2; } +BinaryenOp BinaryenQFMSVecF64x2(void) { return QFMSF64x2; } BinaryenOp BinaryenAddVecF64x2(void) { return AddVecF64x2; } BinaryenOp BinaryenSubVecF64x2(void) { return SubVecF64x2; } BinaryenOp BinaryenMulVecF64x2(void) { return MulVecF64x2; } @@ -1532,15 +1537,17 @@ BinaryenExpressionRef BinaryenSIMDShuffle(BinaryenModuleRef module, } return static_cast<Expression*>(ret); } -BinaryenExpressionRef BinaryenSIMDBitselect(BinaryenModuleRef module, - BinaryenExpressionRef left, - BinaryenExpressionRef right, - BinaryenExpressionRef cond) { - auto* ret = Builder(*(Module*)module) - .makeSIMDBitselect( - (Expression*)left, (Expression*)right, (Expression*)cond); +BinaryenExpressionRef BinaryenSIMDTernary(BinaryenModuleRef module, + BinaryenOp op, + BinaryenExpressionRef a, + BinaryenExpressionRef b, + BinaryenExpressionRef c) { + auto* ret = + Builder(*(Module*)module) + .makeSIMDTernary( + SIMDTernaryOp(op), (Expression*)a, (Expression*)b, (Expression*)c); if (tracing) { - traceExpression(ret, "BinaryenSIMDBitselect", left, right, cond); + traceExpression(ret, "BinaryenSIMDTernary", op, a, b, c); } return static_cast<Expression*>(ret); } @@ -2652,37 +2659,46 @@ void BinaryenSIMDShuffleGetMask(BinaryenExpressionRef expr, uint8_t* mask) { assert(expression->is<SIMDShuffle>()); memcpy(mask, static_cast<SIMDShuffle*>(expression)->mask.data(), 16); } -// SIMDBitselect -BinaryenExpressionRef BinaryenSIMDBitselectGetLeft(BinaryenExpressionRef expr) { +// SIMDTernary +BinaryenOp BinaryenSIMDTernaryGetOp(BinaryenExpressionRef expr) { if (tracing) { - std::cout << " BinaryenSIMDBitselectGetLeft(expressions[" - << expressions[expr] << "]);\n"; + std::cout << " BinaryenSIMDTernaryOp(expressions[" << expressions[expr] + << "]);\n"; } auto* expression = (Expression*)expr; - assert(expression->is<SIMDBitselect>()); - return static_cast<SIMDBitselect*>(expression)->left; + assert(expression->is<SIMDTernary>()); + return static_cast<SIMDTernary*>(expression)->op; } -BinaryenExpressionRef -BinaryenSIMDBitselectGetRight(BinaryenExpressionRef expr) { +BinaryenExpressionRef BinaryenSIMDTernaryGetA(BinaryenExpressionRef expr) { if (tracing) { - std::cout << " BinaryenSIMDBitselectGetRight(expressions[" - << expressions[expr] << "]);\n"; + std::cout << " BinaryenSIMDTernaryGetA(expressions[" << expressions[expr] + << "]);\n"; } auto* expression = (Expression*)expr; - assert(expression->is<SIMDBitselect>()); - return static_cast<SIMDBitselect*>(expression)->right; + assert(expression->is<SIMDTernary>()); + return static_cast<SIMDTernary*>(expression)->a; } -BinaryenExpressionRef BinaryenSIMDBitselectGetCond(BinaryenExpressionRef expr) { +BinaryenExpressionRef BinaryenSIMDTernaryGetB(BinaryenExpressionRef expr) { if (tracing) { - std::cout << " BinaryenSIMDBitselectGetCond(expressions[" - << expressions[expr] << "]);\n"; + std::cout << " BinaryenSIMDTernaryGetB(expressions[" << expressions[expr] + << "]);\n"; + } + + auto* expression = (Expression*)expr; + assert(expression->is<SIMDTernary>()); + return static_cast<SIMDTernary*>(expression)->b; +} +BinaryenExpressionRef BinaryenSIMDTernaryGetC(BinaryenExpressionRef expr) { + if (tracing) { + std::cout << " BinaryenSIMDTernaryGetC(expressions[" << expressions[expr] + << "]);\n"; } auto* expression = (Expression*)expr; - assert(expression->is<SIMDBitselect>()); - return static_cast<SIMDBitselect*>(expression)->cond; + assert(expression->is<SIMDTernary>()); + return static_cast<SIMDTernary*>(expression)->c; } // SIMDShift BinaryenOp BinaryenSIMDShiftGetOp(BinaryenExpressionRef expr) { diff --git a/src/binaryen-c.h b/src/binaryen-c.h index 451dcf23f..396ee2e8d 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -123,7 +123,7 @@ BinaryenExpressionId BinaryenAtomicFenceId(void); BinaryenExpressionId BinaryenSIMDExtractId(void); BinaryenExpressionId BinaryenSIMDReplaceId(void); BinaryenExpressionId BinaryenSIMDShuffleId(void); -BinaryenExpressionId BinaryenSIMDBitselectId(void); +BinaryenExpressionId BinaryenSIMDTernaryId(void); BinaryenExpressionId BinaryenSIMDShiftId(void); BinaryenExpressionId BinaryenMemoryInitId(void); BinaryenExpressionId BinaryenDataDropId(void); @@ -486,6 +486,8 @@ BinaryenOp BinaryenSubVecI64x2(void); BinaryenOp BinaryenAbsVecF32x4(void); BinaryenOp BinaryenNegVecF32x4(void); BinaryenOp BinaryenSqrtVecF32x4(void); +BinaryenOp BinaryenQFMAVecF32x4(void); +BinaryenOp BinaryenQFMSVecF32x4(void); BinaryenOp BinaryenAddVecF32x4(void); BinaryenOp BinaryenSubVecF32x4(void); BinaryenOp BinaryenMulVecF32x4(void); @@ -495,6 +497,8 @@ BinaryenOp BinaryenMaxVecF32x4(void); BinaryenOp BinaryenAbsVecF64x2(void); BinaryenOp BinaryenNegVecF64x2(void); BinaryenOp BinaryenSqrtVecF64x2(void); +BinaryenOp BinaryenQFMAVecF64x2(void); +BinaryenOp BinaryenQFMSVecF64x2(void); BinaryenOp BinaryenAddVecF64x2(void); BinaryenOp BinaryenSubVecF64x2(void); BinaryenOp BinaryenMulVecF64x2(void); @@ -687,10 +691,11 @@ BinaryenExpressionRef BinaryenSIMDShuffle(BinaryenModuleRef module, BinaryenExpressionRef left, BinaryenExpressionRef right, const uint8_t mask[16]); -BinaryenExpressionRef BinaryenSIMDBitselect(BinaryenModuleRef module, - BinaryenExpressionRef left, - BinaryenExpressionRef right, - BinaryenExpressionRef cond); +BinaryenExpressionRef BinaryenSIMDTernary(BinaryenModuleRef module, + BinaryenOp op, + BinaryenExpressionRef a, + BinaryenExpressionRef b, + BinaryenExpressionRef c); BinaryenExpressionRef BinaryenSIMDShift(BinaryenModuleRef module, BinaryenOp op, BinaryenExpressionRef vec, @@ -856,9 +861,10 @@ BinaryenExpressionRef BinaryenSIMDShuffleGetLeft(BinaryenExpressionRef expr); BinaryenExpressionRef BinaryenSIMDShuffleGetRight(BinaryenExpressionRef expr); void BinaryenSIMDShuffleGetMask(BinaryenExpressionRef expr, uint8_t* mask); -BinaryenExpressionRef BinaryenSIMDBitselectGetLeft(BinaryenExpressionRef expr); -BinaryenExpressionRef BinaryenSIMDBitselectGetRight(BinaryenExpressionRef expr); -BinaryenExpressionRef BinaryenSIMDBitselectGetCond(BinaryenExpressionRef expr); +BinaryenOp BinaryenSIMDTernaryGetOp(BinaryenExpressionRef expr); +BinaryenExpressionRef BinaryenSIMDTernaryGetA(BinaryenExpressionRef expr); +BinaryenExpressionRef BinaryenSIMDTernaryGetB(BinaryenExpressionRef expr); +BinaryenExpressionRef BinaryenSIMDTernaryGetC(BinaryenExpressionRef expr); BinaryenOp BinaryenSIMDShiftGetOp(BinaryenExpressionRef expr); BinaryenExpressionRef BinaryenSIMDShiftGetVec(BinaryenExpressionRef expr); diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index 68a8140a6..08d911aef 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 'q': { + switch (op[9]) { + case 'a': + if (strcmp(op, "f32x4.qfma") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::QFMAF32x4); } + goto parse_error; + case 's': + if (strcmp(op, "f32x4.qfms") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::QFMSF32x4); } + goto parse_error; + default: goto parse_error; + } + } case 'r': if (strcmp(op, "f32x4.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecF32x4, 4); } goto parse_error; @@ -608,6 +619,17 @@ switch (op[0]) { default: goto parse_error; } } + case 'q': { + switch (op[9]) { + case 'a': + if (strcmp(op, "f64x2.qfma") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::QFMAF64x2); } + goto parse_error; + case 's': + if (strcmp(op, "f64x2.qfms") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::QFMSF64x2); } + goto parse_error; + default: goto parse_error; + } + } case 'r': if (strcmp(op, "f64x2.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecF64x2, 2); } goto parse_error; @@ -2315,7 +2337,7 @@ switch (op[0]) { if (strcmp(op, "v128.and") == 0) { return makeBinary(s, BinaryOp::AndVec128); } goto parse_error; case 'b': - if (strcmp(op, "v128.bitselect") == 0) { return makeSIMDBitselect(s); } + if (strcmp(op, "v128.bitselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::Bitselect); } goto parse_error; case 'c': if (strcmp(op, "v128.const") == 0) { return makeConst(s, v128); } diff --git a/src/ir/ExpressionAnalyzer.cpp b/src/ir/ExpressionAnalyzer.cpp index a52d7af90..ee3cb0123 100644 --- a/src/ir/ExpressionAnalyzer.cpp +++ b/src/ir/ExpressionAnalyzer.cpp @@ -194,7 +194,7 @@ template<typename T> void visitImmediates(Expression* curr, T& visitor) { visitor.visitInt(x); } } - void visitSIMDBitselect(SIMDBitselect* curr) {} + void visitSIMDTernary(SIMDTernary* curr) { visitor.visitInt(curr->op); } void visitSIMDShift(SIMDShift* curr) { visitor.visitInt(curr->op); } void visitMemoryInit(MemoryInit* curr) { visitor.visitIndex(curr->segment); diff --git a/src/ir/ExpressionManipulator.cpp b/src/ir/ExpressionManipulator.cpp index 7b0ee29d7..7c4de4ceb 100644 --- a/src/ir/ExpressionManipulator.cpp +++ b/src/ir/ExpressionManipulator.cpp @@ -171,9 +171,9 @@ flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) { return builder.makeSIMDShuffle( copy(curr->left), copy(curr->right), curr->mask); } - Expression* visitSIMDBitselect(SIMDBitselect* curr) { - return builder.makeSIMDBitselect( - copy(curr->left), copy(curr->right), copy(curr->cond)); + Expression* visitSIMDTernary(SIMDTernary* curr) { + return builder.makeSIMDTernary( + curr->op, copy(curr->a), copy(curr->b), copy(curr->c)); } Expression* visitSIMDShift(SIMDShift* curr) { return builder.makeSIMDShift( diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp index 49b70684b..6c4e7a447 100644 --- a/src/ir/ReFinalize.cpp +++ b/src/ir/ReFinalize.cpp @@ -145,7 +145,7 @@ void ReFinalize::visitAtomicFence(AtomicFence* curr) { curr->finalize(); } void ReFinalize::visitSIMDExtract(SIMDExtract* curr) { curr->finalize(); } void ReFinalize::visitSIMDReplace(SIMDReplace* curr) { curr->finalize(); } void ReFinalize::visitSIMDShuffle(SIMDShuffle* curr) { curr->finalize(); } -void ReFinalize::visitSIMDBitselect(SIMDBitselect* curr) { curr->finalize(); } +void ReFinalize::visitSIMDTernary(SIMDTernary* curr) { curr->finalize(); } void ReFinalize::visitSIMDShift(SIMDShift* curr) { curr->finalize(); } void ReFinalize::visitMemoryInit(MemoryInit* curr) { curr->finalize(); } void ReFinalize::visitDataDrop(DataDrop* curr) { curr->finalize(); } diff --git a/src/ir/effects.h b/src/ir/effects.h index c175bed85..dcee4404b 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -305,7 +305,7 @@ struct EffectAnalyzer void visitSIMDExtract(SIMDExtract* curr) {} void visitSIMDReplace(SIMDReplace* curr) {} void visitSIMDShuffle(SIMDShuffle* curr) {} - void visitSIMDBitselect(SIMDBitselect* curr) {} + void visitSIMDTernary(SIMDTernary* curr) {} void visitSIMDShift(SIMDShift* curr) {} void visitMemoryInit(MemoryInit* curr) { writesMemory = true; diff --git a/src/ir/utils.h b/src/ir/utils.h index 43ba2fdde..4ca80caa3 100644 --- a/src/ir/utils.h +++ b/src/ir/utils.h @@ -132,7 +132,7 @@ struct ReFinalize void visitSIMDExtract(SIMDExtract* curr); void visitSIMDReplace(SIMDReplace* curr); void visitSIMDShuffle(SIMDShuffle* curr); - void visitSIMDBitselect(SIMDBitselect* curr); + void visitSIMDTernary(SIMDTernary* curr); void visitSIMDShift(SIMDShift* curr); void visitMemoryInit(MemoryInit* curr); void visitDataDrop(DataDrop* curr); @@ -196,7 +196,7 @@ struct ReFinalizeNode : public OverriddenVisitor<ReFinalizeNode> { void visitSIMDExtract(SIMDExtract* curr) { curr->finalize(); } void visitSIMDReplace(SIMDReplace* curr) { curr->finalize(); } void visitSIMDShuffle(SIMDShuffle* curr) { curr->finalize(); } - void visitSIMDBitselect(SIMDBitselect* curr) { curr->finalize(); } + void visitSIMDTernary(SIMDTernary* curr) { curr->finalize(); } void visitSIMDShift(SIMDShift* curr) { curr->finalize(); } void visitMemoryInit(MemoryInit* curr) { curr->finalize(); } void visitDataDrop(DataDrop* curr) { curr->finalize(); } diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 30a023b2c..bb5e4b21e 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -74,7 +74,7 @@ Module['AtomicFenceId'] = Module['_BinaryenAtomicFenceId'](); Module['SIMDExtractId'] = Module['_BinaryenSIMDExtractId'](); Module['SIMDReplaceId'] = Module['_BinaryenSIMDReplaceId'](); Module['SIMDShuffleId'] = Module['_BinaryenSIMDShuffleId'](); -Module['SIMDBitselectId'] = Module['_BinaryenSIMDBitselectId'](); +Module['SIMDTernaryId'] = Module['_BinaryenSIMDTernaryId'](); Module['SIMDShiftId'] = Module['_BinaryenSIMDShiftId'](); Module['MemoryInitId'] = Module['_BinaryenMemoryInitId'](); Module['DataDropId'] = Module['_BinaryenDataDropId'](); @@ -366,6 +366,8 @@ Module['SubVecI64x2'] = Module['_BinaryenSubVecI64x2'](); Module['AbsVecF32x4'] = Module['_BinaryenAbsVecF32x4'](); Module['NegVecF32x4'] = Module['_BinaryenNegVecF32x4'](); Module['SqrtVecF32x4'] = Module['_BinaryenSqrtVecF32x4'](); +Module['QFMAVecF32x4'] = Module['_BinaryenQFMAVecF32x4'](); +Module['QFMSVecF32x4'] = Module['_BinaryenQFMSVecF32x4'](); Module['AddVecF32x4'] = Module['_BinaryenAddVecF32x4'](); Module['SubVecF32x4'] = Module['_BinaryenSubVecF32x4'](); Module['MulVecF32x4'] = Module['_BinaryenMulVecF32x4'](); @@ -375,6 +377,8 @@ Module['MaxVecF32x4'] = Module['_BinaryenMaxVecF32x4'](); Module['AbsVecF64x2'] = Module['_BinaryenAbsVecF64x2'](); Module['NegVecF64x2'] = Module['_BinaryenNegVecF64x2'](); Module['SqrtVecF64x2'] = Module['_BinaryenSqrtVecF64x2'](); +Module['QFMAVecF64x2'] = Module['_BinaryenQFMAVecF64x2'](); +Module['QFMSVecF64x2'] = Module['_BinaryenQFMSVecF64x2'](); Module['AddVecF64x2'] = Module['_BinaryenAddVecF64x2'](); Module['SubVecF64x2'] = Module['_BinaryenSubVecF64x2'](); Module['MulVecF64x2'] = Module['_BinaryenMulVecF64x2'](); @@ -1323,7 +1327,7 @@ function wrapModule(module, self) { return Module['_BinaryenUnary'](module, Module['XorVec128'], value); }, 'bitselect': function(left, right, cond) { - return Module['_BinaryenSIMDBitselect'](module, left, right, cond); + return Module['_BinaryenSIMDTernary'](module, Module['Bitselect'], left, right, cond); }, 'pop': function() { return Module['_BinaryenPop'](module, Module['v128']); @@ -1660,6 +1664,12 @@ function wrapModule(module, self) { 'sqrt': function(value) { return Module['_BinaryenUnary'](module, Module['SqrtVecF32x4'], value); }, + 'qfma': function(a, b, c) { + return Module['_BinaryenSIMDTernary'](module, Module['QFMAVecF32x4'], a, b, c); + }, + 'qfms': function(a, b, c) { + return Module['_BinaryenSIMDTernary'](module, Module['QFMSVecF32x4'], a, b, c); + }, 'add': function(left, right) { return Module['_BinaryenBinary'](module, Module['AddVecF32x4'], left, right); }, @@ -1723,6 +1733,12 @@ function wrapModule(module, self) { 'sqrt': function(value) { return Module['_BinaryenUnary'](module, Module['SqrtVecF64x2'], value); }, + 'qfma': function(a, b, c) { + return Module['_BinaryenSIMDTernary'](module, Module['QFMAVecF64x2'], a, b, c); + }, + 'qfms': function(a, b, c) { + return Module['_BinaryenSIMDTernary'](module, Module['QFMSVecF64x2'], a, b, c); + }, 'add': function(left, right) { return Module['_BinaryenBinary'](module, Module['AddVecF64x2'], left, right); }, @@ -2370,13 +2386,14 @@ Module['getExpressionInfo'] = function(expr) { 'mask': mask }; }); - case Module['SIMDBitselectId']: + case Module['SIMDTernaryId']: return { 'id': id, 'type': type, - 'left': Module['_BinaryenSIMDBitselectGetLeft'](expr), - 'right': Module['_BinaryenSIMDBitselectGetRight'](expr), - 'cond': Module['_BinaryenSIMDBitselectGetCond'](expr) + 'op': Module['_BinaryenSIMDTernaryGetOp'](expr), + 'a': Module['_BinaryenSIMDTernaryGetA'](expr), + 'b': Module['_BinaryenSIMDTernaryGetB'](expr), + 'c': Module['_BinaryenSIMDTernaryGetC'](expr) }; case Module['SIMDShiftId']: return { diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp index 464451763..1d13ed67c 100644 --- a/src/passes/DeadCodeElimination.cpp +++ b/src/passes/DeadCodeElimination.cpp @@ -306,8 +306,8 @@ struct DeadCodeElimination DELEGATE(SIMDReplace); case Expression::Id::SIMDShuffleId: DELEGATE(SIMDShuffle); - case Expression::Id::SIMDBitselectId: - DELEGATE(SIMDBitselect); + case Expression::Id::SIMDTernaryId: + DELEGATE(SIMDTernary); case Expression::Id::SIMDShiftId: DELEGATE(SIMDShift); case Expression::Id::MemoryInitId: diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index b1e1240ae..ad4d20bae 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -330,9 +330,25 @@ struct PrintExpressionContents o << " " << std::to_string(mask_index); } } - void visitSIMDBitselect(SIMDBitselect* curr) { + void visitSIMDTernary(SIMDTernary* curr) { prepareColor(o); - o << "v128.bitselect"; + switch (curr->op) { + case Bitselect: + o << "v128.bitselect"; + break; + case QFMAF32x4: + o << "f32x4.qfma"; + break; + case QFMSF32x4: + o << "f32x4.qfms"; + break; + case QFMAF64x2: + o << "f64x2.qfma"; + break; + case QFMSF64x2: + o << "f64x2.qfms"; + break; + } } void visitSIMDShift(SIMDShift* curr) { prepareColor(o); @@ -1534,13 +1550,13 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> { printFullLine(curr->right); decIndent(); } - void visitSIMDBitselect(SIMDBitselect* curr) { + void visitSIMDTernary(SIMDTernary* curr) { o << '('; PrintExpressionContents(currFunction, o).visit(curr); incIndent(); - printFullLine(curr->left); - printFullLine(curr->right); - printFullLine(curr->cond); + printFullLine(curr->a); + printFullLine(curr->b); + printFullLine(curr->c); decIndent(); } void visitSIMDShift(SIMDShift* curr) { diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index dde8a0de7..82a269740 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -2336,7 +2336,7 @@ private: case 3: return makeSIMDShuffle(); case 4: - return makeSIMDBitselect(); + return makeSIMDTernary(); case 5: return makeSIMDShift(); } @@ -2444,11 +2444,18 @@ private: return builder.makeSIMDShuffle(left, right, mask); } - Expression* makeSIMDBitselect() { - Expression* left = make(v128); - Expression* right = make(v128); - Expression* cond = make(v128); - return builder.makeSIMDBitselect(left, right, cond); + Expression* makeSIMDTernary() { + // TODO: Enable qfma/qfms once it is implemented in V8 and the interpreter + // SIMDTernaryOp op = pick(Bitselect, + // QFMAF32x4, + // QFMSF32x4, + // QFMAF64x2, + // QFMSF64x2); + SIMDTernaryOp op = Bitselect; + Expression* a = make(v128); + Expression* b = make(v128); + Expression* c = make(v128); + return builder.makeSIMDTernary(op, a, b, c); } Expression* makeSIMDShift() { diff --git a/src/wasm-binary.h b/src/wasm-binary.h index b3ac336ee..1c5fa774a 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -829,6 +829,8 @@ enum ASTNodes { F32x4Abs = 0x95, F32x4Neg = 0x96, F32x4Sqrt = 0x97, + F32x4QFMA = 0x98, + F32x4QFMS = 0x99, F32x4Add = 0x9a, F32x4Sub = 0x9b, F32x4Mul = 0x9c, @@ -838,6 +840,8 @@ enum ASTNodes { F64x2Abs = 0xa0, F64x2Neg = 0xa1, F64x2Sqrt = 0xa2, + F64x2QFMA = 0xa3, + F64x2QFMS = 0xa4, F64x2Add = 0xa5, F64x2Sub = 0xa6, F64x2Mul = 0xa7, @@ -1246,7 +1250,7 @@ public: bool maybeVisitSIMDExtract(Expression*& out, uint32_t code); bool maybeVisitSIMDReplace(Expression*& out, uint32_t code); bool maybeVisitSIMDShuffle(Expression*& out, uint32_t code); - bool maybeVisitSIMDBitselect(Expression*& out, uint32_t code); + bool maybeVisitSIMDTernary(Expression*& out, uint32_t code); bool maybeVisitSIMDShift(Expression*& out, uint32_t code); bool maybeVisitMemoryInit(Expression*& out, uint32_t code); bool maybeVisitDataDrop(Expression*& out, uint32_t code); diff --git a/src/wasm-builder.h b/src/wasm-builder.h index 3e61b1a36..c2f1e41b6 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -400,12 +400,15 @@ public: ret->finalize(); return ret; } - SIMDBitselect* - makeSIMDBitselect(Expression* left, Expression* right, Expression* cond) { - auto* ret = allocator.alloc<SIMDBitselect>(); - ret->left = left; - ret->right = right; - ret->cond = cond; + SIMDTernary* makeSIMDTernary(SIMDTernaryOp op, + Expression* a, + Expression* b, + Expression* c) { + auto* ret = allocator.alloc<SIMDTernary>(); + ret->op = op; + ret->a = a; + ret->b = b; + ret->c = c; ret->finalize(); return ret; } diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index d854b20d3..2c4496f3f 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -863,24 +863,30 @@ public: Literal right = flow.value; return left.shuffleV8x16(right, curr->mask); } - Flow visitSIMDBitselect(SIMDBitselect* curr) { + Flow visitSIMDTernary(SIMDTernary* curr) { NOTE_ENTER("SIMDBitselect"); - Flow flow = this->visit(curr->left); + Flow flow = this->visit(curr->a); if (flow.breaking()) { return flow; } - Literal left = flow.value; - flow = this->visit(curr->right); + Literal a = flow.value; + flow = this->visit(curr->b); if (flow.breaking()) { return flow; } - Literal right = flow.value; - flow = this->visit(curr->cond); + Literal b = flow.value; + flow = this->visit(curr->c); if (flow.breaking()) { return flow; } - Literal cond = flow.value; - return cond.bitselectV128(left, right); + Literal c = flow.value; + switch (curr->op) { + case Bitselect: + return c.bitselectV128(a, b); + default: + // TODO: implement qfma/qfms + WASM_UNREACHABLE(); + } } Flow visitSIMDShift(SIMDShift* curr) { NOTE_ENTER("SIMDShift"); diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index b6ef320d5..67035f0ff 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -198,7 +198,7 @@ private: Expression* makeSIMDExtract(Element& s, SIMDExtractOp op, size_t lanes); Expression* makeSIMDReplace(Element& s, SIMDReplaceOp op, size_t lanes); Expression* makeSIMDShuffle(Element& s); - Expression* makeSIMDBitselect(Element& s); + Expression* makeSIMDTernary(Element& s, SIMDTernaryOp op); Expression* makeSIMDShift(Element& s, SIMDShiftOp op); Expression* makeMemoryInit(Element& s); Expression* makeDataDrop(Element& s); diff --git a/src/wasm-stack.h b/src/wasm-stack.h index 3a7d7c38e..4b0ffde40 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -107,7 +107,7 @@ public: void visitSIMDExtract(SIMDExtract* curr); void visitSIMDReplace(SIMDReplace* curr); void visitSIMDShuffle(SIMDShuffle* curr); - void visitSIMDBitselect(SIMDBitselect* curr); + void visitSIMDTernary(SIMDTernary* curr); void visitSIMDShift(SIMDShift* curr); void visitMemoryInit(MemoryInit* curr); void visitDataDrop(DataDrop* curr); @@ -183,7 +183,7 @@ public: void visitSIMDExtract(SIMDExtract* curr); void visitSIMDReplace(SIMDReplace* curr); void visitSIMDShuffle(SIMDShuffle* curr); - void visitSIMDBitselect(SIMDBitselect* curr); + void visitSIMDTernary(SIMDTernary* curr); void visitSIMDShift(SIMDShift* curr); void visitMemoryInit(MemoryInit* curr); void visitDataDrop(DataDrop* curr); @@ -565,10 +565,10 @@ void BinaryenIRWriter<SubType>::visitSIMDShuffle(SIMDShuffle* curr) { } template<typename SubType> -void BinaryenIRWriter<SubType>::visitSIMDBitselect(SIMDBitselect* curr) { - visit(curr->left); - visit(curr->right); - visit(curr->cond); +void BinaryenIRWriter<SubType>::visitSIMDTernary(SIMDTernary* curr) { + visit(curr->a); + visit(curr->b); + visit(curr->c); if (curr->type == unreachable) { emitUnreachable(); return; diff --git a/src/wasm-traversal.h b/src/wasm-traversal.h index 202d136c8..06ab69615 100644 --- a/src/wasm-traversal.h +++ b/src/wasm-traversal.h @@ -58,7 +58,7 @@ template<typename SubType, typename ReturnType = void> struct Visitor { ReturnType visitSIMDExtract(SIMDExtract* curr) { return ReturnType(); } ReturnType visitSIMDReplace(SIMDReplace* curr) { return ReturnType(); } ReturnType visitSIMDShuffle(SIMDShuffle* curr) { return ReturnType(); } - ReturnType visitSIMDBitselect(SIMDBitselect* curr) { return ReturnType(); } + ReturnType visitSIMDTernary(SIMDTernary* curr) { return ReturnType(); } ReturnType visitSIMDShift(SIMDShift* curr) { return ReturnType(); } ReturnType visitMemoryInit(MemoryInit* curr) { return ReturnType(); } ReturnType visitDataDrop(DataDrop* curr) { return ReturnType(); } @@ -139,8 +139,8 @@ template<typename SubType, typename ReturnType = void> struct Visitor { DELEGATE(SIMDReplace); case Expression::Id::SIMDShuffleId: DELEGATE(SIMDShuffle); - case Expression::Id::SIMDBitselectId: - DELEGATE(SIMDBitselect); + case Expression::Id::SIMDTernaryId: + DELEGATE(SIMDTernary); case Expression::Id::SIMDShiftId: DELEGATE(SIMDShift); case Expression::Id::MemoryInitId: @@ -225,7 +225,7 @@ struct OverriddenVisitor { UNIMPLEMENTED(SIMDExtract); UNIMPLEMENTED(SIMDReplace); UNIMPLEMENTED(SIMDShuffle); - UNIMPLEMENTED(SIMDBitselect); + UNIMPLEMENTED(SIMDTernary); UNIMPLEMENTED(SIMDShift); UNIMPLEMENTED(MemoryInit); UNIMPLEMENTED(DataDrop); @@ -307,8 +307,8 @@ struct OverriddenVisitor { DELEGATE(SIMDReplace); case Expression::Id::SIMDShuffleId: DELEGATE(SIMDShuffle); - case Expression::Id::SIMDBitselectId: - DELEGATE(SIMDBitselect); + case Expression::Id::SIMDTernaryId: + DELEGATE(SIMDTernary); case Expression::Id::SIMDShiftId: DELEGATE(SIMDShift); case Expression::Id::MemoryInitId: @@ -430,7 +430,7 @@ struct UnifiedExpressionVisitor : public Visitor<SubType, ReturnType> { ReturnType visitSIMDShuffle(SIMDShuffle* curr) { return static_cast<SubType*>(this)->visitExpression(curr); } - ReturnType visitSIMDBitselect(SIMDBitselect* curr) { + ReturnType visitSIMDTernary(SIMDTernary* curr) { return static_cast<SubType*>(this)->visitExpression(curr); } ReturnType visitSIMDShift(SIMDShift* curr) { @@ -732,8 +732,8 @@ struct Walker : public VisitorType { static void doVisitSIMDShuffle(SubType* self, Expression** currp) { self->visitSIMDShuffle((*currp)->cast<SIMDShuffle>()); } - static void doVisitSIMDBitselect(SubType* self, Expression** currp) { - self->visitSIMDBitselect((*currp)->cast<SIMDBitselect>()); + static void doVisitSIMDTernary(SubType* self, Expression** currp) { + self->visitSIMDTernary((*currp)->cast<SIMDTernary>()); } static void doVisitSIMDShift(SubType* self, Expression** currp) { self->visitSIMDShift((*currp)->cast<SIMDShift>()); @@ -946,11 +946,11 @@ struct PostWalker : public Walker<SubType, VisitorType> { self->pushTask(SubType::scan, &curr->cast<SIMDShuffle>()->left); break; } - case Expression::Id::SIMDBitselectId: { - self->pushTask(SubType::doVisitSIMDBitselect, currp); - self->pushTask(SubType::scan, &curr->cast<SIMDBitselect>()->cond); - self->pushTask(SubType::scan, &curr->cast<SIMDBitselect>()->right); - self->pushTask(SubType::scan, &curr->cast<SIMDBitselect>()->left); + case Expression::Id::SIMDTernaryId: { + self->pushTask(SubType::doVisitSIMDTernary, currp); + self->pushTask(SubType::scan, &curr->cast<SIMDTernary>()->c); + self->pushTask(SubType::scan, &curr->cast<SIMDTernary>()->b); + self->pushTask(SubType::scan, &curr->cast<SIMDTernary>()->a); break; } case Expression::Id::SIMDShiftId: { diff --git a/src/wasm.h b/src/wasm.h index e7d83ace3..9c0f5dec8 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -417,6 +417,8 @@ enum SIMDShiftOp { ShrUVecI64x2 }; +enum SIMDTernaryOp { Bitselect, QFMAF32x4, QFMSF32x4, QFMAF64x2, QFMSF64x2 }; + // // Expressions // @@ -472,7 +474,7 @@ public: SIMDExtractId, SIMDReplaceId, SIMDShuffleId, - SIMDBitselectId, + SIMDTernaryId, SIMDShiftId, MemoryInitId, DataDropId, @@ -834,14 +836,15 @@ public: void finalize(); }; -class SIMDBitselect : public SpecificExpression<Expression::SIMDBitselectId> { +class SIMDTernary : public SpecificExpression<Expression::SIMDTernaryId> { public: - SIMDBitselect() = default; - SIMDBitselect(MixedArena& allocator) : SIMDBitselect() {} + SIMDTernary() = default; + SIMDTernary(MixedArena& allocator) : SIMDTernary() {} - Expression* left; - Expression* right; - Expression* cond; + SIMDTernaryOp op; + Expression* a; + Expression* b; + Expression* c; void finalize(); }; diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index b7daeda5a..529a3ff52 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -2355,7 +2355,7 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { if (maybeVisitSIMDShuffle(curr, opcode)) { break; } - if (maybeVisitSIMDBitselect(curr, opcode)) { + if (maybeVisitSIMDTernary(curr, opcode)) { break; } if (maybeVisitSIMDShift(curr, opcode)) { @@ -4251,15 +4251,35 @@ bool WasmBinaryBuilder::maybeVisitSIMDShuffle(Expression*& out, uint32_t code) { return true; } -bool WasmBinaryBuilder::maybeVisitSIMDBitselect(Expression*& out, - uint32_t code) { - if (code != BinaryConsts::V128Bitselect) { - return false; +bool WasmBinaryBuilder::maybeVisitSIMDTernary(Expression*& out, uint32_t code) { + SIMDTernary* curr; + switch (code) { + case BinaryConsts::V128Bitselect: + curr = allocator.alloc<SIMDTernary>(); + curr->op = Bitselect; + break; + case BinaryConsts::F32x4QFMA: + curr = allocator.alloc<SIMDTernary>(); + curr->op = QFMAF32x4; + break; + case BinaryConsts::F32x4QFMS: + curr = allocator.alloc<SIMDTernary>(); + curr->op = QFMSF32x4; + break; + case BinaryConsts::F64x2QFMA: + curr = allocator.alloc<SIMDTernary>(); + curr->op = QFMAF64x2; + break; + case BinaryConsts::F64x2QFMS: + curr = allocator.alloc<SIMDTernary>(); + curr->op = QFMSF64x2; + break; + default: + return false; } - auto* curr = allocator.alloc<SIMDBitselect>(); - curr->cond = popNonVoidExpression(); - curr->right = popNonVoidExpression(); - curr->left = popNonVoidExpression(); + curr->c = popNonVoidExpression(); + curr->b = popNonVoidExpression(); + curr->a = popNonVoidExpression(); curr->finalize(); out = curr; return true; diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 3a1e0db09..322c36c45 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -1473,11 +1473,13 @@ Expression* SExpressionWasmBuilder::makeSIMDShuffle(Element& s) { return ret; } -Expression* SExpressionWasmBuilder::makeSIMDBitselect(Element& s) { - auto ret = allocator.alloc<SIMDBitselect>(); - ret->left = parseExpression(s[1]); - ret->right = parseExpression(s[2]); - ret->cond = parseExpression(s[3]); +Expression* SExpressionWasmBuilder::makeSIMDTernary(Element& s, + SIMDTernaryOp op) { + auto ret = allocator.alloc<SIMDTernary>(); + ret->op = op; + ret->a = parseExpression(s[1]); + ret->b = parseExpression(s[2]); + ret->c = parseExpression(s[3]); ret->finalize(); return ret; } diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index faa06330b..498a53cb2 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -491,8 +491,25 @@ void BinaryInstWriter::visitSIMDShuffle(SIMDShuffle* curr) { } } -void BinaryInstWriter::visitSIMDBitselect(SIMDBitselect* curr) { - o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::V128Bitselect); +void BinaryInstWriter::visitSIMDTernary(SIMDTernary* curr) { + o << int8_t(BinaryConsts::SIMDPrefix); + switch (curr->op) { + case Bitselect: + o << U32LEB(BinaryConsts::V128Bitselect); + break; + case QFMAF32x4: + o << U32LEB(BinaryConsts::F32x4QFMA); + break; + case QFMSF32x4: + o << U32LEB(BinaryConsts::F32x4QFMS); + break; + case QFMAF64x2: + o << U32LEB(BinaryConsts::F64x2QFMA); + break; + case QFMSF64x2: + o << U32LEB(BinaryConsts::F64x2QFMS); + break; + } } void BinaryInstWriter::visitSIMDShift(SIMDShift* curr) { diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 9b1220371..f2d6c259b 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -274,7 +274,7 @@ public: void visitSIMDExtract(SIMDExtract* curr); void visitSIMDReplace(SIMDReplace* curr); void visitSIMDShuffle(SIMDShuffle* curr); - void visitSIMDBitselect(SIMDBitselect* curr); + void visitSIMDTernary(SIMDTernary* curr); void visitSIMDShift(SIMDShift* curr); void visitMemoryInit(MemoryInit* curr); void visitDataDrop(DataDrop* curr); @@ -1030,17 +1030,17 @@ void FunctionValidator::visitSIMDShuffle(SIMDShuffle* curr) { } } -void FunctionValidator::visitSIMDBitselect(SIMDBitselect* curr) { +void FunctionValidator::visitSIMDTernary(SIMDTernary* curr) { shouldBeTrue( getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)"); shouldBeEqualOrFirstIsUnreachable( - curr->type, v128, curr, "v128.bitselect must have type v128"); + curr->type, v128, curr, "SIMD ternary must have type v128"); shouldBeEqualOrFirstIsUnreachable( - curr->left->type, v128, curr, "expected operand of type v128"); + curr->a->type, v128, curr, "expected operand of type v128"); shouldBeEqualOrFirstIsUnreachable( - curr->right->type, v128, curr, "expected operand of type v128"); + curr->b->type, v128, curr, "expected operand of type v128"); shouldBeEqualOrFirstIsUnreachable( - curr->cond->type, v128, curr, "expected operand of type v128"); + curr->c->type, v128, curr, "expected operand of type v128"); } void FunctionValidator::visitSIMDShift(SIMDShift* curr) { diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index 1a47327c1..a0b845446 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -157,8 +157,8 @@ const char* getExpressionName(Expression* curr) { return "simd_replace"; case Expression::Id::SIMDShuffleId: return "simd_shuffle"; - case Expression::Id::SIMDBitselectId: - return "simd_bitselect"; + case Expression::Id::SIMDTernaryId: + return "simd_ternary"; case Expression::Id::SIMDShiftId: return "simd_shift"; case Expression::Id::MemoryInitId: @@ -582,11 +582,11 @@ void SIMDShuffle::finalize() { } } -void SIMDBitselect::finalize() { - assert(left && right && cond); +void SIMDTernary::finalize() { + assert(a && b && c); type = v128; - if (left->type == unreachable || right->type == unreachable || - cond->type == unreachable) { + if (a->type == unreachable || b->type == unreachable || + c->type == unreachable) { type = unreachable; } } diff --git a/src/wasm2js.h b/src/wasm2js.h index 1526dbb89..95ba2e154 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -1832,7 +1832,7 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, unimplemented(curr); WASM_UNREACHABLE(); } - Ref visitSIMDBitselect(SIMDBitselect* curr) { + Ref visitSIMDTernary(SIMDTernary* curr) { unimplemented(curr); WASM_UNREACHABLE(); } |