Bug 1233111 - Implement SIMD shiftRightByScalar(). r=bbouvier

This is the right shift function that the SIMD.js spec requires. The old
shiftRightArithmeticByScalar() and shiftRightLogicalByScalar() functions will go
away.

These functions perform an arithmetic shift for signed types and a logical
shift for unsigned types.

Add support to Odin and Ion too, at least for the Int32x4 variant.

--HG--
extra : rebase_source : 7852f266a1ad505436c4c1607c17d542d81b2673
This commit is contained in:
Jakob Stoklund Olesen 2015-12-23 09:52:39 -08:00
Родитель c265e4ff17
Коммит 4ac36bc255
7 изменённых файлов: 52 добавлений и 2 удалений

Просмотреть файл

@ -77,6 +77,19 @@ enum AsmJSSimdType
AsmJSSimdType_bool32x4
};
static inline bool
IsSignedIntSimdType(AsmJSSimdType type)
{
switch (type) {
case AsmJSSimdType_int32x4:
return true;
case AsmJSSimdType_float32x4:
case AsmJSSimdType_bool32x4:
return false;
}
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Unknown SIMD type");
}
// Set of known operations, for a given SIMD type (int32x4, float32x4,...)
enum AsmJSSimdOperation
{

Просмотреть файл

@ -4970,6 +4970,10 @@ CheckSimdOperationCall(FunctionValidator& f, ParseNode* call, const ModuleValida
case AsmJSSimdOperation_shiftLeftByScalar:
return CheckSimdBinary(f, call, opType, MSimdShift::lsh, type);
case AsmJSSimdOperation_shiftRightByScalar:
return CheckSimdBinary(f, call, opType,
IsSignedIntSimdType(opType) ? MSimdShift::rsh : MSimdShift::ursh,
type);
case AsmJSSimdOperation_shiftRightArithmeticByScalar:
return CheckSimdBinary(f, call, opType, MSimdShift::rsh, type);
case AsmJSSimdOperation_shiftRightLogicalByScalar:

Просмотреть файл

@ -247,6 +247,7 @@
V(or, (BinaryFunc<Int8x16, Or, Int8x16>), 2) \
V(sub, (BinaryFunc<Int8x16, Sub, Int8x16>), 2) \
V(shiftLeftByScalar, (BinaryScalar<Int8x16, ShiftLeft>), 2) \
V(shiftRightByScalar, (BinaryScalar<Int8x16, ShiftRightArithmetic>), 2) \
V(shiftRightArithmeticByScalar, (BinaryScalar<Int8x16, ShiftRightArithmetic>), 2) \
V(shiftRightLogicalByScalar, (BinaryScalar<Int8x16, ShiftRightLogical>), 2) \
V(xor, (BinaryFunc<Int8x16, Xor, Int8x16>), 2)
@ -295,6 +296,7 @@
V(or, (BinaryFunc<Uint8x16, Or, Uint8x16>), 2) \
V(sub, (BinaryFunc<Uint8x16, Sub, Uint8x16>), 2) \
V(shiftLeftByScalar, (BinaryScalar<Uint8x16, ShiftLeft>), 2) \
V(shiftRightByScalar, (BinaryScalar<Uint8x16, ShiftRightLogical>), 2) \
V(shiftRightArithmeticByScalar, (BinaryScalar<Uint8x16, ShiftRightArithmetic>), 2) \
V(shiftRightLogicalByScalar, (BinaryScalar<Uint8x16, ShiftRightLogical>), 2) \
V(xor, (BinaryFunc<Uint8x16, Xor, Uint8x16>), 2)
@ -343,6 +345,7 @@
V(or, (BinaryFunc<Int16x8, Or, Int16x8>), 2) \
V(sub, (BinaryFunc<Int16x8, Sub, Int16x8>), 2) \
V(shiftLeftByScalar, (BinaryScalar<Int16x8, ShiftLeft>), 2) \
V(shiftRightByScalar, (BinaryScalar<Int16x8, ShiftRightArithmetic>), 2) \
V(shiftRightArithmeticByScalar, (BinaryScalar<Int16x8, ShiftRightArithmetic>), 2) \
V(shiftRightLogicalByScalar, (BinaryScalar<Int16x8, ShiftRightLogical>), 2) \
V(xor, (BinaryFunc<Int16x8, Xor, Int16x8>), 2)
@ -391,6 +394,7 @@
V(or, (BinaryFunc<Uint16x8, Or, Uint16x8>), 2) \
V(sub, (BinaryFunc<Uint16x8, Sub, Uint16x8>), 2) \
V(shiftLeftByScalar, (BinaryScalar<Uint16x8, ShiftLeft>), 2) \
V(shiftRightByScalar, (BinaryScalar<Uint16x8, ShiftRightLogical>), 2) \
V(shiftRightArithmeticByScalar, (BinaryScalar<Uint16x8, ShiftRightArithmetic>), 2) \
V(shiftRightLogicalByScalar, (BinaryScalar<Uint16x8, ShiftRightLogical>), 2) \
V(xor, (BinaryFunc<Uint16x8, Xor, Uint16x8>), 2)
@ -443,6 +447,7 @@
V(or, (BinaryFunc<Int32x4, Or, Int32x4>), 2) \
V(sub, (BinaryFunc<Int32x4, Sub, Int32x4>), 2) \
V(shiftLeftByScalar, (BinaryScalar<Int32x4, ShiftLeft>), 2) \
V(shiftRightByScalar, (BinaryScalar<Int32x4, ShiftRightArithmetic>), 2) \
V(shiftRightArithmeticByScalar, (BinaryScalar<Int32x4, ShiftRightArithmetic>), 2) \
V(shiftRightLogicalByScalar, (BinaryScalar<Int32x4, ShiftRightLogical>), 2) \
V(xor, (BinaryFunc<Int32x4, Xor, Int32x4>), 2)
@ -498,6 +503,7 @@
V(or, (BinaryFunc<Uint32x4, Or, Uint32x4>), 2) \
V(sub, (BinaryFunc<Uint32x4, Sub, Uint32x4>), 2) \
V(shiftLeftByScalar, (BinaryScalar<Uint32x4, ShiftLeft>), 2) \
V(shiftRightByScalar, (BinaryScalar<Uint32x4, ShiftRightLogical>), 2) \
V(shiftRightArithmeticByScalar, (BinaryScalar<Uint32x4, ShiftRightArithmetic>), 2) \
V(shiftRightLogicalByScalar, (BinaryScalar<Uint32x4, ShiftRightLogical>), 2) \
V(xor, (BinaryFunc<Uint32x4, Xor, Uint32x4>), 2)
@ -572,6 +578,7 @@
// Bitwise shifts defined on integer SIMD types.
#define FOREACH_SHIFT_SIMD_OP(_) \
_(shiftLeftByScalar) \
_(shiftRightByScalar) \
_(shiftRightArithmeticByScalar) \
_(shiftRightLogicalByScalar)

Просмотреть файл

@ -44,6 +44,13 @@ function f() {
assertEqX4(SIMD.Int32x4.shiftRightLogicalByScalar(v, 31), a.map(ursh(31)));
assertEqX4(SIMD.Int32x4.shiftRightLogicalByScalar(v, 32), a.map(ursh(32)));
assertEqX4(SIMD.Int32x4.shiftRightByScalar(v, -1), a.map(rsh(31)));
assertEqX4(SIMD.Int32x4.shiftRightByScalar(v, 0), a.map(rsh(0)));
assertEqX4(SIMD.Int32x4.shiftRightByScalar(v, 1), a.map(rsh(1)));
assertEqX4(SIMD.Int32x4.shiftRightByScalar(v, 2), a.map(rsh(2)));
assertEqX4(SIMD.Int32x4.shiftRightByScalar(v, 31), a.map(rsh(31)));
assertEqX4(SIMD.Int32x4.shiftRightByScalar(v, 32), a.map(rsh(31)));
// Non constant shift counts
var c = shifts[i % shifts.length];
assertEqX4(SIMD.Int32x4.shiftLeftByScalar(v, c), a.map(lsh(c)));

Просмотреть файл

@ -924,7 +924,8 @@ assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + NOTF32 + 'function f() {var x=f
// Logical ops
const LSHI = 'var lsh=i4.shiftLeftByScalar;'
const RSHI = 'var rsh=i4.shiftRightArithmeticByScalar;'
const RSHI = 'var rsh=i4.shiftRightByScalar;'
const ARSHI = 'var arsh=i4.shiftRightArithmeticByScalar;'
const URSHI = 'var ursh=i4.shiftRightLogicalByScalar;'
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + F32 + FROUND + LSHI + "function f() {var x=f4(1,2,3,4); return ci4(lsh(x,f32(42)));} return f");
@ -940,19 +941,23 @@ var vinput = [0, 1, INT32_MIN, INT32_MAX];
// Behave as x86 for now, fix when more broadly specified. See also bug 1068028
function Lsh(i) { if (i > 31) return () => 0; return function(x) { return (x << i) | 0 } }
function Rsh(i) { if (i > 31) return (x) => (x<0)?-1:0; return function(x) { return (x >> i) | 0 } }
function Arsh(i) { if (i > 31) return (x) => (x<0)?-1:0; return function(x) { return (x >> i) | 0 } }
function Ursh(i) { if (i > 31) return () => 0; return function(x) { return (x >>> i) | 0 } }
var asmLsh = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + LSHI + 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return ci4(lsh(v, x+y))} return f;'), this)
var asmRsh = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + RSHI + 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return ci4(rsh(v, x+y))} return f;'), this)
var asmArsh = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + ARSHI + 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return ci4(arsh(v, x+y))} return f;'), this)
var asmUrsh = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + URSHI + 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return ci4(ursh(v, x+y))} return f;'), this)
for (var i = 1; i < 64; i++) {
CheckI4(LSHI, 'var x=' + input + '; x=lsh(x, ' + i + ')', vinput.map(Lsh(i)));
CheckI4(RSHI, 'var x=' + input + '; x=rsh(x, ' + i + ')', vinput.map(Rsh(i)));
CheckI4(ARSHI, 'var x=' + input + '; x=arsh(x, ' + i + ')', vinput.map(Arsh(i)));
CheckI4(URSHI, 'var x=' + input + '; x=ursh(x, ' + i + ')', vinput.map(Ursh(i)));
assertEqX4(asmLsh(i, 3), vinput.map(Lsh(i + 3)));
assertEqX4(asmRsh(i, 3), vinput.map(Rsh(i + 3)));
assertEqX4(asmArsh(i, 3), vinput.map(Arsh(i + 3)));
assertEqX4(asmUrsh(i, 3), vinput.map(Ursh(i + 3)));
}

Просмотреть файл

@ -3107,8 +3107,10 @@ IonBuilder::inlineSimdInt32x4(CallInfo& callInfo, JSNative native)
if (native == js::simd_int32x4_shiftLeftByScalar)
return inlineBinarySimd<MSimdShift>(callInfo, native, MSimdShift::lsh, SimdTypeDescr::Int32x4);
if (native == js::simd_int32x4_shiftRightArithmeticByScalar)
if (native == js::simd_int32x4_shiftRightArithmeticByScalar ||
native == js::simd_int32x4_shiftRightByScalar) {
return inlineBinarySimd<MSimdShift>(callInfo, native, MSimdShift::rsh, SimdTypeDescr::Int32x4);
}
if (native == js::simd_int32x4_shiftRightLogicalByScalar)
return inlineBinarySimd<MSimdShift>(callInfo, native, MSimdShift::ursh, SimdTypeDescr::Int32x4);

Просмотреть файл

@ -91,6 +91,7 @@ function test() {
{
for (var bits = -2; bits < 12; bits++) {
testBinaryScalarFunc(v, bits, Int8x16.shiftLeftByScalar, lsh8);
testBinaryScalarFunc(v, bits, Int8x16.shiftRightByScalar, rsha8);
testBinaryScalarFunc(v, bits, Int8x16.shiftRightArithmeticByScalar, rsha8);
testBinaryScalarFunc(v, bits, Int8x16.shiftRightLogicalByScalar, rshl8);
}
@ -106,6 +107,7 @@ function test() {
{
for (var bits = -2; bits < 20; bits++) {
testBinaryScalarFunc(v, bits, Int16x8.shiftLeftByScalar, lsh16);
testBinaryScalarFunc(v, bits, Int16x8.shiftRightByScalar, rsha16);
testBinaryScalarFunc(v, bits, Int16x8.shiftRightArithmeticByScalar, rsha16);
testBinaryScalarFunc(v, bits, Int16x8.shiftRightLogicalByScalar, rshl16);
}
@ -121,6 +123,7 @@ function test() {
{
for (var bits = -2; bits < 36; bits++) {
testBinaryScalarFunc(v, bits, Int32x4.shiftLeftByScalar, lsh32);
testBinaryScalarFunc(v, bits, Int32x4.shiftRightByScalar, rsha32);
testBinaryScalarFunc(v, bits, Int32x4.shiftRightArithmeticByScalar, rsha32);
testBinaryScalarFunc(v, bits, Int32x4.shiftRightLogicalByScalar, rshl32);
}
@ -137,6 +140,7 @@ function test() {
{
for (var bits = -2; bits < 12; bits++) {
testBinaryScalarFunc(v, bits, Uint8x16.shiftLeftByScalar, ulsh8);
testBinaryScalarFunc(v, bits, Uint8x16.shiftRightByScalar, urshl8);
testBinaryScalarFunc(v, bits, Uint8x16.shiftRightArithmeticByScalar, ursha8);
testBinaryScalarFunc(v, bits, Uint8x16.shiftRightLogicalByScalar, urshl8);
}
@ -152,6 +156,7 @@ function test() {
{
for (var bits = -2; bits < 20; bits++) {
testBinaryScalarFunc(v, bits, Uint16x8.shiftLeftByScalar, ulsh16);
testBinaryScalarFunc(v, bits, Uint16x8.shiftRightByScalar, urshl16);
testBinaryScalarFunc(v, bits, Uint16x8.shiftRightArithmeticByScalar, ursha16);
testBinaryScalarFunc(v, bits, Uint16x8.shiftRightLogicalByScalar, urshl16);
}
@ -168,6 +173,7 @@ function test() {
{
for (var bits = -2; bits < 36; bits++) {
testBinaryScalarFunc(v, bits, Uint32x4.shiftLeftByScalar, ulsh32);
testBinaryScalarFunc(v, bits, Uint32x4.shiftRightByScalar, urshl32);
testBinaryScalarFunc(v, bits, Uint32x4.shiftRightArithmeticByScalar, ursha32);
testBinaryScalarFunc(v, bits, Uint32x4.shiftRightLogicalByScalar, urshl32);
}
@ -179,31 +185,37 @@ function test() {
var v = SIMD.Int8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
assertThrowsInstanceOf(() => SIMD.Int8x16.shiftLeftByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Int8x16.shiftRightByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Int8x16.shiftRightArithmeticByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Int8x16.shiftRightLogicalByScalar(v, bad), TestError);
var v = SIMD.Int16x8(1,2,3,4,5,6,7,8);
assertThrowsInstanceOf(() => SIMD.Int16x8.shiftLeftByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Int16x8.shiftRightByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Int16x8.shiftRightArithmeticByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Int16x8.shiftRightLogicalByScalar(v, bad), TestError);
var v = SIMD.Int32x4(1,2,3,4);
assertThrowsInstanceOf(() => SIMD.Int32x4.shiftLeftByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Int32x4.shiftRightByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Int32x4.shiftRightArithmeticByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Int32x4.shiftRightLogicalByScalar(v, bad), TestError);
var v = SIMD.Uint8x16(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
assertThrowsInstanceOf(() => SIMD.Uint8x16.shiftLeftByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Uint8x16.shiftRightByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Uint8x16.shiftRightArithmeticByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Uint8x16.shiftRightLogicalByScalar(v, bad), TestError);
var v = SIMD.Uint16x8(1,2,3,4,5,6,7,8);
assertThrowsInstanceOf(() => SIMD.Uint16x8.shiftLeftByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Uint16x8.shiftRightByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Uint16x8.shiftRightArithmeticByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Uint16x8.shiftRightLogicalByScalar(v, bad), TestError);
var v = SIMD.Uint32x4(1,2,3,4);
assertThrowsInstanceOf(() => SIMD.Uint32x4.shiftLeftByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Uint32x4.shiftRightByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Uint32x4.shiftRightArithmeticByScalar(v, bad), TestError);
assertThrowsInstanceOf(() => SIMD.Uint32x4.shiftRightLogicalByScalar(v, bad), TestError);