mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-25 03:05:34 +00:00
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:
parent
a917df3a54
commit
e0fb4b123e
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
37
js/src/jit-test/tests/SIMD/saturate.js
Normal file
37
js/src/jit-test/tests/SIMD/saturate.js
Normal 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();
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user