Bug 1136226 - Inline saturating arithmetic operations. r=sunfish

Add support for inlining addSaturate and subSaturate SIMD operations when
compiling SIMD.js.
This commit is contained in:
Jakob Stoklund Olesen 2016-05-31 09:00:20 -07:00
parent a917df3a54
commit e0fb4b123e
6 changed files with 73 additions and 14 deletions

View File

@ -9,11 +9,11 @@ function booleanBinaryX4(op, v, w) {
return arr; return arr;
} }
function binaryX4(op, v, w) { function binaryX(op, v, w) {
var arr = []; var arr = [];
var [varr, warr] = [simdToArray(v), simdToArray(w)]; var [varr, warr] = [simdToArray(v), simdToArray(w)];
[varr, warr] = [varr.map(Math.fround), warr.map(Math.fround)]; [varr, warr] = [varr.map(Math.fround), warr.map(Math.fround)];
for (var i = 0; i < 4; i++) for (var i = 0; i < varr.length; i++)
arr[i] = op(varr[i], warr[i]); arr[i] = op(varr[i], warr[i]);
return arr.map(Math.fround); return arr.map(Math.fround);
} }

View File

@ -10,13 +10,13 @@ function f() {
var f2 = SIMD.Float32x4(4, 3, 2, 1); var f2 = SIMD.Float32x4(4, 3, 2, 1);
for (var i = 0; i < 150; i++) { for (var i = 0; i < 150; i++) {
assertEqX4(SIMD.Float32x4.add(f1, f2), binaryX4((x, y) => x + y, f1, f2)); assertEqX4(SIMD.Float32x4.add(f1, f2), binaryX((x, y) => x + y, f1, f2));
assertEqX4(SIMD.Float32x4.sub(f1, f2), binaryX4((x, y) => x - y, f1, f2)); assertEqX4(SIMD.Float32x4.sub(f1, f2), binaryX((x, y) => x - y, f1, f2));
assertEqX4(SIMD.Float32x4.mul(f1, f2), binaryX4((x, y) => x * y, f1, f2)); assertEqX4(SIMD.Float32x4.mul(f1, f2), binaryX((x, y) => x * y, f1, f2));
assertEqX4(SIMD.Int32x4.add(i1, i2), binaryX4((x, y) => x + y, i1, i2)); assertEqX4(SIMD.Int32x4.add(i1, i2), binaryX((x, y) => x + y, i1, i2));
assertEqX4(SIMD.Int32x4.sub(i1, i2), binaryX4((x, y) => x - y, i1, i2)); assertEqX4(SIMD.Int32x4.sub(i1, i2), binaryX((x, y) => x - y, i1, i2));
assertEqX4(SIMD.Int32x4.mul(i1, i2), binaryX4((x, y) => x * y, i1, i2)); assertEqX4(SIMD.Int32x4.mul(i1, i2), binaryX((x, y) => x * y, i1, i2));
} }
} }

View File

@ -22,11 +22,11 @@ function f() {
var f1 = SIMD.Float32x4(1, 2, 3, 4); var f1 = SIMD.Float32x4(1, 2, 3, 4);
var f2 = SIMD.Float32x4(4, 3, 2, 1); var f2 = SIMD.Float32x4(4, 3, 2, 1);
for (var i = 0; i < 150; i++) { for (var i = 0; i < 150; i++) {
assertEqX4(SIMD.Float32x4.div(f1, f2), binaryX4((x, y) => x / y, f1, f2)); assertEqX4(SIMD.Float32x4.div(f1, f2), binaryX((x, y) => x / y, f1, f2));
assertEqX4(SIMD.Float32x4.min(f1, f2), binaryX4(Math.min, f1, f2)); assertEqX4(SIMD.Float32x4.min(f1, f2), binaryX(Math.min, f1, f2));
assertEqX4(SIMD.Float32x4.max(f1, f2), binaryX4(Math.max, f1, f2)); assertEqX4(SIMD.Float32x4.max(f1, f2), binaryX(Math.max, f1, f2));
assertEqX4(SIMD.Float32x4.minNum(f1, f2), binaryX4(minNum, f1, f2)); assertEqX4(SIMD.Float32x4.minNum(f1, f2), binaryX(minNum, f1, f2));
assertEqX4(SIMD.Float32x4.maxNum(f1, f2), binaryX4(maxNum, f1, f2)); assertEqX4(SIMD.Float32x4.maxNum(f1, f2), binaryX(maxNum, f1, f2));
} }
} }

View File

@ -0,0 +1,37 @@
load(libdir + 'simd.js');
setJitCompilerOption("ion.warmup.trigger", 50);
const INT8_MIN = -128;
const INT8_MAX = 127;
const UINT8_MAX = 255;
function sat8(x) {
if (x < INT8_MIN) return INT8_MIN;
if (x > INT8_MAX) return INT8_MAX;
return x;
}
function usat8(x) {
if (x < 0) return 0;
if (x > UINT8_MAX) return UINT8_MAX;
return x;
}
function f() {
var i1 = SIMD.Int8x16(1, 100, 3, 4);
var i2 = SIMD.Int8x16(4, 30, 2, 1);
var u1 = SIMD.Uint8x16(1, 2, 3, 4);
var u2 = SIMD.Uint8x16(4, 3, 2, 1);
for (var i = 0; i < 150; i++) {
assertEqX4(SIMD.Int8x16.addSaturate(i1, i2), binaryX((x, y) => sat8(x + y), i1, i2));
assertEqX4(SIMD.Int8x16.subSaturate(i1, i2), binaryX((x, y) => sat8(x - y), i1, i2));
assertEqX4(SIMD.Uint8x16.addSaturate(u1, u2), binaryX((x, y) => usat8(x + y), u1, u2));
assertEqX4(SIMD.Uint8x16.subSaturate(u1, u2), binaryX((x, y) => usat8(x - y), u1, u2));
}
}
f();

View File

@ -918,6 +918,8 @@ class IonBuilder
template <typename T> template <typename T>
InliningStatus inlineSimdBinary(CallInfo& callInfo, JSNative native, InliningStatus inlineSimdBinary(CallInfo& callInfo, JSNative native,
typename T::Operation op, SimdType type); typename T::Operation op, SimdType type);
InliningStatus inlineSimdBinarySaturating(CallInfo& callInfo, JSNative native,
MSimdBinarySaturating::Operation op, SimdType type);
InliningStatus inlineSimdShift(CallInfo& callInfo, JSNative native, MSimdShift::Operation op, InliningStatus inlineSimdShift(CallInfo& callInfo, JSNative native, MSimdShift::Operation op,
SimdType type); SimdType type);
InliningStatus inlineSimdComp(CallInfo& callInfo, JSNative native, InliningStatus inlineSimdComp(CallInfo& callInfo, JSNative native,

View File

@ -3268,9 +3268,12 @@ IonBuilder::inlineSimd(CallInfo& callInfo, JSFunction* target, SimdType type)
case SimdOperation::Fn_minNum: case SimdOperation::Fn_minNum:
return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_minNum, return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_minNum,
type); type);
// Binary saturating.
case SimdOperation::Fn_addSaturate: case SimdOperation::Fn_addSaturate:
return inlineSimdBinarySaturating(callInfo, native, MSimdBinarySaturating::add, type);
case SimdOperation::Fn_subSaturate: case SimdOperation::Fn_subSaturate:
MOZ_CRASH("NYI"); return inlineSimdBinarySaturating(callInfo, native, MSimdBinarySaturating::sub, type);
// Binary bitwise. // Binary bitwise.
case SimdOperation::Fn_and: case SimdOperation::Fn_and:
@ -3563,6 +3566,23 @@ IonBuilder::inlineSimdBinary(CallInfo& callInfo, JSNative native, typename T::Op
return boxSimd(callInfo, ins, templateObj); return boxSimd(callInfo, ins, templateObj);
} }
// Inline a binary SIMD operation where both arguments are SIMD types.
IonBuilder::InliningStatus
IonBuilder::inlineSimdBinarySaturating(CallInfo& callInfo, JSNative native,
MSimdBinarySaturating::Operation op, SimdType type)
{
InlineTypedObject* templateObj = nullptr;
if (!canInlineSimd(callInfo, native, 2, &templateObj))
return InliningStatus_NotInlined;
MDefinition* lhs = unboxSimd(callInfo.getArg(0), type);
MDefinition* rhs = unboxSimd(callInfo.getArg(1), type);
MSimdBinarySaturating* ins =
MSimdBinarySaturating::New(alloc(), lhs, rhs, op, GetSimdSign(type));
return boxSimd(callInfo, ins, templateObj);
}
// Inline a SIMD shiftByScalar operation. // Inline a SIMD shiftByScalar operation.
IonBuilder::InliningStatus IonBuilder::InliningStatus
IonBuilder::inlineSimdShift(CallInfo& callInfo, JSNative native, MSimdShift::Operation op, IonBuilder::inlineSimdShift(CallInfo& callInfo, JSNative native, MSimdShift::Operation op,