Skip to content

Commit

Permalink
Prototype new SIMD multiplications
Browse files Browse the repository at this point in the history
Including saturating, rounding Q15 multiplication as proposed in
WebAssembly/simd#365 and extending multiplications as
proposed in WebAssembly/simd#376. Since these are just
prototypes, skips adding them to the C or JS APIs and the fuzzer, as well as
implementing them in the interpreter.
  • Loading branch information
tlively committed Oct 27, 2020
1 parent 6c28516 commit bb008a0
Show file tree
Hide file tree
Showing 19 changed files with 840 additions and 106 deletions.
13 changes: 13 additions & 0 deletions scripts/gen-s-parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,11 @@
("i16x8.max_s", "makeBinary(s, BinaryOp::MaxSVecI16x8)"),
("i16x8.max_u", "makeBinary(s, BinaryOp::MaxUVecI16x8)"),
("i16x8.avgr_u", "makeBinary(s, BinaryOp::AvgrUVecI16x8)"),
("i16x8.q15mulr_sat_s", "makeBinary(s, BinaryOp::Q15MulrSatSVecI16x8)"),
("i16x8.extmul_low_i8x16_s", "makeBinary(s, BinaryOp::ExtMulLowSVecI16x8)"),
("i16x8.extmul_high_i8x16_s", "makeBinary(s, BinaryOp::ExtMulHighSVecI16x8)"),
("i16x8.extmul_low_i8x16_u", "makeBinary(s, BinaryOp::ExtMulLowUVecI16x8)"),
("i16x8.extmul_high_i8x16_u", "makeBinary(s, BinaryOp::ExtMulHighUVecI16x8)"),
("i32x4.abs", "makeUnary(s, UnaryOp::AbsVecI32x4)"),
("i32x4.neg", "makeUnary(s, UnaryOp::NegVecI32x4)"),
("i32x4.any_true", "makeUnary(s, UnaryOp::AnyTrueVecI32x4)"),
Expand All @@ -415,6 +420,10 @@
("i32x4.max_s", "makeBinary(s, BinaryOp::MaxSVecI32x4)"),
("i32x4.max_u", "makeBinary(s, BinaryOp::MaxUVecI32x4)"),
("i32x4.dot_i16x8_s", "makeBinary(s, BinaryOp::DotSVecI16x8ToVecI32x4)"),
("i32x4.extmul_low_i16x8_s", "makeBinary(s, BinaryOp::ExtMulLowSVecI32x4)"),
("i32x4.extmul_high_i16x8_s", "makeBinary(s, BinaryOp::ExtMulHighSVecI32x4)"),
("i32x4.extmul_low_i16x8_u", "makeBinary(s, BinaryOp::ExtMulLowUVecI32x4)"),
("i32x4.extmul_high_i16x8_u", "makeBinary(s, BinaryOp::ExtMulHighUVecI32x4)"),
("i64x2.neg", "makeUnary(s, UnaryOp::NegVecI64x2)"),
("i64x2.any_true", "makeUnary(s, UnaryOp::AnyTrueVecI64x2)"),
("i64x2.all_true", "makeUnary(s, UnaryOp::AllTrueVecI64x2)"),
Expand All @@ -424,6 +433,10 @@
("i64x2.add", "makeBinary(s, BinaryOp::AddVecI64x2)"),
("i64x2.sub", "makeBinary(s, BinaryOp::SubVecI64x2)"),
("i64x2.mul", "makeBinary(s, BinaryOp::MulVecI64x2)"),
("i64x2.extmul_low_i32x4_s", "makeBinary(s, BinaryOp::ExtMulLowSVecI64x2)"),
("i64x2.extmul_high_i32x4_s", "makeBinary(s, BinaryOp::ExtMulHighSVecI64x2)"),
("i64x2.extmul_low_i32x4_u", "makeBinary(s, BinaryOp::ExtMulLowUVecI64x2)"),
("i64x2.extmul_high_i32x4_u", "makeBinary(s, BinaryOp::ExtMulHighUVecI64x2)"),
("f32x4.abs", "makeUnary(s, UnaryOp::AbsVecF32x4)"),
("f32x4.neg", "makeUnary(s, UnaryOp::NegVecF32x4)"),
("f32x4.sqrt", "makeUnary(s, UnaryOp::SqrtVecF32x4)"),
Expand Down
4 changes: 3 additions & 1 deletion src/binaryen-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ BINARYEN_API BinaryenOp BinaryenOrVec128(void);
BINARYEN_API BinaryenOp BinaryenXorVec128(void);
BINARYEN_API BinaryenOp BinaryenAndNotVec128(void);
BINARYEN_API BinaryenOp BinaryenBitselectVec128(void);
// TODO: Add i8x16.popcnt to C and JS APIs once merged to proposal
// TODO: Add i8x16.popcnt to C and JS APIs once merged to the proposal
BINARYEN_API BinaryenOp BinaryenAbsVecI8x16(void);
BINARYEN_API BinaryenOp BinaryenNegVecI8x16(void);
BINARYEN_API BinaryenOp BinaryenAnyTrueVecI8x16(void);
Expand Down Expand Up @@ -526,6 +526,8 @@ BINARYEN_API BinaryenOp BinaryenMinUVecI16x8(void);
BINARYEN_API BinaryenOp BinaryenMaxSVecI16x8(void);
BINARYEN_API BinaryenOp BinaryenMaxUVecI16x8(void);
BINARYEN_API BinaryenOp BinaryenAvgrUVecI16x8(void);
// TODO: Add i16x8.q15mulr_sat_s to C and JS APIs once merged to the proposal
// TODO: Add extending multiplications to APIs once they are merged as well
BINARYEN_API BinaryenOp BinaryenAbsVecI32x4(void);
BINARYEN_API BinaryenOp BinaryenNegVecI32x4(void);
BINARYEN_API BinaryenOp BinaryenAnyTrueVecI32x4(void);
Expand Down
125 changes: 112 additions & 13 deletions src/gen-s-parser.inc
Original file line number Diff line number Diff line change
Expand Up @@ -799,13 +799,45 @@ switch (op[0]) {
if (strcmp(op, "i16x8.eq") == 0) { return makeBinary(s, BinaryOp::EqVecI16x8); }
goto parse_error;
case 'x': {
switch (op[19]) {
case 's':
if (strcmp(op, "i16x8.extract_lane_s") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneSVecI16x8, 8); }
goto parse_error;
case 'u':
if (strcmp(op, "i16x8.extract_lane_u") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneUVecI16x8, 8); }
goto parse_error;
switch (op[9]) {
case 'm': {
switch (op[13]) {
case 'h': {
switch (op[24]) {
case 's':
if (strcmp(op, "i16x8.extmul_high_i8x16_s") == 0) { return makeBinary(s, BinaryOp::ExtMulHighSVecI16x8); }
goto parse_error;
case 'u':
if (strcmp(op, "i16x8.extmul_high_i8x16_u") == 0) { return makeBinary(s, BinaryOp::ExtMulHighUVecI16x8); }
goto parse_error;
default: goto parse_error;
}
}
case 'l': {
switch (op[23]) {
case 's':
if (strcmp(op, "i16x8.extmul_low_i8x16_s") == 0) { return makeBinary(s, BinaryOp::ExtMulLowSVecI16x8); }
goto parse_error;
case 'u':
if (strcmp(op, "i16x8.extmul_low_i8x16_u") == 0) { return makeBinary(s, BinaryOp::ExtMulLowUVecI16x8); }
goto parse_error;
default: goto parse_error;
}
}
default: goto parse_error;
}
}
case 'r': {
switch (op[19]) {
case 's':
if (strcmp(op, "i16x8.extract_lane_s") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneSVecI16x8, 8); }
goto parse_error;
case 'u':
if (strcmp(op, "i16x8.extract_lane_u") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneUVecI16x8, 8); }
goto parse_error;
default: goto parse_error;
}
}
default: goto parse_error;
}
}
Expand Down Expand Up @@ -934,6 +966,9 @@ switch (op[0]) {
default: goto parse_error;
}
}
case 'q':
if (strcmp(op, "i16x8.q15mulr_sat_s") == 0) { return makeBinary(s, BinaryOp::Q15MulrSatSVecI16x8); }
goto parse_error;
case 'r':
if (strcmp(op, "i16x8.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI16x8, 8); }
goto parse_error;
Expand Down Expand Up @@ -1520,9 +1555,41 @@ switch (op[0]) {
case 'q':
if (strcmp(op, "i32x4.eq") == 0) { return makeBinary(s, BinaryOp::EqVecI32x4); }
goto parse_error;
case 'x':
if (strcmp(op, "i32x4.extract_lane") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecI32x4, 4); }
goto parse_error;
case 'x': {
switch (op[9]) {
case 'm': {
switch (op[13]) {
case 'h': {
switch (op[24]) {
case 's':
if (strcmp(op, "i32x4.extmul_high_i16x8_s") == 0) { return makeBinary(s, BinaryOp::ExtMulHighSVecI32x4); }
goto parse_error;
case 'u':
if (strcmp(op, "i32x4.extmul_high_i16x8_u") == 0) { return makeBinary(s, BinaryOp::ExtMulHighUVecI32x4); }
goto parse_error;
default: goto parse_error;
}
}
case 'l': {
switch (op[23]) {
case 's':
if (strcmp(op, "i32x4.extmul_low_i16x8_s") == 0) { return makeBinary(s, BinaryOp::ExtMulLowSVecI32x4); }
goto parse_error;
case 'u':
if (strcmp(op, "i32x4.extmul_low_i16x8_u") == 0) { return makeBinary(s, BinaryOp::ExtMulLowUVecI32x4); }
goto parse_error;
default: goto parse_error;
}
}
default: goto parse_error;
}
}
case 'r':
if (strcmp(op, "i32x4.extract_lane") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecI32x4, 4); }
goto parse_error;
default: goto parse_error;
}
}
default: goto parse_error;
}
}
Expand Down Expand Up @@ -2251,9 +2318,41 @@ switch (op[0]) {
default: goto parse_error;
}
}
case 'e':
if (strcmp(op, "i64x2.extract_lane") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecI64x2, 2); }
goto parse_error;
case 'e': {
switch (op[9]) {
case 'm': {
switch (op[13]) {
case 'h': {
switch (op[24]) {
case 's':
if (strcmp(op, "i64x2.extmul_high_i32x4_s") == 0) { return makeBinary(s, BinaryOp::ExtMulHighSVecI64x2); }
goto parse_error;
case 'u':
if (strcmp(op, "i64x2.extmul_high_i32x4_u") == 0) { return makeBinary(s, BinaryOp::ExtMulHighUVecI64x2); }
goto parse_error;
default: goto parse_error;
}
}
case 'l': {
switch (op[23]) {
case 's':
if (strcmp(op, "i64x2.extmul_low_i32x4_s") == 0) { return makeBinary(s, BinaryOp::ExtMulLowSVecI64x2); }
goto parse_error;
case 'u':
if (strcmp(op, "i64x2.extmul_low_i32x4_u") == 0) { return makeBinary(s, BinaryOp::ExtMulLowUVecI64x2); }
goto parse_error;
default: goto parse_error;
}
}
default: goto parse_error;
}
}
case 'r':
if (strcmp(op, "i64x2.extract_lane") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecI64x2, 2); }
goto parse_error;
default: goto parse_error;
}
}
case 'l': {
switch (op[15]) {
case 's':
Expand Down
39 changes: 39 additions & 0 deletions src/ir/cost.h
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,21 @@ struct CostAnalyzer : public Visitor<CostAnalyzer, Index> {
case AvgrUVecI16x8:
ret = 1;
break;
case Q15MulrSatSVecI16x8:
ret = 1;
break;
case ExtMulLowSVecI16x8:
ret = 1;
break;
case ExtMulHighSVecI16x8:
ret = 1;
break;
case ExtMulLowUVecI16x8:
ret = 1;
break;
case ExtMulHighUVecI16x8:
ret = 1;
break;
case AddVecI32x4:
ret = 1;
break;
Expand All @@ -672,6 +687,18 @@ struct CostAnalyzer : public Visitor<CostAnalyzer, Index> {
case DotSVecI16x8ToVecI32x4:
ret = 1;
break;
case ExtMulLowSVecI32x4:
ret = 1;
break;
case ExtMulHighSVecI32x4:
ret = 1;
break;
case ExtMulLowUVecI32x4:
ret = 1;
break;
case ExtMulHighUVecI32x4:
ret = 1;
break;
case AddVecI64x2:
ret = 1;
break;
Expand All @@ -681,6 +708,18 @@ struct CostAnalyzer : public Visitor<CostAnalyzer, Index> {
case MulVecI64x2:
ret = 1;
break;
case ExtMulLowSVecI64x2:
ret = 1;
break;
case ExtMulHighSVecI64x2:
ret = 1;
break;
case ExtMulLowUVecI64x2:
ret = 1;
break;
case ExtMulHighUVecI64x2:
ret = 1;
break;
case AddVecF32x4:
ret = 1;
break;
Expand Down
13 changes: 13 additions & 0 deletions src/literal.h
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,11 @@ class Literal {
Literal maxSI16x8(const Literal& other) const;
Literal maxUI16x8(const Literal& other) const;
Literal avgrUI16x8(const Literal& other) const;
Literal q15MulrSatSI16x8(const Literal& other) const;
Literal extMulLowSI16x8(const Literal& other) const;
Literal extMulHighSI16x8(const Literal& other) const;
Literal extMulLowUI16x8(const Literal& other) const;
Literal extMulHighUI16x8(const Literal& other) const;
Literal absI32x4() const;
Literal negI32x4() const;
Literal anyTrueI32x4() const;
Expand All @@ -525,6 +530,10 @@ class Literal {
Literal maxSI32x4(const Literal& other) const;
Literal maxUI32x4(const Literal& other) const;
Literal dotSI16x8toI32x4(const Literal& other) const;
Literal extMulLowSI32x4(const Literal& other) const;
Literal extMulHighSI32x4(const Literal& other) const;
Literal extMulLowUI32x4(const Literal& other) const;
Literal extMulHighUI32x4(const Literal& other) const;
Literal negI64x2() const;
Literal anyTrueI64x2() const;
Literal allTrueI64x2() const;
Expand All @@ -534,6 +543,10 @@ class Literal {
Literal addI64x2(const Literal& other) const;
Literal subI64x2(const Literal& other) const;
Literal mulI64x2(const Literal& other) const;
Literal extMulLowSI64x2(const Literal& other) const;
Literal extMulHighSI64x2(const Literal& other) const;
Literal extMulLowUI64x2(const Literal& other) const;
Literal extMulHighUI64x2(const Literal& other) const;
Literal absF32x4() const;
Literal negF32x4() const;
Literal sqrtF32x4() const;
Expand Down
41 changes: 41 additions & 0 deletions src/passes/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1357,6 +1357,22 @@ struct PrintExpressionContents
case AvgrUVecI16x8:
o << "i16x8.avgr_u";
break;
case Q15MulrSatSVecI16x8:
o << "i16x8.q15mulr_sat_s";
break;
case ExtMulLowSVecI16x8:
o << "i16x8.extmul_low_i8x16_s";
break;
case ExtMulHighSVecI16x8:
o << "i16x8.extmul_high_i8x16_s";
break;
case ExtMulLowUVecI16x8:
o << "i16x8.extmul_low_i8x16_u";
break;
case ExtMulHighUVecI16x8:
o << "i16x8.extmul_high_i8x16_u";
break;

case AddVecI32x4:
o << "i32x4.add";
break;
Expand All @@ -1381,6 +1397,19 @@ struct PrintExpressionContents
case DotSVecI16x8ToVecI32x4:
o << "i32x4.dot_i16x8_s";
break;
case ExtMulLowSVecI32x4:
o << "i32x4.extmul_low_i16x8_s";
break;
case ExtMulHighSVecI32x4:
o << "i32x4.extmul_high_i16x8_s";
break;
case ExtMulLowUVecI32x4:
o << "i32x4.extmul_low_i16x8_u";
break;
case ExtMulHighUVecI32x4:
o << "i32x4.extmul_high_i16x8_u";
break;

case AddVecI64x2:
o << "i64x2.add";
break;
Expand All @@ -1390,6 +1419,18 @@ struct PrintExpressionContents
case MulVecI64x2:
o << "i64x2.mul";
break;
case ExtMulLowSVecI64x2:
o << "i64x2.extmul_low_i32x4_s";
break;
case ExtMulHighSVecI64x2:
o << "i64x2.extmul_high_i32x4_s";
break;
case ExtMulLowUVecI64x2:
o << "i64x2.extmul_low_i32x4_u";
break;
case ExtMulHighUVecI64x2:
o << "i64x2.extmul_high_i32x4_u";
break;

case AddVecF32x4:
o << "f32x4.add";
Expand Down
3 changes: 3 additions & 0 deletions src/tools/fuzzing.h
Original file line number Diff line number Diff line change
Expand Up @@ -2448,6 +2448,9 @@ class TranslateToFuzzReader {
MinUVecI8x16,
MaxSVecI8x16,
MaxUVecI8x16,
// TODO: avgr_u
// TODO: q15mulr_sat_s
// TODO: extmul
AddVecI16x8,
AddSatSVecI16x8,
AddSatUVecI16x8,
Expand Down
14 changes: 14 additions & 0 deletions src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,7 @@ enum ASTNodes {
I16x8MaxS = 0x98,
I16x8MaxU = 0x99,
I16x8AvgrU = 0x9b,
I16x8Q15MulrSatS = 0x9c,

I32x4Abs = 0xa0,
I32x4Neg = 0xa1,
Expand Down Expand Up @@ -934,6 +935,19 @@ enum ASTNodes {
F64x2ConvertSI64x2 = 0x0102,
F64x2ConvertUI64x2 = 0x0103,

I16x8ExtMulLowSI8x16 = 0x0110,
I16x8ExtMulHighSI8x16 = 0x0111,
I16x8ExtMulLowUI8x16 = 0x0112,
I16x8ExtMulHighUI8x16 = 0x0113,
I32x4ExtMulLowSI16x8 = 0x0114,
I32x4ExtMulHighSI16x8 = 0x0115,
I32x4ExtMulLowUI16x8 = 0x0116,
I32x4ExtMulHighUI16x8 = 0x0117,
I64x2ExtMulLowSI32x4 = 0x0118,
I64x2ExtMulHighSI32x4 = 0x0119,
I64x2ExtMulLowUI32x4 = 0x011a,
I64x2ExtMulHighUI32x4 = 0x011b,

// bulk memory opcodes

MemoryInit = 0x08,
Expand Down
Loading

0 comments on commit bb008a0

Please sign in to comment.