Skip to content

Commit bca5be3

Browse files
committed
Prototype i32x4.widen_i8x16_{s,u}
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 27a5a71 commit bca5be3

23 files changed

+199
-33
lines changed

scripts/gen-s-parser.py

Lines changed: 2 additions & 0 deletions
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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1815,6 +1815,17 @@ switch (op[0]) {
18151815
default: goto parse_error;
18161816
}
18171817
}
1818+
case 'i': {
1819+
switch (op[18]) {
1820+
case 's':
1821+
if (strcmp(op, "i32x4.widen_i8x16_s") == 0) { return makeSIMDWiden(s, SIMDWidenOp::WidenSVecI8x16ToVecI32x4); }
1822+
goto parse_error;
1823+
case 'u':
1824+
if (strcmp(op, "i32x4.widen_i8x16_u") == 0) { return makeSIMDWiden(s, SIMDWidenOp::WidenUVecI8x16ToVecI32x4); }
1825+
goto parse_error;
1826+
default: goto parse_error;
1827+
}
1828+
}
18181829
case 'l': {
18191830
switch (op[22]) {
18201831
case 's':

src/ir/ReFinalize.cpp

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 20 additions & 0 deletions
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 << curr->index;
686+
}
674687
void visitPrefetch(Prefetch* curr) {
675688
prepareColor(o);
676689
switch (curr->op) {
@@ -2233,6 +2246,13 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
22332246
printFullLine(curr->vec);
22342247
decIndent();
22352248
}
2249+
void visitSIMDWiden(SIMDWiden* curr) {
2250+
o << '(';
2251+
PrintExpressionContents(currFunction, o).visit(curr);
2252+
incIndent();
2253+
printFullLine(curr->vec);
2254+
decIndent();
2255+
}
22362256
void visitPrefetch(Prefetch* curr) {
22372257
o << '(';
22382258
PrintExpressionContents(currFunction, o).visit(curr);

src/wasm-binary.h

Lines changed: 4 additions & 0 deletions
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,
@@ -1515,6 +1518,7 @@ class WasmBinaryBuilder {
15151518
bool maybeVisitSIMDShift(Expression*& out, uint32_t code);
15161519
bool maybeVisitSIMDLoad(Expression*& out, uint32_t code);
15171520
bool maybeVisitSIMDLoadStoreLane(Expression*& out, uint32_t code);
1521+
bool maybeVisitSIMDWiden(Expression*& out, uint32_t code);
15181522
bool maybeVisitPrefetch(Expression*& out, uint32_t code);
15191523
bool maybeVisitMemoryInit(Expression*& out, uint32_t code);
15201524
bool maybeVisitDataDrop(Expression*& out, uint32_t code);

src/wasm-delegations-fields.h

Lines changed: 8 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 19 additions & 1 deletion
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,
@@ -603,6 +608,7 @@ class Expression {
603608
SIMDShiftId,
604609
SIMDLoadId,
605610
SIMDLoadStoreLaneId,
611+
SIMDWidenId,
606612
MemoryInitId,
607613
DataDropId,
608614
MemoryCopyId,
@@ -1049,6 +1055,18 @@ class SIMDLoadStoreLane
10491055
void finalize();
10501056
};
10511057

1058+
class SIMDWiden : public SpecificExpression<Expression::SIMDWidenId> {
1059+
public:
1060+
SIMDWiden() = default;
1061+
SIMDWiden(MixedArena& allocator) {}
1062+
1063+
SIMDWidenOp op;
1064+
uint8_t index;
1065+
Expression* vec;
1066+
1067+
void finalize();
1068+
};
1069+
10521070
class Prefetch : public SpecificExpression<Expression::PrefetchId> {
10531071
public:
10541072
Prefetch() = default;

src/wasm/wasm-binary.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2978,6 +2978,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
29782978
if (maybeVisitSIMDLoadStoreLane(curr, opcode)) {
29792979
break;
29802980
}
2981+
if (maybeVisitSIMDWiden(curr, opcode)) {
2982+
break;
2983+
}
29812984
if (maybeVisitPrefetch(curr, opcode)) {
29822985
break;
29832986
}
@@ -5439,6 +5442,27 @@ bool WasmBinaryBuilder::maybeVisitSIMDLoadStoreLane(Expression*& out,
54395442
return true;
54405443
}
54415444

5445+
bool WasmBinaryBuilder::maybeVisitSIMDWiden(Expression*& out, uint32_t code) {
5446+
SIMDWidenOp op;
5447+
switch (code) {
5448+
case BinaryConsts::I32x4WidenSI8x16:
5449+
op = WidenSVecI8x16ToVecI32x4;
5450+
break;
5451+
case BinaryConsts::I32x4WidenUI8x16:
5452+
op = WidenUVecI8x16ToVecI32x4;
5453+
break;
5454+
default:
5455+
return false;
5456+
}
5457+
auto* curr = allocator.alloc<SIMDWiden>();
5458+
curr->op = op;
5459+
curr->index = getLaneIndex(4);
5460+
curr->vec = popNonVoidExpression();
5461+
curr->finalize();
5462+
out = curr;
5463+
return true;
5464+
}
5465+
54425466
bool WasmBinaryBuilder::maybeVisitPrefetch(Expression*& out, uint32_t code) {
54435467
PrefetchOp op;
54445468
switch (code) {

src/wasm/wasm-s-parser.cpp

Lines changed: 9 additions & 0 deletions
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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,19 @@ void BinaryInstWriter::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
694694
o << curr->index;
695695
}
696696

697+
void BinaryInstWriter::visitSIMDWiden(SIMDWiden* curr) {
698+
o << int8_t(BinaryConsts::SIMDPrefix);
699+
switch (curr->op) {
700+
case WidenSVecI8x16ToVecI32x4:
701+
o << U32LEB(BinaryConsts::I32x4WidenSI8x16);
702+
break;
703+
case WidenUVecI8x16ToVecI32x4:
704+
o << U32LEB(BinaryConsts::I32x4WidenUI8x16);
705+
break;
706+
}
707+
o << uint8_t(curr->index);
708+
}
709+
697710
void BinaryInstWriter::visitPrefetch(Prefetch* curr) {
698711
o << int8_t(BinaryConsts::SIMDPrefix);
699712
switch (curr->op) {

src/wasm/wasm.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ const char* getExpressionName(Expression* curr) {
174174
return "simd_load";
175175
case Expression::Id::SIMDLoadStoreLaneId:
176176
return "simd_load_store_lane";
177+
case Expression::Id::SIMDWidenId:
178+
return "simd_widen";
177179
case Expression::Id::PrefetchId:
178180
return "prefetch";
179181
case Expression::Id::MemoryInitId:
@@ -622,6 +624,11 @@ void SIMDLoadStoreLane::finalize() {
622624
}
623625
}
624626

627+
void SIMDWiden::finalize() {
628+
assert(vec);
629+
type = vec->type == Type::unreachable ? Type::unreachable : Type::v128;
630+
}
631+
625632
Index SIMDLoadStoreLane::getMemBytes() {
626633
switch (op) {
627634
case LoadLaneVec8x16:

src/wasm2js.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2120,6 +2120,10 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
21202120
unimplemented(curr);
21212121
WASM_UNREACHABLE("unimp");
21222122
}
2123+
Ref visitSIMDWiden(SIMDWiden* curr) {
2124+
unimplemented(curr);
2125+
WASM_UNREACHABLE("unimp");
2126+
}
21232127
Ref visitMemoryInit(MemoryInit* curr) {
21242128
ABI::wasm2js::ensureHelpers(module, ABI::wasm2js::MEMORY_INIT);
21252129
return ValueBuilder::makeCall(ABI::wasm2js::MEMORY_INIT,

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

Lines changed: 3 additions & 3 deletions
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

Lines changed: 29 additions & 29 deletions
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-
RefIsNullId: 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-
BrOnCastId: 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+
RefIsNullId: 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+
BrOnCastId: 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

Lines changed: 10 additions & 0 deletions
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
)

0 commit comments

Comments
 (0)