Skip to content

Commit b5c2875

Browse files
authored
Prototype i32x4.widen_i8x16_{s,u} (#3535)
As proposed in WebAssembly/simd#395. Note that the other instructions in the proposal have not been implemented in LLVM or in V8, so there is no need to implement them in Binaryen right now either. This PR introduces a new expression class for the new instructions because they uniquely take an immediate argument identifying which portion of the input vector to widen.
1 parent a4837c0 commit b5c2875

23 files changed

+197
-33
lines changed

scripts/gen-s-parser.py

+2
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,8 @@
522522
("i32x4.trunc_sat_f64x2_zero_u", "makeUnary(s, UnaryOp::TruncSatZeroUVecF64x2ToVecI32x4)"),
523523
("f32x4.demote_f64x2_zero", "makeUnary(s, UnaryOp::DemoteZeroVecF64x2ToVecF32x4)"),
524524
("f64x2.promote_low_f32x4", "makeUnary(s, UnaryOp::PromoteLowVecF32x4ToVecF64x2)"),
525+
("i32x4.widen_i8x16_s", "makeSIMDWiden(s, SIMDWidenOp::WidenSVecI8x16ToVecI32x4)"),
526+
("i32x4.widen_i8x16_u", "makeSIMDWiden(s, SIMDWidenOp::WidenUVecI8x16ToVecI32x4)"),
525527

526528
# prefetch instructions
527529
("prefetch.t", "makePrefetch(s, PrefetchOp::PrefetchTemporal)"),

src/gen-s-parser.inc

+11
Original file line numberDiff line numberDiff line change
@@ -1832,6 +1832,17 @@ switch (op[0]) {
18321832
default: goto parse_error;
18331833
}
18341834
}
1835+
case 'i': {
1836+
switch (op[18]) {
1837+
case 's':
1838+
if (strcmp(op, "i32x4.widen_i8x16_s") == 0) { return makeSIMDWiden(s, SIMDWidenOp::WidenSVecI8x16ToVecI32x4); }
1839+
goto parse_error;
1840+
case 'u':
1841+
if (strcmp(op, "i32x4.widen_i8x16_u") == 0) { return makeSIMDWiden(s, SIMDWidenOp::WidenUVecI8x16ToVecI32x4); }
1842+
goto parse_error;
1843+
default: goto parse_error;
1844+
}
1845+
}
18351846
case 'l': {
18361847
switch (op[22]) {
18371848
case 's':

src/ir/ReFinalize.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ void ReFinalize::visitSIMDLoad(SIMDLoad* curr) { curr->finalize(); }
112112
void ReFinalize::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
113113
curr->finalize();
114114
}
115+
void ReFinalize::visitSIMDWiden(SIMDWiden* curr) { curr->finalize(); }
115116
void ReFinalize::visitPrefetch(Prefetch* curr) { curr->finalize(); }
116117
void ReFinalize::visitMemoryInit(MemoryInit* curr) { curr->finalize(); }
117118
void ReFinalize::visitDataDrop(DataDrop* curr) { curr->finalize(); }

src/ir/cost.h

+1
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, Index> {
540540
Index visitSIMDShift(SIMDShift* curr) {
541541
return 1 + visit(curr->vec) + visit(curr->shift);
542542
}
543+
Index visitSIMDWiden(SIMDWiden* curr) { return 1 + visit(curr->vec); }
543544
Index visitSIMDShuffle(SIMDShuffle* curr) {
544545
return 1 + visit(curr->left) + visit(curr->right);
545546
}

src/ir/effects.h

+1
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ class EffectAnalyzer {
430430
}
431431
parent.implicitTrap = true;
432432
}
433+
void visitSIMDWiden(SIMDWiden* curr) {}
433434
void visitPrefetch(Prefetch* curr) {
434435
// Do not reorder with respect to other memory ops
435436
parent.writesMemory = true;

src/passes/Print.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,19 @@ struct PrintExpressionContents
671671
}
672672
o << " " << int(curr->index);
673673
}
674+
void visitSIMDWiden(SIMDWiden* curr) {
675+
prepareColor(o);
676+
switch (curr->op) {
677+
case WidenSVecI8x16ToVecI32x4:
678+
o << "i32x4.widen_i8x16_s ";
679+
break;
680+
case WidenUVecI8x16ToVecI32x4:
681+
o << "i32x4.widen_i8x16_u ";
682+
break;
683+
}
684+
restoreNormalColor(o);
685+
o << int(curr->index);
686+
}
674687
void visitPrefetch(Prefetch* curr) {
675688
prepareColor(o);
676689
switch (curr->op) {
@@ -2303,6 +2316,13 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
23032316
printFullLine(curr->vec);
23042317
decIndent();
23052318
}
2319+
void visitSIMDWiden(SIMDWiden* curr) {
2320+
o << '(';
2321+
PrintExpressionContents(currFunction, o).visit(curr);
2322+
incIndent();
2323+
printFullLine(curr->vec);
2324+
decIndent();
2325+
}
23062326
void visitPrefetch(Prefetch* curr) {
23072327
o << '(';
23082328
PrintExpressionContents(currFunction, o).visit(curr);

src/wasm-binary.h

+4
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,9 @@ enum ASTNodes {
979979
F32x4DemoteZeroF64x2 = 0x57,
980980
F64x2PromoteLowF32x4 = 0x69,
981981

982+
I32x4WidenSI8x16 = 0x67,
983+
I32x4WidenUI8x16 = 0x68,
984+
982985
// prefetch opcodes
983986

984987
PrefetchT = 0xc5,
@@ -1521,6 +1524,7 @@ class WasmBinaryBuilder {
15211524
bool maybeVisitSIMDShift(Expression*& out, uint32_t code);
15221525
bool maybeVisitSIMDLoad(Expression*& out, uint32_t code);
15231526
bool maybeVisitSIMDLoadStoreLane(Expression*& out, uint32_t code);
1527+
bool maybeVisitSIMDWiden(Expression*& out, uint32_t code);
15241528
bool maybeVisitPrefetch(Expression*& out, uint32_t code);
15251529
bool maybeVisitMemoryInit(Expression*& out, uint32_t code);
15261530
bool maybeVisitDataDrop(Expression*& out, uint32_t code);

src/wasm-delegations-fields.h

+8
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,14 @@ switch (DELEGATE_ID) {
386386
DELEGATE_END(SIMDLoadStoreLane);
387387
break;
388388
}
389+
case Expression::Id::SIMDWidenId: {
390+
DELEGATE_START(SIMDWiden);
391+
DELEGATE_FIELD_CHILD(SIMDWiden, vec);
392+
DELEGATE_FIELD_INT(SIMDWiden, op);
393+
DELEGATE_FIELD_INT(SIMDWiden, index);
394+
DELEGATE_END(SIMDWiden);
395+
break;
396+
}
389397
case Expression::Id::PrefetchId: {
390398
DELEGATE_START(Prefetch);
391399
DELEGATE_FIELD_CHILD(Prefetch, ptr);

src/wasm-delegations.h

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ DELEGATE(SIMDTernary);
4040
DELEGATE(SIMDShift);
4141
DELEGATE(SIMDLoad);
4242
DELEGATE(SIMDLoadStoreLane);
43+
DELEGATE(SIMDWiden);
4344
DELEGATE(Prefetch);
4445
DELEGATE(MemoryInit);
4546
DELEGATE(DataDrop);

src/wasm-interpreter.h

+1
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,7 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
11321132
}
11331133
WASM_UNREACHABLE("invalid op");
11341134
}
1135+
Flow visitSIMDWiden(SIMDWiden* curr) { WASM_UNREACHABLE("unimp"); }
11351136
Flow visitSelect(Select* curr) {
11361137
NOTE_ENTER("Select");
11371138
Flow ifTrue = visit(curr->ifTrue);

src/wasm-s-parser.h

+1
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ class SExpressionWasmBuilder {
220220
Expression* makeSIMDShift(Element& s, SIMDShiftOp op);
221221
Expression* makeSIMDLoad(Element& s, SIMDLoadOp op);
222222
Expression* makeSIMDLoadStoreLane(Element& s, SIMDLoadStoreLaneOp op);
223+
Expression* makeSIMDWiden(Element& s, SIMDWidenOp op);
223224
Expression* makePrefetch(Element& s, PrefetchOp op);
224225
Expression* makeMemoryInit(Element& s);
225226
Expression* makeDataDrop(Element& s);

src/wasm.h

+19-1
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ enum SIMDReplaceOp {
481481
ReplaceLaneVecI32x4,
482482
ReplaceLaneVecI64x2,
483483
ReplaceLaneVecF32x4,
484-
ReplaceLaneVecF64x2
484+
ReplaceLaneVecF64x2,
485485
};
486486

487487
enum SIMDShiftOp {
@@ -537,6 +537,11 @@ enum SIMDTernaryOp {
537537
SignSelectVec64x2
538538
};
539539

540+
enum SIMDWidenOp {
541+
WidenSVecI8x16ToVecI32x4,
542+
WidenUVecI8x16ToVecI32x4,
543+
};
544+
540545
enum PrefetchOp {
541546
PrefetchTemporal,
542547
PrefetchNontemporal,
@@ -625,6 +630,7 @@ class Expression {
625630
SIMDShiftId,
626631
SIMDLoadId,
627632
SIMDLoadStoreLaneId,
633+
SIMDWidenId,
628634
MemoryInitId,
629635
DataDropId,
630636
MemoryCopyId,
@@ -1072,6 +1078,18 @@ class SIMDLoadStoreLane
10721078
void finalize();
10731079
};
10741080

1081+
class SIMDWiden : public SpecificExpression<Expression::SIMDWidenId> {
1082+
public:
1083+
SIMDWiden() = default;
1084+
SIMDWiden(MixedArena& allocator) {}
1085+
1086+
SIMDWidenOp op;
1087+
uint8_t index;
1088+
Expression* vec;
1089+
1090+
void finalize();
1091+
};
1092+
10751093
class Prefetch : public SpecificExpression<Expression::PrefetchId> {
10761094
public:
10771095
Prefetch() = default;

src/wasm/wasm-binary.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -3005,6 +3005,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
30053005
if (maybeVisitSIMDLoadStoreLane(curr, opcode)) {
30063006
break;
30073007
}
3008+
if (maybeVisitSIMDWiden(curr, opcode)) {
3009+
break;
3010+
}
30083011
if (maybeVisitPrefetch(curr, opcode)) {
30093012
break;
30103013
}
@@ -5466,6 +5469,27 @@ bool WasmBinaryBuilder::maybeVisitSIMDLoadStoreLane(Expression*& out,
54665469
return true;
54675470
}
54685471

5472+
bool WasmBinaryBuilder::maybeVisitSIMDWiden(Expression*& out, uint32_t code) {
5473+
SIMDWidenOp op;
5474+
switch (code) {
5475+
case BinaryConsts::I32x4WidenSI8x16:
5476+
op = WidenSVecI8x16ToVecI32x4;
5477+
break;
5478+
case BinaryConsts::I32x4WidenUI8x16:
5479+
op = WidenUVecI8x16ToVecI32x4;
5480+
break;
5481+
default:
5482+
return false;
5483+
}
5484+
auto* curr = allocator.alloc<SIMDWiden>();
5485+
curr->op = op;
5486+
curr->index = getLaneIndex(4);
5487+
curr->vec = popNonVoidExpression();
5488+
curr->finalize();
5489+
out = curr;
5490+
return true;
5491+
}
5492+
54695493
bool WasmBinaryBuilder::maybeVisitPrefetch(Expression*& out, uint32_t code) {
54705494
PrefetchOp op;
54715495
switch (code) {

src/wasm/wasm-s-parser.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -1666,6 +1666,15 @@ SExpressionWasmBuilder::makeSIMDLoadStoreLane(Element& s,
16661666
return ret;
16671667
}
16681668

1669+
Expression* SExpressionWasmBuilder::makeSIMDWiden(Element& s, SIMDWidenOp op) {
1670+
auto* ret = allocator.alloc<SIMDWiden>();
1671+
ret->op = op;
1672+
ret->index = parseLaneIndex(s[1], 4);
1673+
ret->vec = parseExpression(s[2]);
1674+
ret->finalize();
1675+
return ret;
1676+
}
1677+
16691678
Expression* SExpressionWasmBuilder::makePrefetch(Element& s, PrefetchOp op) {
16701679
Address offset, align;
16711680
size_t i = parseMemAttributes(s, offset, align, /*defaultAlign*/ 1);

src/wasm/wasm-stack.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,19 @@ void BinaryInstWriter::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
691691
o << curr->index;
692692
}
693693

694+
void BinaryInstWriter::visitSIMDWiden(SIMDWiden* curr) {
695+
o << int8_t(BinaryConsts::SIMDPrefix);
696+
switch (curr->op) {
697+
case WidenSVecI8x16ToVecI32x4:
698+
o << U32LEB(BinaryConsts::I32x4WidenSI8x16);
699+
break;
700+
case WidenUVecI8x16ToVecI32x4:
701+
o << U32LEB(BinaryConsts::I32x4WidenUI8x16);
702+
break;
703+
}
704+
o << uint8_t(curr->index);
705+
}
706+
694707
void BinaryInstWriter::visitPrefetch(Prefetch* curr) {
695708
o << int8_t(BinaryConsts::SIMDPrefix);
696709
switch (curr->op) {

src/wasm/wasm.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,11 @@ void SIMDLoadStoreLane::finalize() {
496496
}
497497
}
498498

499+
void SIMDWiden::finalize() {
500+
assert(vec);
501+
type = vec->type == Type::unreachable ? Type::unreachable : Type::v128;
502+
}
503+
499504
Index SIMDLoadStoreLane::getMemBytes() {
500505
switch (op) {
501506
case LoadLaneVec8x16:

src/wasm2js.h

+4
Original file line numberDiff line numberDiff line change
@@ -2119,6 +2119,10 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
21192119
unimplemented(curr);
21202120
WASM_UNREACHABLE("unimp");
21212121
}
2122+
Ref visitSIMDWiden(SIMDWiden* curr) {
2123+
unimplemented(curr);
2124+
WASM_UNREACHABLE("unimp");
2125+
}
21222126
Ref visitMemoryInit(MemoryInit* curr) {
21232127
ABI::wasm2js::ensureHelpers(module, ABI::wasm2js::MEMORY_INIT);
21242128
return ValueBuilder::makeCall(ABI::wasm2js::MEMORY_INIT,

test/binaryen.js/exception-handling.js.txt

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@
1919
)
2020
)
2121

22-
getExpressionInfo(throw) = {"id":47,"type":1,"event":"e"}
23-
getExpressionInfo(rethrow) = {"id":48,"type":1,"depth":0}
24-
getExpressionInfo(try) = {"id":46,"type":1,"hasCatchAll":0}
22+
getExpressionInfo(throw) = {"id":48,"type":1,"event":"e"}
23+
getExpressionInfo(rethrow) = {"id":49,"type":1,"depth":0}
24+
getExpressionInfo(try) = {"id":47,"type":1,"hasCatchAll":0}

test/binaryen.js/kitchen-sink.js.txt

+29-29
Original file line numberDiff line numberDiff line change
@@ -76,35 +76,35 @@ SIMDShuffleId: 32
7676
SIMDTernaryId: 33
7777
SIMDShiftId: 34
7878
SIMDLoadId: 35
79-
MemoryInitId: 37
80-
DataDropId: 38
81-
MemoryCopyId: 39
82-
MemoryFillId: 40
83-
PopId: 41
84-
RefNullId: 42
85-
RefIsId: 43
86-
RefFuncId: 44
87-
RefEqId: 45
88-
TryId: 46
89-
ThrowId: 47
90-
RethrowId: 48
91-
TupleMakeId: 49
92-
TupleExtractId: 50
93-
I31NewId: 51
94-
I31GetId: 52
95-
CallRefId: 53
96-
RefTestId: 54
97-
RefCastId: 55
98-
BrOnId: 56
99-
RttCanonId: 57
100-
RttSubId: 58
101-
StructNewId: 59
102-
StructGetId: 60
103-
StructSetId: 61
104-
ArrayNewId: 62
105-
ArrayGetId: 63
106-
ArraySetId: 64
107-
ArrayLenId: 65
79+
MemoryInitId: 38
80+
DataDropId: 39
81+
MemoryCopyId: 40
82+
MemoryFillId: 41
83+
PopId: 42
84+
RefNullId: 43
85+
RefIsId: 44
86+
RefFuncId: 45
87+
RefEqId: 46
88+
TryId: 47
89+
ThrowId: 48
90+
RethrowId: 49
91+
TupleMakeId: 50
92+
TupleExtractId: 51
93+
I31NewId: 52
94+
I31GetId: 53
95+
CallRefId: 54
96+
RefTestId: 55
97+
RefCastId: 56
98+
BrOnId: 57
99+
RttCanonId: 58
100+
RttSubId: 59
101+
StructNewId: 60
102+
StructGetId: 61
103+
StructSetId: 62
104+
ArrayNewId: 63
105+
ArrayGetId: 64
106+
ArraySetId: 65
107+
ArrayLenId: 66
108108
getExpressionInfo={"id":15,"type":4,"op":6}
109109
(f32.neg
110110
(f32.const -33.61199951171875)

test/simd.wast

+10
Original file line numberDiff line numberDiff line change
@@ -1436,4 +1436,14 @@
14361436
(local.get $0)
14371437
)
14381438
)
1439+
(func $i32x4.widen_i8x16_s (param $0 v128) (result v128)
1440+
(i32x4.widen_i8x16_s 0
1441+
(local.get $0)
1442+
)
1443+
)
1444+
(func $i32x4.widen_i8x16_u (param $0 v128) (result v128)
1445+
(i32x4.widen_i8x16_u 0
1446+
(local.get $0)
1447+
)
1448+
)
14391449
)

test/simd.wast.from-wast

+10
Original file line numberDiff line numberDiff line change
@@ -1454,4 +1454,14 @@
14541454
(local.get $0)
14551455
)
14561456
)
1457+
(func $i32x4.widen_i8x16_s (param $0 v128) (result v128)
1458+
(i32x4.widen_i8x16_s 0
1459+
(local.get $0)
1460+
)
1461+
)
1462+
(func $i32x4.widen_i8x16_u (param $0 v128) (result v128)
1463+
(i32x4.widen_i8x16_u 0
1464+
(local.get $0)
1465+
)
1466+
)
14571467
)

0 commit comments

Comments
 (0)