summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2021-02-01 16:53:01 -0800
committerGitHub <noreply@github.com>2021-02-01 16:53:01 -0800
commitb5c287567ebcb3cbb1b1acb7f9e717f8b834ea83 (patch)
tree158cb452f58553cc0244d98c45e9d2b2705c1bbd
parenta4837c095275b465005841616ff10bcd0b0d7996 (diff)
downloadbinaryen-b5c287567ebcb3cbb1b1acb7f9e717f8b834ea83.tar.gz
binaryen-b5c287567ebcb3cbb1b1acb7f9e717f8b834ea83.tar.bz2
binaryen-b5c287567ebcb3cbb1b1acb7f9e717f8b834ea83.zip
Prototype i32x4.widen_i8x16_{s,u} (#3535)
As proposed in https://github.com/WebAssembly/simd/pull/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.
-rwxr-xr-xscripts/gen-s-parser.py2
-rw-r--r--src/gen-s-parser.inc11
-rw-r--r--src/ir/ReFinalize.cpp1
-rw-r--r--src/ir/cost.h1
-rw-r--r--src/ir/effects.h1
-rw-r--r--src/passes/Print.cpp20
-rw-r--r--src/wasm-binary.h4
-rw-r--r--src/wasm-delegations-fields.h8
-rw-r--r--src/wasm-delegations.h1
-rw-r--r--src/wasm-interpreter.h1
-rw-r--r--src/wasm-s-parser.h1
-rw-r--r--src/wasm.h20
-rw-r--r--src/wasm/wasm-binary.cpp24
-rw-r--r--src/wasm/wasm-s-parser.cpp9
-rw-r--r--src/wasm/wasm-stack.cpp13
-rw-r--r--src/wasm/wasm.cpp5
-rw-r--r--src/wasm2js.h4
-rw-r--r--test/binaryen.js/exception-handling.js.txt6
-rw-r--r--test/binaryen.js/kitchen-sink.js.txt58
-rw-r--r--test/simd.wast10
-rw-r--r--test/simd.wast.from-wast10
-rw-r--r--test/simd.wast.fromBinary10
-rw-r--r--test/simd.wast.fromBinary.noDebugInfo10
23 files changed, 197 insertions, 33 deletions
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py
index af29f4020..c65e5ddc4 100755
--- a/scripts/gen-s-parser.py
+++ b/scripts/gen-s-parser.py
@@ -522,6 +522,8 @@ instructions = [
("i32x4.trunc_sat_f64x2_zero_u", "makeUnary(s, UnaryOp::TruncSatZeroUVecF64x2ToVecI32x4)"),
("f32x4.demote_f64x2_zero", "makeUnary(s, UnaryOp::DemoteZeroVecF64x2ToVecF32x4)"),
("f64x2.promote_low_f32x4", "makeUnary(s, UnaryOp::PromoteLowVecF32x4ToVecF64x2)"),
+ ("i32x4.widen_i8x16_s", "makeSIMDWiden(s, SIMDWidenOp::WidenSVecI8x16ToVecI32x4)"),
+ ("i32x4.widen_i8x16_u", "makeSIMDWiden(s, SIMDWidenOp::WidenUVecI8x16ToVecI32x4)"),
# prefetch instructions
("prefetch.t", "makePrefetch(s, PrefetchOp::PrefetchTemporal)"),
diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc
index 281a2cfca..4e5a61d92 100644
--- a/src/gen-s-parser.inc
+++ b/src/gen-s-parser.inc
@@ -1832,6 +1832,17 @@ switch (op[0]) {
default: goto parse_error;
}
}
+ case 'i': {
+ switch (op[18]) {
+ case 's':
+ if (strcmp(op, "i32x4.widen_i8x16_s") == 0) { return makeSIMDWiden(s, SIMDWidenOp::WidenSVecI8x16ToVecI32x4); }
+ goto parse_error;
+ case 'u':
+ if (strcmp(op, "i32x4.widen_i8x16_u") == 0) { return makeSIMDWiden(s, SIMDWidenOp::WidenUVecI8x16ToVecI32x4); }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
case 'l': {
switch (op[22]) {
case 's':
diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp
index 808b9d41b..de4184596 100644
--- a/src/ir/ReFinalize.cpp
+++ b/src/ir/ReFinalize.cpp
@@ -112,6 +112,7 @@ void ReFinalize::visitSIMDLoad(SIMDLoad* curr) { curr->finalize(); }
void ReFinalize::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
curr->finalize();
}
+void ReFinalize::visitSIMDWiden(SIMDWiden* curr) { curr->finalize(); }
void ReFinalize::visitPrefetch(Prefetch* curr) { curr->finalize(); }
void ReFinalize::visitMemoryInit(MemoryInit* curr) { curr->finalize(); }
void ReFinalize::visitDataDrop(DataDrop* curr) { curr->finalize(); }
diff --git a/src/ir/cost.h b/src/ir/cost.h
index 212933ffb..50941bdd3 100644
--- a/src/ir/cost.h
+++ b/src/ir/cost.h
@@ -540,6 +540,7 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, Index> {
Index visitSIMDShift(SIMDShift* curr) {
return 1 + visit(curr->vec) + visit(curr->shift);
}
+ Index visitSIMDWiden(SIMDWiden* curr) { return 1 + visit(curr->vec); }
Index visitSIMDShuffle(SIMDShuffle* curr) {
return 1 + visit(curr->left) + visit(curr->right);
}
diff --git a/src/ir/effects.h b/src/ir/effects.h
index c7142dc34..d52fcfb15 100644
--- a/src/ir/effects.h
+++ b/src/ir/effects.h
@@ -430,6 +430,7 @@ private:
}
parent.implicitTrap = true;
}
+ void visitSIMDWiden(SIMDWiden* curr) {}
void visitPrefetch(Prefetch* curr) {
// Do not reorder with respect to other memory ops
parent.writesMemory = true;
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 39c66cc57..74bd5598f 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -671,6 +671,19 @@ struct PrintExpressionContents
}
o << " " << int(curr->index);
}
+ void visitSIMDWiden(SIMDWiden* curr) {
+ prepareColor(o);
+ switch (curr->op) {
+ case WidenSVecI8x16ToVecI32x4:
+ o << "i32x4.widen_i8x16_s ";
+ break;
+ case WidenUVecI8x16ToVecI32x4:
+ o << "i32x4.widen_i8x16_u ";
+ break;
+ }
+ restoreNormalColor(o);
+ o << int(curr->index);
+ }
void visitPrefetch(Prefetch* curr) {
prepareColor(o);
switch (curr->op) {
@@ -2303,6 +2316,13 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
printFullLine(curr->vec);
decIndent();
}
+ void visitSIMDWiden(SIMDWiden* curr) {
+ o << '(';
+ PrintExpressionContents(currFunction, o).visit(curr);
+ incIndent();
+ printFullLine(curr->vec);
+ decIndent();
+ }
void visitPrefetch(Prefetch* curr) {
o << '(';
PrintExpressionContents(currFunction, o).visit(curr);
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 0213baffe..6a409f7db 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -979,6 +979,9 @@ enum ASTNodes {
F32x4DemoteZeroF64x2 = 0x57,
F64x2PromoteLowF32x4 = 0x69,
+ I32x4WidenSI8x16 = 0x67,
+ I32x4WidenUI8x16 = 0x68,
+
// prefetch opcodes
PrefetchT = 0xc5,
@@ -1521,6 +1524,7 @@ public:
bool maybeVisitSIMDShift(Expression*& out, uint32_t code);
bool maybeVisitSIMDLoad(Expression*& out, uint32_t code);
bool maybeVisitSIMDLoadStoreLane(Expression*& out, uint32_t code);
+ bool maybeVisitSIMDWiden(Expression*& out, uint32_t code);
bool maybeVisitPrefetch(Expression*& out, uint32_t code);
bool maybeVisitMemoryInit(Expression*& out, uint32_t code);
bool maybeVisitDataDrop(Expression*& out, uint32_t code);
diff --git a/src/wasm-delegations-fields.h b/src/wasm-delegations-fields.h
index d4ea25b3d..b99ebef40 100644
--- a/src/wasm-delegations-fields.h
+++ b/src/wasm-delegations-fields.h
@@ -386,6 +386,14 @@ switch (DELEGATE_ID) {
DELEGATE_END(SIMDLoadStoreLane);
break;
}
+ case Expression::Id::SIMDWidenId: {
+ DELEGATE_START(SIMDWiden);
+ DELEGATE_FIELD_CHILD(SIMDWiden, vec);
+ DELEGATE_FIELD_INT(SIMDWiden, op);
+ DELEGATE_FIELD_INT(SIMDWiden, index);
+ DELEGATE_END(SIMDWiden);
+ break;
+ }
case Expression::Id::PrefetchId: {
DELEGATE_START(Prefetch);
DELEGATE_FIELD_CHILD(Prefetch, ptr);
diff --git a/src/wasm-delegations.h b/src/wasm-delegations.h
index fd419f508..5a05a731f 100644
--- a/src/wasm-delegations.h
+++ b/src/wasm-delegations.h
@@ -40,6 +40,7 @@ DELEGATE(SIMDTernary);
DELEGATE(SIMDShift);
DELEGATE(SIMDLoad);
DELEGATE(SIMDLoadStoreLane);
+DELEGATE(SIMDWiden);
DELEGATE(Prefetch);
DELEGATE(MemoryInit);
DELEGATE(DataDrop);
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index c01b56ec7..26764c304 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -1132,6 +1132,7 @@ public:
}
WASM_UNREACHABLE("invalid op");
}
+ Flow visitSIMDWiden(SIMDWiden* curr) { WASM_UNREACHABLE("unimp"); }
Flow visitSelect(Select* curr) {
NOTE_ENTER("Select");
Flow ifTrue = visit(curr->ifTrue);
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index 921ef6b4a..031589894 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -220,6 +220,7 @@ private:
Expression* makeSIMDShift(Element& s, SIMDShiftOp op);
Expression* makeSIMDLoad(Element& s, SIMDLoadOp op);
Expression* makeSIMDLoadStoreLane(Element& s, SIMDLoadStoreLaneOp op);
+ Expression* makeSIMDWiden(Element& s, SIMDWidenOp op);
Expression* makePrefetch(Element& s, PrefetchOp op);
Expression* makeMemoryInit(Element& s);
Expression* makeDataDrop(Element& s);
diff --git a/src/wasm.h b/src/wasm.h
index bd2e31814..0050fcc28 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -481,7 +481,7 @@ enum SIMDReplaceOp {
ReplaceLaneVecI32x4,
ReplaceLaneVecI64x2,
ReplaceLaneVecF32x4,
- ReplaceLaneVecF64x2
+ ReplaceLaneVecF64x2,
};
enum SIMDShiftOp {
@@ -537,6 +537,11 @@ enum SIMDTernaryOp {
SignSelectVec64x2
};
+enum SIMDWidenOp {
+ WidenSVecI8x16ToVecI32x4,
+ WidenUVecI8x16ToVecI32x4,
+};
+
enum PrefetchOp {
PrefetchTemporal,
PrefetchNontemporal,
@@ -625,6 +630,7 @@ public:
SIMDShiftId,
SIMDLoadId,
SIMDLoadStoreLaneId,
+ SIMDWidenId,
MemoryInitId,
DataDropId,
MemoryCopyId,
@@ -1072,6 +1078,18 @@ public:
void finalize();
};
+class SIMDWiden : public SpecificExpression<Expression::SIMDWidenId> {
+public:
+ SIMDWiden() = default;
+ SIMDWiden(MixedArena& allocator) {}
+
+ SIMDWidenOp op;
+ uint8_t index;
+ Expression* vec;
+
+ void finalize();
+};
+
class Prefetch : public SpecificExpression<Expression::PrefetchId> {
public:
Prefetch() = default;
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index b7ffcd8d7..2c473a254 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -3005,6 +3005,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
if (maybeVisitSIMDLoadStoreLane(curr, opcode)) {
break;
}
+ if (maybeVisitSIMDWiden(curr, opcode)) {
+ break;
+ }
if (maybeVisitPrefetch(curr, opcode)) {
break;
}
@@ -5466,6 +5469,27 @@ bool WasmBinaryBuilder::maybeVisitSIMDLoadStoreLane(Expression*& out,
return true;
}
+bool WasmBinaryBuilder::maybeVisitSIMDWiden(Expression*& out, uint32_t code) {
+ SIMDWidenOp op;
+ switch (code) {
+ case BinaryConsts::I32x4WidenSI8x16:
+ op = WidenSVecI8x16ToVecI32x4;
+ break;
+ case BinaryConsts::I32x4WidenUI8x16:
+ op = WidenUVecI8x16ToVecI32x4;
+ break;
+ default:
+ return false;
+ }
+ auto* curr = allocator.alloc<SIMDWiden>();
+ curr->op = op;
+ curr->index = getLaneIndex(4);
+ curr->vec = popNonVoidExpression();
+ curr->finalize();
+ out = curr;
+ return true;
+}
+
bool WasmBinaryBuilder::maybeVisitPrefetch(Expression*& out, uint32_t code) {
PrefetchOp op;
switch (code) {
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 3075f70d7..0dc121f2c 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -1666,6 +1666,15 @@ SExpressionWasmBuilder::makeSIMDLoadStoreLane(Element& s,
return ret;
}
+Expression* SExpressionWasmBuilder::makeSIMDWiden(Element& s, SIMDWidenOp op) {
+ auto* ret = allocator.alloc<SIMDWiden>();
+ ret->op = op;
+ ret->index = parseLaneIndex(s[1], 4);
+ ret->vec = parseExpression(s[2]);
+ ret->finalize();
+ return ret;
+}
+
Expression* SExpressionWasmBuilder::makePrefetch(Element& s, PrefetchOp op) {
Address offset, align;
size_t i = parseMemAttributes(s, offset, align, /*defaultAlign*/ 1);
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index d42080bac..cb8702d0c 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -691,6 +691,19 @@ void BinaryInstWriter::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
o << curr->index;
}
+void BinaryInstWriter::visitSIMDWiden(SIMDWiden* curr) {
+ o << int8_t(BinaryConsts::SIMDPrefix);
+ switch (curr->op) {
+ case WidenSVecI8x16ToVecI32x4:
+ o << U32LEB(BinaryConsts::I32x4WidenSI8x16);
+ break;
+ case WidenUVecI8x16ToVecI32x4:
+ o << U32LEB(BinaryConsts::I32x4WidenUI8x16);
+ break;
+ }
+ o << uint8_t(curr->index);
+}
+
void BinaryInstWriter::visitPrefetch(Prefetch* curr) {
o << int8_t(BinaryConsts::SIMDPrefix);
switch (curr->op) {
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index f8d8890ec..e9d2bf116 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -496,6 +496,11 @@ void SIMDLoadStoreLane::finalize() {
}
}
+void SIMDWiden::finalize() {
+ assert(vec);
+ type = vec->type == Type::unreachable ? Type::unreachable : Type::v128;
+}
+
Index SIMDLoadStoreLane::getMemBytes() {
switch (op) {
case LoadLaneVec8x16:
diff --git a/src/wasm2js.h b/src/wasm2js.h
index 43c5f4cbd..db25fd472 100644
--- a/src/wasm2js.h
+++ b/src/wasm2js.h
@@ -2119,6 +2119,10 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
unimplemented(curr);
WASM_UNREACHABLE("unimp");
}
+ Ref visitSIMDWiden(SIMDWiden* curr) {
+ unimplemented(curr);
+ WASM_UNREACHABLE("unimp");
+ }
Ref visitMemoryInit(MemoryInit* curr) {
ABI::wasm2js::ensureHelpers(module, ABI::wasm2js::MEMORY_INIT);
return ValueBuilder::makeCall(ABI::wasm2js::MEMORY_INIT,
diff --git a/test/binaryen.js/exception-handling.js.txt b/test/binaryen.js/exception-handling.js.txt
index e7c72e6a7..69b619564 100644
--- a/test/binaryen.js/exception-handling.js.txt
+++ b/test/binaryen.js/exception-handling.js.txt
@@ -19,6 +19,6 @@
)
)
-getExpressionInfo(throw) = {"id":47,"type":1,"event":"e"}
-getExpressionInfo(rethrow) = {"id":48,"type":1,"depth":0}
-getExpressionInfo(try) = {"id":46,"type":1,"hasCatchAll":0}
+getExpressionInfo(throw) = {"id":48,"type":1,"event":"e"}
+getExpressionInfo(rethrow) = {"id":49,"type":1,"depth":0}
+getExpressionInfo(try) = {"id":47,"type":1,"hasCatchAll":0}
diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt
index 5ad60b286..9b45d9a01 100644
--- a/test/binaryen.js/kitchen-sink.js.txt
+++ b/test/binaryen.js/kitchen-sink.js.txt
@@ -76,35 +76,35 @@ SIMDShuffleId: 32
SIMDTernaryId: 33
SIMDShiftId: 34
SIMDLoadId: 35
-MemoryInitId: 37
-DataDropId: 38
-MemoryCopyId: 39
-MemoryFillId: 40
-PopId: 41
-RefNullId: 42
-RefIsId: 43
-RefFuncId: 44
-RefEqId: 45
-TryId: 46
-ThrowId: 47
-RethrowId: 48
-TupleMakeId: 49
-TupleExtractId: 50
-I31NewId: 51
-I31GetId: 52
-CallRefId: 53
-RefTestId: 54
-RefCastId: 55
-BrOnId: 56
-RttCanonId: 57
-RttSubId: 58
-StructNewId: 59
-StructGetId: 60
-StructSetId: 61
-ArrayNewId: 62
-ArrayGetId: 63
-ArraySetId: 64
-ArrayLenId: 65
+MemoryInitId: 38
+DataDropId: 39
+MemoryCopyId: 40
+MemoryFillId: 41
+PopId: 42
+RefNullId: 43
+RefIsId: 44
+RefFuncId: 45
+RefEqId: 46
+TryId: 47
+ThrowId: 48
+RethrowId: 49
+TupleMakeId: 50
+TupleExtractId: 51
+I31NewId: 52
+I31GetId: 53
+CallRefId: 54
+RefTestId: 55
+RefCastId: 56
+BrOnId: 57
+RttCanonId: 58
+RttSubId: 59
+StructNewId: 60
+StructGetId: 61
+StructSetId: 62
+ArrayNewId: 63
+ArrayGetId: 64
+ArraySetId: 65
+ArrayLenId: 66
getExpressionInfo={"id":15,"type":4,"op":6}
(f32.neg
(f32.const -33.61199951171875)
diff --git a/test/simd.wast b/test/simd.wast
index a171c5398..8d12ea0ac 100644
--- a/test/simd.wast
+++ b/test/simd.wast
@@ -1436,4 +1436,14 @@
(local.get $0)
)
)
+ (func $i32x4.widen_i8x16_s (param $0 v128) (result v128)
+ (i32x4.widen_i8x16_s 0
+ (local.get $0)
+ )
+ )
+ (func $i32x4.widen_i8x16_u (param $0 v128) (result v128)
+ (i32x4.widen_i8x16_u 0
+ (local.get $0)
+ )
+ )
)
diff --git a/test/simd.wast.from-wast b/test/simd.wast.from-wast
index 223191c18..6fbacea11 100644
--- a/test/simd.wast.from-wast
+++ b/test/simd.wast.from-wast
@@ -1454,4 +1454,14 @@
(local.get $0)
)
)
+ (func $i32x4.widen_i8x16_s (param $0 v128) (result v128)
+ (i32x4.widen_i8x16_s 0
+ (local.get $0)
+ )
+ )
+ (func $i32x4.widen_i8x16_u (param $0 v128) (result v128)
+ (i32x4.widen_i8x16_u 0
+ (local.get $0)
+ )
+ )
)
diff --git a/test/simd.wast.fromBinary b/test/simd.wast.fromBinary
index 1c0b12493..4c84b5b25 100644
--- a/test/simd.wast.fromBinary
+++ b/test/simd.wast.fromBinary
@@ -1454,5 +1454,15 @@
(local.get $0)
)
)
+ (func $i32x4.widen_i8x16_s (param $0 v128) (result v128)
+ (i32x4.widen_i8x16_s 0
+ (local.get $0)
+ )
+ )
+ (func $i32x4.widen_i8x16_u (param $0 v128) (result v128)
+ (i32x4.widen_i8x16_u 0
+ (local.get $0)
+ )
+ )
)
diff --git a/test/simd.wast.fromBinary.noDebugInfo b/test/simd.wast.fromBinary.noDebugInfo
index 3feb5a7b4..bb5cdd5e0 100644
--- a/test/simd.wast.fromBinary.noDebugInfo
+++ b/test/simd.wast.fromBinary.noDebugInfo
@@ -1454,5 +1454,15 @@
(local.get $0)
)
)
+ (func $256 (param $0 v128) (result v128)
+ (i32x4.widen_i8x16_s 0
+ (local.get $0)
+ )
+ )
+ (func $257 (param $0 v128) (result v128)
+ (i32x4.widen_i8x16_u 0
+ (local.get $0)
+ )
+ )
)