mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1044256: SIMD: Add support for unary operators in Odin; r=luke
This commit is contained in:
parent
2abf42f482
commit
66b40bb34e
@ -2427,6 +2427,17 @@ class FunctionCompiler
|
||||
return ins;
|
||||
}
|
||||
|
||||
MDefinition *unarySimd(MDefinition *input, MSimdUnaryArith::Operation op, MIRType type)
|
||||
{
|
||||
if (inDeadCode())
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT(IsSimdType(input->type()) && input->type() == type);
|
||||
MInstruction *ins = MSimdUnaryArith::NewAsmJS(alloc(), input, op, type);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
|
||||
MDefinition *binarySimd(MDefinition *lhs, MDefinition *rhs, MSimdBinaryArith::Operation op,
|
||||
MIRType type)
|
||||
{
|
||||
@ -4853,6 +4864,18 @@ class CheckSimdVectorScalarArgs
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
static inline bool
|
||||
CheckSimdUnary(FunctionCompiler &f, ParseNode *call, Type retType, MSimdUnaryArith::Operation op,
|
||||
MDefinition **def, Type *type)
|
||||
{
|
||||
DefinitionVector defs;
|
||||
if (!CheckSimdCallArgs(f, call, 1, CheckArgIsSubtypeOf(retType), &defs))
|
||||
return false;
|
||||
*def = f.unarySimd(defs[0], op, retType.toMIRType());
|
||||
*type = retType;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class OpEnum>
|
||||
static inline bool
|
||||
CheckSimdBinary(FunctionCompiler &f, ParseNode *call, Type retType, OpEnum op, MDefinition **def,
|
||||
@ -4985,6 +5008,19 @@ CheckSimdOperationCall(FunctionCompiler &f, ParseNode *call, const ModuleCompile
|
||||
case AsmJSSimdOperation_shiftRightLogical:
|
||||
return CheckSimdBinary(f, call, Type::Int32x4, MSimdShift::ursh, def, type);
|
||||
|
||||
case AsmJSSimdOperation_abs:
|
||||
return CheckSimdUnary(f, call, retType, MSimdUnaryArith::abs, def, type);
|
||||
case AsmJSSimdOperation_neg:
|
||||
return CheckSimdUnary(f, call, retType, MSimdUnaryArith::neg, def, type);
|
||||
case AsmJSSimdOperation_not:
|
||||
return CheckSimdUnary(f, call, retType, MSimdUnaryArith::not_, def, type);
|
||||
case AsmJSSimdOperation_sqrt:
|
||||
return CheckSimdUnary(f, call, retType, MSimdUnaryArith::sqrt, def, type);
|
||||
case AsmJSSimdOperation_reciprocal:
|
||||
return CheckSimdUnary(f, call, retType, MSimdUnaryArith::reciprocal, def, type);
|
||||
case AsmJSSimdOperation_reciprocalSqrt:
|
||||
return CheckSimdUnary(f, call, retType, MSimdUnaryArith::reciprocalSqrt, def, type);
|
||||
|
||||
case AsmJSSimdOperation_splat: {
|
||||
DefinitionVector defs;
|
||||
Type formalType = retType.simdToCoercedScalarType();
|
||||
|
@ -120,6 +120,10 @@
|
||||
_(shiftRight) \
|
||||
_(shiftRightLogical)
|
||||
#define FOREACH_FLOAT32X4_SIMD_OP(_) \
|
||||
_(abs) \
|
||||
_(sqrt) \
|
||||
_(reciprocal) \
|
||||
_(reciprocalSqrt) \
|
||||
_(fromInt32x4) \
|
||||
_(fromInt32x4Bits) \
|
||||
_(mul) \
|
||||
@ -143,7 +147,9 @@
|
||||
_(withX) \
|
||||
_(withY) \
|
||||
_(withZ) \
|
||||
_(withW)
|
||||
_(withW) \
|
||||
_(not) \
|
||||
_(neg)
|
||||
#define FORALL_SIMD_OP(_) \
|
||||
FOREACH_INT32X4_SIMD_OP(_) \
|
||||
FOREACH_FLOAT32X4_SIMD_OP(_) \
|
||||
|
@ -24,11 +24,14 @@ const INT32_MIN = INT32_MAX + 1 | 0;
|
||||
|
||||
const assertEqFFI = {assertEq:assertEq};
|
||||
|
||||
function assertEqX4(real, expected) {
|
||||
assertEq(real.x, expected[0]);
|
||||
assertEq(real.y, expected[1]);
|
||||
assertEq(real.z, expected[2]);
|
||||
assertEq(real.w, expected[3]);
|
||||
function assertEqX4(real, expected, assertFunc) {
|
||||
if (typeof assertFunc === 'undefined')
|
||||
assertFunc = assertEq;
|
||||
|
||||
assertFunc(real.x, expected[0]);
|
||||
assertFunc(real.y, expected[1]);
|
||||
assertFunc(real.z, expected[2]);
|
||||
assertFunc(real.w, expected[3]);
|
||||
}
|
||||
|
||||
function CheckI4(header, code, expected) {
|
||||
@ -444,6 +447,68 @@ CheckF4(F32M, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4m(x,y)', [4,6,15,8]);
|
||||
CheckF4(F32M, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4m(x,y)', [Math.fround(13.37) * 4,6,15,8]);
|
||||
CheckF4(F32M, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4(f4m(x,y))', [Math.fround(13.37) * 4,6,15,8]);
|
||||
|
||||
// Unary arithmetic operators
|
||||
function CheckUnaryF4(op, checkFunc, assertFunc) {
|
||||
var _ = asmLink(asmCompile('glob', USE_ASM + F32 + 'var op=f4.' + op + '; function f(x){x=f4(x); return f4(op(x)); } return f'), this);
|
||||
return function(input) {
|
||||
var simd = SIMD.float32x4(input[0], input[1], input[2], input[3]);
|
||||
|
||||
var exp = input.map(Math.fround).map(checkFunc).map(Math.fround);
|
||||
var obs = _(simd);
|
||||
assertEqX4(obs, exp, assertFunc);
|
||||
}
|
||||
}
|
||||
|
||||
function CheckUnaryI4(op, checkFunc) {
|
||||
var _ = asmLink(asmCompile('glob', USE_ASM + I32 + 'var op=i4.' + op + '; function f(x){x=i4(x); return i4(op(x)); } return f'), this);
|
||||
return function(input) {
|
||||
var simd = SIMD.int32x4(input[0], input[1], input[2], input[3]);
|
||||
assertEqX4(_(simd), input.map(checkFunc).map(function(x) { return x | 0}));
|
||||
}
|
||||
}
|
||||
|
||||
CheckUnaryI4('neg', function(x) { return -x })([1, -2, INT32_MIN, INT32_MAX]);
|
||||
CheckUnaryI4('not', function(x) { return ~x })([1, -2, INT32_MIN, INT32_MAX]);
|
||||
|
||||
var CheckAbs = CheckUnaryF4('abs', Math.abs);
|
||||
CheckAbs([1, 42.42, 0.63, 13.37]);
|
||||
CheckAbs([NaN, -Infinity, Infinity, 0]);
|
||||
|
||||
var CheckNegF = CheckUnaryF4('neg', function(x) { return -x });
|
||||
CheckNegF([1, 42.42, 0.63, 13.37]);
|
||||
CheckNegF([NaN, -Infinity, Infinity, 0]);
|
||||
|
||||
var CheckNotF = CheckUnaryF4('not', (function() {
|
||||
var f32 = new Float32Array(1);
|
||||
var i32 = new Int32Array(f32.buffer);
|
||||
return function(x) {
|
||||
f32[0] = x;
|
||||
i32[0] = ~i32[0];
|
||||
return f32[0];
|
||||
}
|
||||
})());
|
||||
CheckNotF([1, 42.42, 0.63, 13.37]);
|
||||
CheckNotF([NaN, -Infinity, Infinity, 0]);
|
||||
|
||||
var CheckSqrt = CheckUnaryF4('sqrt', function(x) { return Math.sqrt(x); });
|
||||
CheckSqrt([1, 42.42, 0.63, 13.37]);
|
||||
CheckSqrt([NaN, -Infinity, Infinity, 0]);
|
||||
|
||||
// Reciprocal and reciprocalSqrt give approximate results
|
||||
function assertNear(a, b) {
|
||||
if (a !== a && b === b)
|
||||
throw 'Observed NaN, expected ' + b;
|
||||
if (Math.abs(a - b) > 1e-3)
|
||||
throw 'More than 1e-3 between ' + a + ' and ' + b;
|
||||
}
|
||||
var CheckRecp = CheckUnaryF4('reciprocal', function(x) { return 1 / x; }, assertNear);
|
||||
CheckRecp([1, 42.42, 0.63, 13.37]);
|
||||
CheckRecp([NaN, -Infinity, Infinity, 0]);
|
||||
|
||||
var CheckRecp = CheckUnaryF4('reciprocalSqrt', function(x) { return 1 / Math.sqrt(x); }, assertNear);
|
||||
CheckRecp([1, 42.42, 0.63, 13.37]);
|
||||
CheckRecp([NaN, -Infinity, Infinity, 0]);
|
||||
|
||||
// Min/Max
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + "var f4m=i4.min; function f() {} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + "var f4d=i4.max; function f() {} return f");
|
||||
|
Loading…
Reference in New Issue
Block a user