Skip to content

Commit 5f7d263

Browse files
authored
Prototype new SIMD multiplications (#3291)
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.
1 parent 8fd93ee commit 5f7d263

19 files changed

+840
-106
lines changed

scripts/gen-s-parser.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,11 @@
399399
("i16x8.max_s", "makeBinary(s, BinaryOp::MaxSVecI16x8)"),
400400
("i16x8.max_u", "makeBinary(s, BinaryOp::MaxUVecI16x8)"),
401401
("i16x8.avgr_u", "makeBinary(s, BinaryOp::AvgrUVecI16x8)"),
402+
("i16x8.q15mulr_sat_s", "makeBinary(s, BinaryOp::Q15MulrSatSVecI16x8)"),
403+
("i16x8.extmul_low_i8x16_s", "makeBinary(s, BinaryOp::ExtMulLowSVecI16x8)"),
404+
("i16x8.extmul_high_i8x16_s", "makeBinary(s, BinaryOp::ExtMulHighSVecI16x8)"),
405+
("i16x8.extmul_low_i8x16_u", "makeBinary(s, BinaryOp::ExtMulLowUVecI16x8)"),
406+
("i16x8.extmul_high_i8x16_u", "makeBinary(s, BinaryOp::ExtMulHighUVecI16x8)"),
402407
("i32x4.abs", "makeUnary(s, UnaryOp::AbsVecI32x4)"),
403408
("i32x4.neg", "makeUnary(s, UnaryOp::NegVecI32x4)"),
404409
("i32x4.any_true", "makeUnary(s, UnaryOp::AnyTrueVecI32x4)"),
@@ -415,6 +420,10 @@
415420
("i32x4.max_s", "makeBinary(s, BinaryOp::MaxSVecI32x4)"),
416421
("i32x4.max_u", "makeBinary(s, BinaryOp::MaxUVecI32x4)"),
417422
("i32x4.dot_i16x8_s", "makeBinary(s, BinaryOp::DotSVecI16x8ToVecI32x4)"),
423+
("i32x4.extmul_low_i16x8_s", "makeBinary(s, BinaryOp::ExtMulLowSVecI32x4)"),
424+
("i32x4.extmul_high_i16x8_s", "makeBinary(s, BinaryOp::ExtMulHighSVecI32x4)"),
425+
("i32x4.extmul_low_i16x8_u", "makeBinary(s, BinaryOp::ExtMulLowUVecI32x4)"),
426+
("i32x4.extmul_high_i16x8_u", "makeBinary(s, BinaryOp::ExtMulHighUVecI32x4)"),
418427
("i64x2.neg", "makeUnary(s, UnaryOp::NegVecI64x2)"),
419428
("i64x2.any_true", "makeUnary(s, UnaryOp::AnyTrueVecI64x2)"),
420429
("i64x2.all_true", "makeUnary(s, UnaryOp::AllTrueVecI64x2)"),
@@ -424,6 +433,10 @@
424433
("i64x2.add", "makeBinary(s, BinaryOp::AddVecI64x2)"),
425434
("i64x2.sub", "makeBinary(s, BinaryOp::SubVecI64x2)"),
426435
("i64x2.mul", "makeBinary(s, BinaryOp::MulVecI64x2)"),
436+
("i64x2.extmul_low_i32x4_s", "makeBinary(s, BinaryOp::ExtMulLowSVecI64x2)"),
437+
("i64x2.extmul_high_i32x4_s", "makeBinary(s, BinaryOp::ExtMulHighSVecI64x2)"),
438+
("i64x2.extmul_low_i32x4_u", "makeBinary(s, BinaryOp::ExtMulLowUVecI64x2)"),
439+
("i64x2.extmul_high_i32x4_u", "makeBinary(s, BinaryOp::ExtMulHighUVecI64x2)"),
427440
("f32x4.abs", "makeUnary(s, UnaryOp::AbsVecF32x4)"),
428441
("f32x4.neg", "makeUnary(s, UnaryOp::NegVecF32x4)"),
429442
("f32x4.sqrt", "makeUnary(s, UnaryOp::SqrtVecF32x4)"),

src/binaryen-c.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ BINARYEN_API BinaryenOp BinaryenOrVec128(void);
485485
BINARYEN_API BinaryenOp BinaryenXorVec128(void);
486486
BINARYEN_API BinaryenOp BinaryenAndNotVec128(void);
487487
BINARYEN_API BinaryenOp BinaryenBitselectVec128(void);
488-
// TODO: Add i8x16.popcnt to C and JS APIs once merged to proposal
488+
// TODO: Add i8x16.popcnt to C and JS APIs once merged to the proposal
489489
BINARYEN_API BinaryenOp BinaryenAbsVecI8x16(void);
490490
BINARYEN_API BinaryenOp BinaryenNegVecI8x16(void);
491491
BINARYEN_API BinaryenOp BinaryenAnyTrueVecI8x16(void);
@@ -526,6 +526,8 @@ BINARYEN_API BinaryenOp BinaryenMinUVecI16x8(void);
526526
BINARYEN_API BinaryenOp BinaryenMaxSVecI16x8(void);
527527
BINARYEN_API BinaryenOp BinaryenMaxUVecI16x8(void);
528528
BINARYEN_API BinaryenOp BinaryenAvgrUVecI16x8(void);
529+
// TODO: Add i16x8.q15mulr_sat_s to C and JS APIs once merged to the proposal
530+
// TODO: Add extending multiplications to APIs once they are merged as well
529531
BINARYEN_API BinaryenOp BinaryenAbsVecI32x4(void);
530532
BINARYEN_API BinaryenOp BinaryenNegVecI32x4(void);
531533
BINARYEN_API BinaryenOp BinaryenAnyTrueVecI32x4(void);

src/gen-s-parser.inc

Lines changed: 112 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -799,13 +799,45 @@ switch (op[0]) {
799799
if (strcmp(op, "i16x8.eq") == 0) { return makeBinary(s, BinaryOp::EqVecI16x8); }
800800
goto parse_error;
801801
case 'x': {
802-
switch (op[19]) {
803-
case 's':
804-
if (strcmp(op, "i16x8.extract_lane_s") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneSVecI16x8, 8); }
805-
goto parse_error;
806-
case 'u':
807-
if (strcmp(op, "i16x8.extract_lane_u") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneUVecI16x8, 8); }
808-
goto parse_error;
802+
switch (op[9]) {
803+
case 'm': {
804+
switch (op[13]) {
805+
case 'h': {
806+
switch (op[24]) {
807+
case 's':
808+
if (strcmp(op, "i16x8.extmul_high_i8x16_s") == 0) { return makeBinary(s, BinaryOp::ExtMulHighSVecI16x8); }
809+
goto parse_error;
810+
case 'u':
811+
if (strcmp(op, "i16x8.extmul_high_i8x16_u") == 0) { return makeBinary(s, BinaryOp::ExtMulHighUVecI16x8); }
812+
goto parse_error;
813+
default: goto parse_error;
814+
}
815+
}
816+
case 'l': {
817+
switch (op[23]) {
818+
case 's':
819+
if (strcmp(op, "i16x8.extmul_low_i8x16_s") == 0) { return makeBinary(s, BinaryOp::ExtMulLowSVecI16x8); }
820+
goto parse_error;
821+
case 'u':
822+
if (strcmp(op, "i16x8.extmul_low_i8x16_u") == 0) { return makeBinary(s, BinaryOp::ExtMulLowUVecI16x8); }
823+
goto parse_error;
824+
default: goto parse_error;
825+
}
826+
}
827+
default: goto parse_error;
828+
}
829+
}
830+
case 'r': {
831+
switch (op[19]) {
832+
case 's':
833+
if (strcmp(op, "i16x8.extract_lane_s") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneSVecI16x8, 8); }
834+
goto parse_error;
835+
case 'u':
836+
if (strcmp(op, "i16x8.extract_lane_u") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneUVecI16x8, 8); }
837+
goto parse_error;
838+
default: goto parse_error;
839+
}
840+
}
809841
default: goto parse_error;
810842
}
811843
}
@@ -934,6 +966,9 @@ switch (op[0]) {
934966
default: goto parse_error;
935967
}
936968
}
969+
case 'q':
970+
if (strcmp(op, "i16x8.q15mulr_sat_s") == 0) { return makeBinary(s, BinaryOp::Q15MulrSatSVecI16x8); }
971+
goto parse_error;
937972
case 'r':
938973
if (strcmp(op, "i16x8.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI16x8, 8); }
939974
goto parse_error;
@@ -1520,9 +1555,41 @@ switch (op[0]) {
15201555
case 'q':
15211556
if (strcmp(op, "i32x4.eq") == 0) { return makeBinary(s, BinaryOp::EqVecI32x4); }
15221557
goto parse_error;
1523-
case 'x':
1524-
if (strcmp(op, "i32x4.extract_lane") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecI32x4, 4); }
1525-
goto parse_error;
1558+
case 'x': {
1559+
switch (op[9]) {
1560+
case 'm': {
1561+
switch (op[13]) {
1562+
case 'h': {
1563+
switch (op[24]) {
1564+
case 's':
1565+
if (strcmp(op, "i32x4.extmul_high_i16x8_s") == 0) { return makeBinary(s, BinaryOp::ExtMulHighSVecI32x4); }
1566+
goto parse_error;
1567+
case 'u':
1568+
if (strcmp(op, "i32x4.extmul_high_i16x8_u") == 0) { return makeBinary(s, BinaryOp::ExtMulHighUVecI32x4); }
1569+
goto parse_error;
1570+
default: goto parse_error;
1571+
}
1572+
}
1573+
case 'l': {
1574+
switch (op[23]) {
1575+
case 's':
1576+
if (strcmp(op, "i32x4.extmul_low_i16x8_s") == 0) { return makeBinary(s, BinaryOp::ExtMulLowSVecI32x4); }
1577+
goto parse_error;
1578+
case 'u':
1579+
if (strcmp(op, "i32x4.extmul_low_i16x8_u") == 0) { return makeBinary(s, BinaryOp::ExtMulLowUVecI32x4); }
1580+
goto parse_error;
1581+
default: goto parse_error;
1582+
}
1583+
}
1584+
default: goto parse_error;
1585+
}
1586+
}
1587+
case 'r':
1588+
if (strcmp(op, "i32x4.extract_lane") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecI32x4, 4); }
1589+
goto parse_error;
1590+
default: goto parse_error;
1591+
}
1592+
}
15261593
default: goto parse_error;
15271594
}
15281595
}
@@ -2251,9 +2318,41 @@ switch (op[0]) {
22512318
default: goto parse_error;
22522319
}
22532320
}
2254-
case 'e':
2255-
if (strcmp(op, "i64x2.extract_lane") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecI64x2, 2); }
2256-
goto parse_error;
2321+
case 'e': {
2322+
switch (op[9]) {
2323+
case 'm': {
2324+
switch (op[13]) {
2325+
case 'h': {
2326+
switch (op[24]) {
2327+
case 's':
2328+
if (strcmp(op, "i64x2.extmul_high_i32x4_s") == 0) { return makeBinary(s, BinaryOp::ExtMulHighSVecI64x2); }
2329+
goto parse_error;
2330+
case 'u':
2331+
if (strcmp(op, "i64x2.extmul_high_i32x4_u") == 0) { return makeBinary(s, BinaryOp::ExtMulHighUVecI64x2); }
2332+
goto parse_error;
2333+
default: goto parse_error;
2334+
}
2335+
}
2336+
case 'l': {
2337+
switch (op[23]) {
2338+
case 's':
2339+
if (strcmp(op, "i64x2.extmul_low_i32x4_s") == 0) { return makeBinary(s, BinaryOp::ExtMulLowSVecI64x2); }
2340+
goto parse_error;
2341+
case 'u':
2342+
if (strcmp(op, "i64x2.extmul_low_i32x4_u") == 0) { return makeBinary(s, BinaryOp::ExtMulLowUVecI64x2); }
2343+
goto parse_error;
2344+
default: goto parse_error;
2345+
}
2346+
}
2347+
default: goto parse_error;
2348+
}
2349+
}
2350+
case 'r':
2351+
if (strcmp(op, "i64x2.extract_lane") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecI64x2, 2); }
2352+
goto parse_error;
2353+
default: goto parse_error;
2354+
}
2355+
}
22572356
case 'l': {
22582357
switch (op[15]) {
22592358
case 's':

src/ir/cost.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,21 @@ struct CostAnalyzer : public Visitor<CostAnalyzer, Index> {
648648
case AvgrUVecI16x8:
649649
ret = 1;
650650
break;
651+
case Q15MulrSatSVecI16x8:
652+
ret = 1;
653+
break;
654+
case ExtMulLowSVecI16x8:
655+
ret = 1;
656+
break;
657+
case ExtMulHighSVecI16x8:
658+
ret = 1;
659+
break;
660+
case ExtMulLowUVecI16x8:
661+
ret = 1;
662+
break;
663+
case ExtMulHighUVecI16x8:
664+
ret = 1;
665+
break;
651666
case AddVecI32x4:
652667
ret = 1;
653668
break;
@@ -672,6 +687,18 @@ struct CostAnalyzer : public Visitor<CostAnalyzer, Index> {
672687
case DotSVecI16x8ToVecI32x4:
673688
ret = 1;
674689
break;
690+
case ExtMulLowSVecI32x4:
691+
ret = 1;
692+
break;
693+
case ExtMulHighSVecI32x4:
694+
ret = 1;
695+
break;
696+
case ExtMulLowUVecI32x4:
697+
ret = 1;
698+
break;
699+
case ExtMulHighUVecI32x4:
700+
ret = 1;
701+
break;
675702
case AddVecI64x2:
676703
ret = 1;
677704
break;
@@ -681,6 +708,18 @@ struct CostAnalyzer : public Visitor<CostAnalyzer, Index> {
681708
case MulVecI64x2:
682709
ret = 1;
683710
break;
711+
case ExtMulLowSVecI64x2:
712+
ret = 1;
713+
break;
714+
case ExtMulHighSVecI64x2:
715+
ret = 1;
716+
break;
717+
case ExtMulLowUVecI64x2:
718+
ret = 1;
719+
break;
720+
case ExtMulHighUVecI64x2:
721+
ret = 1;
722+
break;
684723
case AddVecF32x4:
685724
ret = 1;
686725
break;

src/literal.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,11 @@ class Literal {
509509
Literal maxSI16x8(const Literal& other) const;
510510
Literal maxUI16x8(const Literal& other) const;
511511
Literal avgrUI16x8(const Literal& other) const;
512+
Literal q15MulrSatSI16x8(const Literal& other) const;
513+
Literal extMulLowSI16x8(const Literal& other) const;
514+
Literal extMulHighSI16x8(const Literal& other) const;
515+
Literal extMulLowUI16x8(const Literal& other) const;
516+
Literal extMulHighUI16x8(const Literal& other) const;
512517
Literal absI32x4() const;
513518
Literal negI32x4() const;
514519
Literal anyTrueI32x4() const;
@@ -525,6 +530,10 @@ class Literal {
525530
Literal maxSI32x4(const Literal& other) const;
526531
Literal maxUI32x4(const Literal& other) const;
527532
Literal dotSI16x8toI32x4(const Literal& other) const;
533+
Literal extMulLowSI32x4(const Literal& other) const;
534+
Literal extMulHighSI32x4(const Literal& other) const;
535+
Literal extMulLowUI32x4(const Literal& other) const;
536+
Literal extMulHighUI32x4(const Literal& other) const;
528537
Literal negI64x2() const;
529538
Literal anyTrueI64x2() const;
530539
Literal allTrueI64x2() const;
@@ -534,6 +543,10 @@ class Literal {
534543
Literal addI64x2(const Literal& other) const;
535544
Literal subI64x2(const Literal& other) const;
536545
Literal mulI64x2(const Literal& other) const;
546+
Literal extMulLowSI64x2(const Literal& other) const;
547+
Literal extMulHighSI64x2(const Literal& other) const;
548+
Literal extMulLowUI64x2(const Literal& other) const;
549+
Literal extMulHighUI64x2(const Literal& other) const;
537550
Literal absF32x4() const;
538551
Literal negF32x4() const;
539552
Literal sqrtF32x4() const;

src/passes/Print.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,22 @@ struct PrintExpressionContents
13571357
case AvgrUVecI16x8:
13581358
o << "i16x8.avgr_u";
13591359
break;
1360+
case Q15MulrSatSVecI16x8:
1361+
o << "i16x8.q15mulr_sat_s";
1362+
break;
1363+
case ExtMulLowSVecI16x8:
1364+
o << "i16x8.extmul_low_i8x16_s";
1365+
break;
1366+
case ExtMulHighSVecI16x8:
1367+
o << "i16x8.extmul_high_i8x16_s";
1368+
break;
1369+
case ExtMulLowUVecI16x8:
1370+
o << "i16x8.extmul_low_i8x16_u";
1371+
break;
1372+
case ExtMulHighUVecI16x8:
1373+
o << "i16x8.extmul_high_i8x16_u";
1374+
break;
1375+
13601376
case AddVecI32x4:
13611377
o << "i32x4.add";
13621378
break;
@@ -1381,6 +1397,19 @@ struct PrintExpressionContents
13811397
case DotSVecI16x8ToVecI32x4:
13821398
o << "i32x4.dot_i16x8_s";
13831399
break;
1400+
case ExtMulLowSVecI32x4:
1401+
o << "i32x4.extmul_low_i16x8_s";
1402+
break;
1403+
case ExtMulHighSVecI32x4:
1404+
o << "i32x4.extmul_high_i16x8_s";
1405+
break;
1406+
case ExtMulLowUVecI32x4:
1407+
o << "i32x4.extmul_low_i16x8_u";
1408+
break;
1409+
case ExtMulHighUVecI32x4:
1410+
o << "i32x4.extmul_high_i16x8_u";
1411+
break;
1412+
13841413
case AddVecI64x2:
13851414
o << "i64x2.add";
13861415
break;
@@ -1390,6 +1419,18 @@ struct PrintExpressionContents
13901419
case MulVecI64x2:
13911420
o << "i64x2.mul";
13921421
break;
1422+
case ExtMulLowSVecI64x2:
1423+
o << "i64x2.extmul_low_i32x4_s";
1424+
break;
1425+
case ExtMulHighSVecI64x2:
1426+
o << "i64x2.extmul_high_i32x4_s";
1427+
break;
1428+
case ExtMulLowUVecI64x2:
1429+
o << "i64x2.extmul_low_i32x4_u";
1430+
break;
1431+
case ExtMulHighUVecI64x2:
1432+
o << "i64x2.extmul_high_i32x4_u";
1433+
break;
13931434

13941435
case AddVecF32x4:
13951436
o << "f32x4.add";

src/tools/fuzzing.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2448,6 +2448,9 @@ class TranslateToFuzzReader {
24482448
MinUVecI8x16,
24492449
MaxSVecI8x16,
24502450
MaxUVecI8x16,
2451+
// TODO: avgr_u
2452+
// TODO: q15mulr_sat_s
2453+
// TODO: extmul
24512454
AddVecI16x8,
24522455
AddSatSVecI16x8,
24532456
AddSatUVecI16x8,

src/wasm-binary.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,7 @@ enum ASTNodes {
851851
I16x8MaxS = 0x98,
852852
I16x8MaxU = 0x99,
853853
I16x8AvgrU = 0x9b,
854+
I16x8Q15MulrSatS = 0x9c,
854855

855856
I32x4Abs = 0xa0,
856857
I32x4Neg = 0xa1,
@@ -934,6 +935,19 @@ enum ASTNodes {
934935
F64x2ConvertSI64x2 = 0x0102,
935936
F64x2ConvertUI64x2 = 0x0103,
936937

938+
I16x8ExtMulLowSI8x16 = 0x9a,
939+
I16x8ExtMulHighSI8x16 = 0x9d,
940+
I16x8ExtMulLowUI8x16 = 0x9e,
941+
I16x8ExtMulHighUI8x16 = 0x9f,
942+
I32x4ExtMulLowSI16x8 = 0xbb,
943+
I32x4ExtMulHighSI16x8 = 0xbd,
944+
I32x4ExtMulLowUI16x8 = 0xbe,
945+
I32x4ExtMulHighUI16x8 = 0xbf,
946+
I64x2ExtMulLowSI32x4 = 0xd2,
947+
I64x2ExtMulHighSI32x4 = 0xd3,
948+
I64x2ExtMulLowUI32x4 = 0xd6,
949+
I64x2ExtMulHighUI32x4 = 0xd7,
950+
937951
// bulk memory opcodes
938952

939953
MemoryInit = 0x08,

0 commit comments

Comments
 (0)