mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1060789: OdinMonkey SIMD: Add support for splat; r=luke
This commit is contained in:
parent
7823b27296
commit
1cadd3c1dd
@ -352,6 +352,7 @@ ValidateSimdOperation(JSContext *cx, AsmJSModule::Global &global, HandleValue gl
|
|||||||
case AsmJSSimdOperation_or: native = simd_int32x4_or; break;
|
case AsmJSSimdOperation_or: native = simd_int32x4_or; break;
|
||||||
case AsmJSSimdOperation_xor: native = simd_int32x4_xor; break;
|
case AsmJSSimdOperation_xor: native = simd_int32x4_xor; break;
|
||||||
case AsmJSSimdOperation_select: native = simd_int32x4_select; break;
|
case AsmJSSimdOperation_select: native = simd_int32x4_select; break;
|
||||||
|
case AsmJSSimdOperation_splat: native = simd_int32x4_splat; break;
|
||||||
case AsmJSSimdOperation_lessThanOrEqual:
|
case AsmJSSimdOperation_lessThanOrEqual:
|
||||||
case AsmJSSimdOperation_greaterThanOrEqual:
|
case AsmJSSimdOperation_greaterThanOrEqual:
|
||||||
case AsmJSSimdOperation_notEqual:
|
case AsmJSSimdOperation_notEqual:
|
||||||
@ -377,6 +378,7 @@ ValidateSimdOperation(JSContext *cx, AsmJSModule::Global &global, HandleValue gl
|
|||||||
case AsmJSSimdOperation_or: native = simd_float32x4_or; break;
|
case AsmJSSimdOperation_or: native = simd_float32x4_or; break;
|
||||||
case AsmJSSimdOperation_xor: native = simd_float32x4_xor; break;
|
case AsmJSSimdOperation_xor: native = simd_float32x4_xor; break;
|
||||||
case AsmJSSimdOperation_select: native = simd_float32x4_select; break;
|
case AsmJSSimdOperation_select: native = simd_float32x4_select; break;
|
||||||
|
case AsmJSSimdOperation_splat: native = simd_float32x4_splat; break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,7 @@ enum AsmJSSimdOperation
|
|||||||
AsmJSSimdOperation_or,
|
AsmJSSimdOperation_or,
|
||||||
AsmJSSimdOperation_xor,
|
AsmJSSimdOperation_xor,
|
||||||
AsmJSSimdOperation_select,
|
AsmJSSimdOperation_select,
|
||||||
|
AsmJSSimdOperation_splat
|
||||||
};
|
};
|
||||||
|
|
||||||
// These labels describe positions in the prologue/epilogue of functions while
|
// These labels describe positions in the prologue/epilogue of functions while
|
||||||
|
@ -1378,7 +1378,8 @@ class MOZ_STACK_CLASS ModuleCompiler
|
|||||||
!addStandardLibrarySimdOpName("and", AsmJSSimdOperation_and) ||
|
!addStandardLibrarySimdOpName("and", AsmJSSimdOperation_and) ||
|
||||||
!addStandardLibrarySimdOpName("or", AsmJSSimdOperation_or) ||
|
!addStandardLibrarySimdOpName("or", AsmJSSimdOperation_or) ||
|
||||||
!addStandardLibrarySimdOpName("xor", AsmJSSimdOperation_xor) ||
|
!addStandardLibrarySimdOpName("xor", AsmJSSimdOperation_xor) ||
|
||||||
!addStandardLibrarySimdOpName("select", AsmJSSimdOperation_select))
|
!addStandardLibrarySimdOpName("select", AsmJSSimdOperation_select) ||
|
||||||
|
!addStandardLibrarySimdOpName("splat", AsmJSSimdOperation_splat))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -3524,6 +3525,7 @@ IsSimdValidOperationType(AsmJSSimdType type, AsmJSSimdOperation op)
|
|||||||
case AsmJSSimdOperation_or:
|
case AsmJSSimdOperation_or:
|
||||||
case AsmJSSimdOperation_xor:
|
case AsmJSSimdOperation_xor:
|
||||||
case AsmJSSimdOperation_select:
|
case AsmJSSimdOperation_select:
|
||||||
|
case AsmJSSimdOperation_splat:
|
||||||
return true;
|
return true;
|
||||||
case AsmJSSimdOperation_mul:
|
case AsmJSSimdOperation_mul:
|
||||||
case AsmJSSimdOperation_div:
|
case AsmJSSimdOperation_div:
|
||||||
@ -4692,6 +4694,38 @@ CheckMathBuiltinCall(FunctionCompiler &f, ParseNode *callNode, AsmJSMathBuiltinF
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
CheckUnarySimd(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Global *global,
|
||||||
|
MDefinition **def, Type *type)
|
||||||
|
{
|
||||||
|
unsigned numArgs = CallArgListLength(call);
|
||||||
|
if (numArgs != 1)
|
||||||
|
return f.failf(call, "expected 1 argument to unary arithmetic SIMD operation, got %u", numArgs);
|
||||||
|
|
||||||
|
ParseNode *arg = CallArgList(call);
|
||||||
|
MDefinition *argDef;
|
||||||
|
Type argType;
|
||||||
|
if (!CheckExpr(f, arg, &argDef, &argType))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// For now, the only unary SIMD operation is splat(scalar).
|
||||||
|
MOZ_ASSERT(global->simdOperation() == AsmJSSimdOperation_splat);
|
||||||
|
switch (global->simdOperationType()) {
|
||||||
|
case AsmJSSimdType_int32x4:
|
||||||
|
if (!argType.isIntish())
|
||||||
|
return f.failf(arg, "%s is not a subtype of intish", argType.toChars());
|
||||||
|
break;
|
||||||
|
case AsmJSSimdType_float32x4:
|
||||||
|
if (!CheckFloatCoercionArg(f, arg, argType, argDef, &argDef))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*type = global->simdOperationType();
|
||||||
|
*def = f.simdSplat<MSimdSplatX4>(argDef, type->toMIRType());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
CheckBinarySimd(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Global *global,
|
CheckBinarySimd(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Global *global,
|
||||||
MDefinition **def, Type *type)
|
MDefinition **def, Type *type)
|
||||||
@ -4714,7 +4748,6 @@ CheckBinarySimd(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Glob
|
|||||||
if (lhsType != retType || rhsType != retType)
|
if (lhsType != retType || rhsType != retType)
|
||||||
return f.failf(lhs, "arguments to SIMD binary op should both be %s", retType.toChars());
|
return f.failf(lhs, "arguments to SIMD binary op should both be %s", retType.toChars());
|
||||||
|
|
||||||
|
|
||||||
MIRType opType = retType.toMIRType();
|
MIRType opType = retType.toMIRType();
|
||||||
switch (global->simdOperation()) {
|
switch (global->simdOperation()) {
|
||||||
case AsmJSSimdOperation_add:
|
case AsmJSSimdOperation_add:
|
||||||
@ -4774,6 +4807,7 @@ CheckBinarySimd(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Glob
|
|||||||
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryBitwise::xor_, opType);
|
*def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryBitwise::xor_, opType);
|
||||||
*type = retType;
|
*type = retType;
|
||||||
break;
|
break;
|
||||||
|
case AsmJSSimdOperation_splat:
|
||||||
case AsmJSSimdOperation_select:
|
case AsmJSSimdOperation_select:
|
||||||
MOZ_CRASH("unexpected SIMD binary operation");
|
MOZ_CRASH("unexpected SIMD binary operation");
|
||||||
}
|
}
|
||||||
@ -4824,6 +4858,8 @@ CheckSimdOperationCall(FunctionCompiler &f, ParseNode *call, const ModuleCompile
|
|||||||
{
|
{
|
||||||
JS_ASSERT(global->isSimdOperation());
|
JS_ASSERT(global->isSimdOperation());
|
||||||
switch (global->simdOperation()) {
|
switch (global->simdOperation()) {
|
||||||
|
case AsmJSSimdOperation_splat:
|
||||||
|
return CheckUnarySimd(f, call, global, def, type);
|
||||||
case AsmJSSimdOperation_add:
|
case AsmJSSimdOperation_add:
|
||||||
case AsmJSSimdOperation_sub:
|
case AsmJSSimdOperation_sub:
|
||||||
case AsmJSSimdOperation_mul:
|
case AsmJSSimdOperation_mul:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
load(libdir + "asm.js");
|
load(libdir + "asm.js");
|
||||||
var heap = new ArrayBuffer(4096);
|
var heap = new ArrayBuffer(0x10000);
|
||||||
|
|
||||||
// Set to true to see more JS debugging spew
|
// Set to true to see more JS debugging spew
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
@ -553,6 +553,34 @@ assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32SEL + "function f
|
|||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32SEL + "function f() {var m=i4(0,0xffffffff,0,0xffffffff); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return f4(f4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32SEL + "function f() {var m=i4(0,0xffffffff,0,0xffffffff); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return f4(f4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32SEL + "function f() {var m=i4(0,0,0xffffffff,0xffffffff); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return f4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32SEL + "function f() {var m=i4(0,0,0xffffffff,0xffffffff); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return f4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]);
|
||||||
|
|
||||||
|
// Splat
|
||||||
|
const I32SPLAT = 'var splat=i4.splat;'
|
||||||
|
const F32SPLAT = 'var splat=f4.splat;'
|
||||||
|
|
||||||
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); var p=f4(1.,2.,3.,4.); p=splat(1);} return f");
|
||||||
|
assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat(1, 2)} return f");
|
||||||
|
assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat()} return f");
|
||||||
|
|
||||||
|
assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat(m);} return f");
|
||||||
|
assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat(1.0);} return f");
|
||||||
|
assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + FROUND + "function f() {var m=i4(1,2,3,4); m=splat(f32(1.0));} return f");
|
||||||
|
|
||||||
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32SPLAT + 'function f(){return i4(splat(42));} return f'), this)(), [42, 42, 42, 42]);
|
||||||
|
|
||||||
|
const l33t = Math.fround(13.37);
|
||||||
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(1));} return f'), this)(), [1, 1, 1, 1]);
|
||||||
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(1 >>> 0));} return f'), this)(), [1, 1, 1, 1]);
|
||||||
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(13.37));} return f'), this)(), [l33t, l33t, l33t, l33t]);
|
||||||
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(f32(13.37)));} return f'), this)(), [l33t, l33t, l33t, l33t]);
|
||||||
|
|
||||||
|
var i32view = new Int32Array(heap);
|
||||||
|
var f32view = new Float32Array(heap);
|
||||||
|
i32view[0] = 42;
|
||||||
|
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + I32 + I32SPLAT + 'var i32=new glob.Int32Array(heap); function f(){return i4(splat(i32[0]));} return f'), this, {}, heap)(), [42, 42, 42, 42]);
|
||||||
|
f32view[0] = 42;
|
||||||
|
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + F32SPLAT + 'var f32=new glob.Float32Array(heap); function f(){return f4(splat(f32[0]));} return f'), this, {}, heap)(), [42, 42, 42, 42]);
|
||||||
|
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(f32(1) + f32(2)));} return f'), this, {}, heap)(), [3, 3, 3, 3]);
|
||||||
|
|
||||||
// Dead code
|
// Dead code
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + 'function f(){var x=i4(1,2,3,4); return i4(x); x=i4(5,6,7,8); return i4(x);} return f'), this)(), [1, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + 'function f(){var x=i4(1,2,3,4); return i4(x); x=i4(5,6,7,8); return i4(x);} return f'), this)(), [1, 2, 3, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + 'function f(){var x=i4(1,2,3,4); var c=0; return i4(x); c=x.x|0; return i4(x);} return f'), this)(), [1, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + 'function f(){var x=i4(1,2,3,4); var c=0; return i4(x); c=x.x|0; return i4(x);} return f'), this)(), [1, 2, 3, 4]);
|
||||||
|
Loading…
Reference in New Issue
Block a user