Skip to content
This repository was archived by the owner on Oct 15, 2019. It is now read-only.

Commit ff2323f

Browse files
Add prototype of the initial SIMD proposal at WebAssembly/simd#1
It's enabled by default, but if you wish to disable it you can with the CMake ENABLE_SIMD_PROTOTYPE option. This also includes an implementation of the Blake2b hash function with the proposed SIMD operators in Test/Blake2b/blake2b.wast
1 parent a7a0b53 commit ff2323f

File tree

17 files changed

+2254
-9
lines changed

17 files changed

+2254
-9
lines changed

CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@ else()
8686
add_definitions("-DPRETEND_32BIT_ADDRESS_SPACE=0")
8787
endif()
8888

89+
option(ENABLE_SIMD_PROTOTYPE "enables the prototype implementation of the proposed WebAssembly SIMD extension" ON)
90+
if(ENABLE_SIMD_PROTOTYPE)
91+
add_definitions("-DENABLE_SIMD_PROTOTYPE=1")
92+
else()
93+
add_definitions("-DENABLE_SIMD_PROTOTYPE=0")
94+
endif()
95+
8996
add_subdirectory(Include/Inline)
9097

9198
add_subdirectory(Source/Core)

Include/IR/OperatorLoggingProxy.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,36 @@ namespace IR
5757
template<size_t naturalAlignmentLog2>
5858
std::string describeImm(LoadOrStoreImm<naturalAlignmentLog2> imm) { return " align=" + std::to_string(1<<imm.alignmentLog2) + " offset=" + std::to_string(imm.offset); }
5959
std::string describeImm(MemoryImm) { return ""; }
60+
61+
#if ENABLE_SIMD_PROTOTYPE
62+
template<size_t numLanes>
63+
std::string describeImm(LaneIndexImm<numLanes> imm) { return " " + std::to_string(imm.laneIndex); }
64+
template<size_t numLanes>
65+
std::string describeImm(SwizzleImm<numLanes> imm)
66+
{
67+
std::string result = " [";
68+
const char* prefix = "";
69+
for(uintp laneIndex = 0;laneIndex < numLanes;++laneIndex)
70+
{
71+
result += prefix + std::to_string(imm.laneIndices[laneIndex]);
72+
prefix = ",";
73+
}
74+
return result;
75+
}
76+
template<size_t numLanes>
77+
std::string describeImm(ShuffleImm<numLanes> imm)
78+
{
79+
std::string result = " [";
80+
const char* prefix = "";
81+
for(uintp laneIndex = 0;laneIndex < numLanes;++laneIndex)
82+
{
83+
result += prefix
84+
+ (imm.laneIndices[laneIndex] < numLanes ? 'a' : 'b')
85+
+ std::to_string(imm.laneIndices[laneIndex]);
86+
prefix = ",";
87+
}
88+
return result;
89+
}
90+
#endif
6091
};
6192
}

Include/IR/Operators.h

Lines changed: 271 additions & 1 deletion
Large diffs are not rendered by default.

Include/IR/Types.h

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,15 @@ namespace IR
1616
i64 = 2,
1717
f32 = 3,
1818
f64 = 4,
19-
19+
20+
#if ENABLE_SIMD_PROTOTYPE
21+
v128 = 5,
22+
b8x16 = 6,
23+
b16x8 = 7,
24+
b32x4 = 8,
25+
b64x2 = 9,
26+
#endif
27+
2028
num,
2129
max = num-1
2230
};
@@ -26,6 +34,49 @@ namespace IR
2634
template<> struct ValueTypeInfo<ValueType::i64> { typedef int64 Value; };
2735
template<> struct ValueTypeInfo<ValueType::f32> { typedef float32 Value; };
2836
template<> struct ValueTypeInfo<ValueType::f64> { typedef float64 Value; };
37+
38+
#if ENABLE_SIMD_PROTOTYPE
39+
union V128
40+
{
41+
uint8 u8[16];
42+
int8 i8[16];
43+
uint16 u16[8];
44+
int16 i16[8];
45+
uint32 u32[4];
46+
int32 i32[4];
47+
uint64 u64[2];
48+
int64 i64[2];
49+
};
50+
51+
template<size_t numLanes>
52+
struct BoolVector
53+
{
54+
bool b[numLanes];
55+
};
56+
57+
template<size_t numLanes>
58+
std::string asString(const BoolVector<numLanes>& boolVector)
59+
{
60+
std::string result;
61+
for(uintp laneIndex = 0;laneIndex < numLanes;++laneIndex)
62+
{
63+
if(laneIndex != 0) { result += ','; }
64+
result += boolVector.b[laneIndex] ? '1' : '0';
65+
}
66+
return result;
67+
}
68+
69+
typedef BoolVector<16> B8x16;
70+
typedef BoolVector<8> B16x8;
71+
typedef BoolVector<4> B32x4;
72+
typedef BoolVector<2> B64x2;
73+
74+
template<> struct ValueTypeInfo<ValueType::v128> { typedef V128 Value; };
75+
template<> struct ValueTypeInfo<ValueType::b8x16> { typedef B8x16 Value; };
76+
template<> struct ValueTypeInfo<ValueType::b16x8> { typedef B16x8 Value; };
77+
template<> struct ValueTypeInfo<ValueType::b32x4> { typedef B32x4 Value; };
78+
template<> struct ValueTypeInfo<ValueType::b64x2> { typedef B64x2 Value; };
79+
#endif
2980

3081
inline uint8 getTypeBitWidth(ValueType type)
3182
{
@@ -35,6 +86,13 @@ namespace IR
3586
case ValueType::i64: return 64;
3687
case ValueType::f32: return 32;
3788
case ValueType::f64: return 64;
89+
#if ENABLE_SIMD_PROTOTYPE
90+
case ValueType::v128: return 128;
91+
case ValueType::b8x16: return 128;
92+
case ValueType::b16x8: return 128;
93+
case ValueType::b32x4: return 128;
94+
case ValueType::b64x2: return 128;
95+
#endif
3896
default: Core::unreachable();
3997
};
4098
}
@@ -48,6 +106,13 @@ namespace IR
48106
case ValueType::i64: return "i64";
49107
case ValueType::f32: return "f32";
50108
case ValueType::f64: return "f64";
109+
#if ENABLE_SIMD_PROTOTYPE
110+
case ValueType::v128: return "v128";
111+
case ValueType::b8x16: return "b8x16";
112+
case ValueType::b16x8: return "b16x8";
113+
case ValueType::b32x4: return "b32x4";
114+
case ValueType::b64x2: return "b64x2";
115+
#endif
51116
default: Core::unreachable();
52117
};
53118
}
@@ -60,6 +125,13 @@ namespace IR
60125
i64 = (uint8)ValueType::i64,
61126
f32 = (uint8)ValueType::f32,
62127
f64 = (uint8)ValueType::f64,
128+
#if ENABLE_SIMD_PROTOTYPE
129+
v128 = (uint8)ValueType::v128,
130+
b8x16 = (uint8)ValueType::b8x16,
131+
b16x8 = (uint8)ValueType::b16x8,
132+
b32x4 = (uint8)ValueType::b32x4,
133+
b64x2 = (uint8)ValueType::b64x2,
134+
#endif
63135
num,
64136
max = num-1,
65137
};
@@ -74,6 +146,13 @@ namespace IR
74146
case ResultType::i64: return "i64";
75147
case ResultType::f32: return "f32";
76148
case ResultType::f64: return "f64";
149+
#if ENABLE_SIMD_PROTOTYPE
150+
case ResultType::v128: return "v128";
151+
case ResultType::b8x16: return "b8x16";
152+
case ResultType::b16x8: return "b16x8";
153+
case ResultType::b32x4: return "b32x4";
154+
case ResultType::b64x2: return "b64x2";
155+
#endif
77156
case ResultType::none: return "()";
78157
default: Core::unreachable();
79158
};

Include/Runtime/Intrinsics.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@ namespace NativeTypes
104104
typedef float32 f32;
105105
typedef float64 f64;
106106
typedef void none;
107+
#if ENABLE_SIMD_PROTOTYPE
108+
typedef IR::V128 v128;
109+
typedef IR::V128 b8x16;
110+
typedef IR::V128 b16x8;
111+
typedef IR::V128 b32x4;
112+
typedef IR::V128 b64x2;
113+
#endif
107114
};
108115

109116
// Macros for defining intrinsic functions of various arities.

Include/Runtime/TaggedValue.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ namespace Runtime
1616
uint64 u64;
1717
float32 f32;
1818
float64 f64;
19+
#if ENABLE_SIMD_PROTOTYPE
20+
IR::V128 v128;
21+
IR::B8x16 b8x16;
22+
IR::B16x8 b16x8;
23+
IR::B32x4 b32x4;
24+
IR::B64x2 b64x2;
25+
#endif
1926
};
2027

2128
UntaggedValue(int32 inI32) { i32 = inI32; }
@@ -24,6 +31,13 @@ namespace Runtime
2431
UntaggedValue(uint64 inU64) { u64 = inU64; }
2532
UntaggedValue(float32 inF32) { f32 = inF32; }
2633
UntaggedValue(float64 inF64) { f64 = inF64; }
34+
#if ENABLE_SIMD_PROTOTYPE
35+
UntaggedValue(IR::V128 inV128) { v128 = inV128; }
36+
UntaggedValue(IR::B8x16 inB8x16) { b8x16 = inB8x16; }
37+
UntaggedValue(IR::B16x8 inB16x8) { b16x8 = inB16x8; }
38+
UntaggedValue(IR::B32x4 inB32x4) { b32x4 = inB32x4; }
39+
UntaggedValue(IR::B64x2 inB64x2) { b64x2 = inB64x2; }
40+
#endif
2741
UntaggedValue() {i64=0;}
2842
};
2943

@@ -38,6 +52,9 @@ namespace Runtime
3852
Value(uint64 inU64): UntaggedValue(inU64), type(IR::ValueType::i64) {}
3953
Value(float32 inF32): UntaggedValue(inF32), type(IR::ValueType::f32) {}
4054
Value(float64 inF64): UntaggedValue(inF64), type(IR::ValueType::f64) {}
55+
#if ENABLE_SIMD_PROTOTYPE
56+
Value(const IR::V128& inV128): UntaggedValue(inV128), type(IR::ValueType::v128) {}
57+
#endif
4158
Value(IR::ValueType inType,UntaggedValue inValue): UntaggedValue(inValue), type(inType) {}
4259
Value(): type(IR::ValueType::any) {}
4360

@@ -49,6 +66,13 @@ namespace Runtime
4966
case IR::ValueType::i64: return "i64(" + std::to_string(value.i64) + ")";
5067
case IR::ValueType::f32: return "f32(" + Floats::asString(value.f32) + ")";
5168
case IR::ValueType::f64: return "f64(" + Floats::asString(value.f64) + ")";
69+
#if ENABLE_SIMD_PROTOTYPE
70+
case IR::ValueType::v128: return "v128(" + std::to_string(value.v128.u64[0]) + "," + std::to_string(value.v128.u64[1]) + ")";
71+
case IR::ValueType::b8x16: return "b8x16(" + IR::asString(value.b8x16) + ')';
72+
case IR::ValueType::b16x8: return "b16x8(" + IR::asString(value.b16x8) + ')';
73+
case IR::ValueType::b32x4: return "b32x4(" + IR::asString(value.b32x4) + ')';
74+
case IR::ValueType::b64x2: return "b64x2(" + IR::asString(value.b64x2) + ')';
75+
#endif
5276
default: Core::unreachable();
5377
}
5478
}
@@ -65,6 +89,9 @@ namespace Runtime
6589
Result(uint64 inU64): UntaggedValue(inU64), type(IR::ResultType::i64) {}
6690
Result(float32 inF32): UntaggedValue(inF32), type(IR::ResultType::f32) {}
6791
Result(float64 inF64): UntaggedValue(inF64), type(IR::ResultType::f64) {}
92+
#if ENABLE_SIMD_PROTOTYPE
93+
Result(const IR::V128& inV128): UntaggedValue(inV128), type(IR::ResultType::v128) {}
94+
#endif
6895
Result(IR::ResultType inType,UntaggedValue inValue): UntaggedValue(inValue), type(inType) {}
6996
Result(const Value& inValue): UntaggedValue(inValue), type(asResultType(inValue.type)) {}
7097
Result(): type(IR::ResultType::none) {}
@@ -78,6 +105,13 @@ namespace Runtime
78105
case IR::ResultType::i64: return "i64(" + std::to_string(result.i64) + ")";
79106
case IR::ResultType::f32: return "f32(" + Floats::asString(result.f32) + ")";
80107
case IR::ResultType::f64: return "f64(" + Floats::asString(result.f64) + ")";
108+
#if ENABLE_SIMD_PROTOTYPE
109+
case IR::ResultType::v128: return "v128(" + std::to_string(result.v128.u64[0]) + "," + std::to_string(result.v128.u64[1]) + ")";
110+
case IR::ValueType::b8x16: return "b8x16(" + IR::asString(result.b8x16) + ')';
111+
case IR::ValueType::b16x8: return "b16x8(" + IR::asString(result.b16x8) + ')';
112+
case IR::ValueType::b32x4: return "b32x4(" + IR::asString(result.b32x4) + ')';
113+
case IR::ValueType::b64x2: return "b64x2(" + IR::asString(result.b64x2) + ')';
114+
#endif
81115
default: Core::unreachable();
82116
}
83117
}
@@ -92,6 +126,9 @@ namespace Runtime
92126
case IR::ResultType::f32: return a.i32 == b.i32;
93127
case IR::ResultType::i64:
94128
case IR::ResultType::f64: return a.i64 == b.i64;
129+
#if ENABLE_SIMD_PROTOTYPE
130+
case IR::ResultType::v128: return a.v128.u64[0] == b.v128.u64[0] && a.v128.u64[1] == b.v128.u64[1];
131+
#endif
95132
case IR::ResultType::none: return true;
96133
default: Core::unreachable();
97134
};

Source/IR/Validate.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,32 @@ namespace IR
318318
VALIDATE_UNLESS("current_memory and grow_memory are only valid if there is a default memory",module.memories.size() == 0);
319319
}
320320

321+
#if ENABLE_SIMD_PROTOTYPE
322+
template<size_t numLanes>
323+
void validateImm(LaneIndexImm<numLanes> imm)
324+
{
325+
VALIDATE_UNLESS("swizzle invalid lane index",imm.laneIndex>=numLanes);
326+
}
327+
328+
template<size_t numLanes>
329+
void validateImm(SwizzleImm<numLanes> imm)
330+
{
331+
for(uintp laneIndex = 0;laneIndex < numLanes;++laneIndex)
332+
{
333+
VALIDATE_UNLESS("swizzle invalid lane index",imm.laneIndices[laneIndex]>=numLanes);
334+
}
335+
}
336+
337+
template<size_t numLanes>
338+
void validateImm(ShuffleImm<numLanes> imm)
339+
{
340+
for(uintp laneIndex = 0;laneIndex < numLanes;++laneIndex)
341+
{
342+
VALIDATE_UNLESS("shuffle invalid lane index",imm.laneIndices[laneIndex]>=numLanes*2);
343+
}
344+
}
345+
#endif
346+
321347
#define LOAD(resultTypeId) \
322348
popAndValidateOperand(operatorName,ValueType::i32); \
323349
pushOperand(ResultType::resultTypeId);
@@ -332,6 +358,21 @@ namespace IR
332358
popAndValidateOperand(operatorName,ValueType::operandTypeId); \
333359
pushOperand(ResultType::resultTypeId)
334360

361+
#if ENABLE_SIMD_PROTOTYPE
362+
#define VECTORSELECT(vectorTypeId,scalarTypeId) \
363+
popAndValidateOperands(operatorName,ValueType::vectorTypeId,ValueType::vectorTypeId,ValueType::scalarTypeId); \
364+
pushOperand(ValueType::vectorTypeId);
365+
#define BUILDVECTOR(scalarTypeId,numLanes,vectorTypeId) \
366+
for(uintp laneIndex = 0;laneIndex < numLanes;++laneIndex) \
367+
{ \
368+
popAndValidateOperand(operatorName,ValueType::scalarTypeId); \
369+
} \
370+
pushOperand(ValueType::vectorTypeId);
371+
#define REPLACELANE(scalarTypeId,vectorTypeId) \
372+
popAndValidateOperands(operatorName,ValueType::vectorTypeId,ValueType::scalarTypeId); \
373+
pushOperand(ValueType::vectorTypeId);
374+
#endif
375+
335376
#define VALIDATE_OP(opcode,name,nameString,Imm,validateOperands) \
336377
void name(Imm imm) \
337378
{ \

0 commit comments

Comments
 (0)