Bug 1155211 - SIMD: Rename lane mutators - with -> replaceLane. r=bbouvier

This commit is contained in:
Florian Merz 2015-06-16 23:10:12 +02:00
parent 1053e1971e
commit 557d2b582a
10 changed files with 297 additions and 213 deletions

View File

@ -5629,6 +5629,41 @@ class CheckSimdVectorScalarArgs
}
};
class CheckSimdReplaceLaneArgs
{
AsmJSSimdType formalSimdType_;
public:
explicit CheckSimdReplaceLaneArgs(AsmJSSimdType t) : formalSimdType_(t) {}
bool operator()(FunctionCompiler& f, ParseNode* arg, unsigned argIndex, Type actualType,
MDefinition** def) const
{
MOZ_ASSERT(argIndex < 3);
uint32_t u32;
switch (argIndex) {
case 0:
// First argument is the vector
if (!(actualType <= Type(formalSimdType_))) {
return f.failf(arg, "%s is not a subtype of %s", actualType.toChars(),
Type(formalSimdType_).toChars());
}
return true;
case 1:
// Second argument is the lane < 4
if (!IsLiteralOrConstInt(f, arg, &u32))
return f.failf(arg, "lane selector should be a constant integer literal");
if (u32 >= SimdTypeToLength(formalSimdType_))
return f.failf(arg, "lane selector should be in bounds");
return true;
case 2:
// Third argument is the scalar
return CheckSimdScalarArgs(formalSimdType_)(f, arg, argIndex, actualType, def);
}
return false;
}
};
} // anonymous namespace
static inline bool
@ -5684,14 +5719,17 @@ CheckSimdBinary<MSimdShift::Operation>(FunctionCompiler& f, ParseNode* call, Asm
}
static bool
CheckSimdWith(FunctionCompiler& f, ParseNode* call, AsmJSSimdType opType, SimdLane lane,
CheckSimdReplaceLane(FunctionCompiler& f, ParseNode* call, AsmJSSimdType opType,
MDefinition** def, Type* type)
{
DefinitionVector defs;
if (!CheckSimdCallArgs(f, call, 2, CheckSimdVectorScalarArgs(opType), &defs))
if (!CheckSimdCallArgs(f, call, 3, CheckSimdReplaceLaneArgs(opType), &defs))
return false;
ParseNode* laneArg = NextNode(CallArgList(call));
uint32_t lane;
JS_ALWAYS_TRUE(IsLiteralInt(f.m(), laneArg, &lane));
*type = opType;
*def = f.insertElementSimd(defs[0], defs[1], lane, type->toMIRType());
*def = f.insertElementSimd(defs[0], defs[2], SimdLane(lane), type->toMIRType());
return true;
}
@ -5950,14 +5988,8 @@ CheckSimdOperationCall(FunctionCompiler& f, ParseNode* call, const ModuleCompile
case AsmJSSimdOperation_xor:
return CheckSimdBinary(f, call, opType, MSimdBinaryBitwise::xor_, def, type);
case AsmJSSimdOperation_withX:
return CheckSimdWith(f, call, opType, SimdLane::LaneX, def, type);
case AsmJSSimdOperation_withY:
return CheckSimdWith(f, call, opType, SimdLane::LaneY, def, type);
case AsmJSSimdOperation_withZ:
return CheckSimdWith(f, call, opType, SimdLane::LaneZ, def, type);
case AsmJSSimdOperation_withW:
return CheckSimdWith(f, call, opType, SimdLane::LaneW, def, type);
case AsmJSSimdOperation_replaceLane:
return CheckSimdReplaceLane(f, call, opType, def, type);
case AsmJSSimdOperation_fromInt32x4:
return CheckSimdCast<MSimdConvert>(f, call, AsmJSSimdType_int32x4, opType, def, type);

View File

@ -614,22 +614,6 @@ template<typename T>
struct Or {
static T apply(T l, T r) { return l | r; }
};
template<typename T>
struct WithX {
static T apply(int32_t lane, T scalar, T x) { return lane == 0 ? scalar : x; }
};
template<typename T>
struct WithY {
static T apply(int32_t lane, T scalar, T x) { return lane == 1 ? scalar : x; }
};
template<typename T>
struct WithZ {
static T apply(int32_t lane, T scalar, T x) { return lane == 2 ? scalar : x; }
};
template<typename T>
struct WithW {
static T apply(int32_t lane, T scalar, T x) { return lane == 3 ? scalar : x; }
};
// For the following three operators, if the value v we're trying to shift is
// such that v << bits can't fit in the int32 range, then we have undefined
// behavior, according to C++11 [expr.shift]p2.
@ -717,26 +701,33 @@ BinaryFunc(JSContext* cx, unsigned argc, Value* vp)
return CoercedBinaryFunc<In, Out, Op, Out>(cx, argc, vp);
}
template<typename V, template<typename T> class OpWith>
template<typename V>
static bool
FuncWith(JSContext* cx, unsigned argc, Value* vp)
ReplaceLane(JSContext* cx, unsigned argc, Value* vp)
{
typedef typename V::Elem Elem;
CallArgs args = CallArgsFromVp(argc, vp);
// Only the first argument is mandatory
if (args.length() < 1 || !IsVectorObject<V>(args[0]))
// Only the first and second arguments are mandatory
if (args.length() < 2 || !IsVectorObject<V>(args[0]))
return ErrorBadArgs(cx);
Elem* vec = TypedObjectMemory<Elem*>(args[0]);
Elem result[V::lanes];
if (!args[1].isInt32())
return ErrorBadArgs(cx);
int32_t lanearg = args[1].toInt32();
if (lanearg < 0 || uint32_t(lanearg) >= V::lanes)
return ErrorBadArgs(cx);
uint32_t lane = uint32_t(lanearg);
Elem value;
if (!V::toType(cx, args.get(1), &value))
if (!V::toType(cx, args.get(2), &value))
return false;
for (unsigned i = 0; i < V::lanes; i++)
result[i] = OpWith<Elem>::apply(i, value, vec[i]);
result[i] = i == lane ? value : vec[i];
return StoreResult<V>(cx, args, result);
}
@ -1170,4 +1161,3 @@ js::simd_int32x4_##Name(JSContext* cx, unsigned argc, Value* vp) \
}
INT32X4_FUNCTION_LIST(DEFINE_SIMD_INT32X4_FUNCTION)
#undef DEFINE_SIMD_INT32X4_FUNCTION

View File

@ -59,15 +59,12 @@
V(store2, (Store<Float32x4, 2>), 3) \
V(store1, (Store<Float32x4, 1>), 3) \
V(sub, (BinaryFunc<Float32x4, Sub, Float32x4>), 2) \
V(withX, (FuncWith<Float32x4, WithX>), 2) \
V(withY, (FuncWith<Float32x4, WithY>), 2) \
V(withZ, (FuncWith<Float32x4, WithZ>), 2) \
V(withW, (FuncWith<Float32x4, WithW>), 2) \
V(xor, (CoercedBinaryFunc<Float32x4, Int32x4, Xor, Float32x4>), 2)
#define FLOAT32X4_TERNARY_FUNCTION_LIST(V) \
V(bitselect, BitSelect<Float32x4>, 3) \
V(clamp, Clamp<Float32x4>, 3) \
V(replaceLane, (ReplaceLane<Float32x4>), 3) \
V(select, Select<Float32x4>, 3)
#define FLOAT32X4_SHUFFLE_FUNCTION_LIST(V) \
@ -111,13 +108,12 @@
V(notEqual, (CompareFunc<Float64x2, NotEqual>), 2) \
V(store, (Store<Float64x2, 2>), 3) \
V(store1, (Store<Float64x2, 1>), 3) \
V(sub, (BinaryFunc<Float64x2, Sub, Float64x2>), 2) \
V(withX, (FuncWith<Float64x2, WithX>), 2) \
V(withY, (FuncWith<Float64x2, WithY>), 2)
V(sub, (BinaryFunc<Float64x2, Sub, Float64x2>), 2)
#define FLOAT64X2_TERNARY_FUNCTION_LIST(V) \
V(bitselect, BitSelect<Float64x2>, 3) \
V(clamp, Clamp<Float64x2>, 3) \
V(replaceLane, (ReplaceLane<Float64x2>), 3) \
V(select, Select<Float64x2>, 3)
#define FLOAT64X2_SHUFFLE_FUNCTION_LIST(V) \
@ -163,14 +159,11 @@
V(store3, (Store<Int32x4, 3>), 3) \
V(store2, (Store<Int32x4, 2>), 3) \
V(store1, (Store<Int32x4, 1>), 3) \
V(withX, (FuncWith<Int32x4, WithX>), 2) \
V(withY, (FuncWith<Int32x4, WithY>), 2) \
V(withZ, (FuncWith<Int32x4, WithZ>), 2) \
V(withW, (FuncWith<Int32x4, WithW>), 2) \
V(xor, (BinaryFunc<Int32x4, Xor, Int32x4>), 2)
#define INT32X4_TERNARY_FUNCTION_LIST(V) \
V(bitselect, BitSelect<Int32x4>, 3) \
V(replaceLane, (ReplaceLane<Int32x4>), 3) \
V(select, Select<Int32x4>, 3)
#define INT32X4_QUARTERNARY_FUNCTION_LIST(V) \
@ -226,16 +219,11 @@
_(notEqual) \
_(greaterThan) \
_(greaterThanOrEqual)
#define WITH_COMMONX4_SIMD_OP(_) \
_(withX) \
_(withY) \
_(withZ) \
_(withW)
// TODO: remove when all SIMD calls are inlined (bug 1112155)
#define ION_COMMONX4_SIMD_OP(_) \
ARITH_COMMONX4_SIMD_OP(_) \
BITWISE_COMMONX4_SIMD_OP(_) \
WITH_COMMONX4_SIMD_OP(_) \
_(replaceLane) \
_(bitselect) \
_(select) \
_(splat) \

View File

@ -0,0 +1,102 @@
load(libdir + 'simd.js');
setJitCompilerOption("ion.warmup.trigger", 50);
function f() {
var f4 = SIMD.float32x4(1, 2, 3, 4);
var i4 = SIMD.int32x4(1, 2, 3, 4);
for (var i = 0; i < 150; i++) {
assertEqX4(SIMD.int32x4.replaceLane(i4, 0, 42), [42, 2, 3, 4]);
assertEqX4(SIMD.int32x4.replaceLane(i4, 1, 42), [1, 42, 3, 4]);
assertEqX4(SIMD.int32x4.replaceLane(i4, 2, 42), [1, 2, 42, 4]);
assertEqX4(SIMD.int32x4.replaceLane(i4, 3, 42), [1, 2, 3, 42]);
assertEqX4(SIMD.float32x4.replaceLane(f4, 0, 42), [42, 2, 3, 4]);
assertEqX4(SIMD.float32x4.replaceLane(f4, 1, 42), [1, 42, 3, 4]);
assertEqX4(SIMD.float32x4.replaceLane(f4, 2, 42), [1, 2, 42, 4]);
assertEqX4(SIMD.float32x4.replaceLane(f4, 3, 42), [1, 2, 3, 42]);
}
}
f();
function e() {
var f4 = SIMD.float32x4(1, 2, 3, 4);
var i4 = SIMD.int32x4(1, 2, 3, 4);
for (let i = 0; i < 150; i++) {
let caught = false;
try {
let x = SIMD.int32x4.replaceLane(i < 149 ? i4 : f4, 0, 42);
} catch(e) {
assertEq(e instanceof TypeError, true);
assertEq(i, 149);
caught = true;
}
assertEq(i < 149 || caught, true);
}
for (let i = 0; i < 150; i++) {
let caught = false;
try {
let x = SIMD.int32x4.replaceLane(i4, i < 149 ? 0 : 4, 42);
} catch(e) {
assertEq(e instanceof TypeError, true);
assertEq(i, 149);
caught = true;
}
assertEq(i < 149 || caught, true);
}
for (let i = 0; i < 150; i++) {
let caught = false;
try {
let x = SIMD.int32x4.replaceLane(i4, i < 149 ? 0 : 1.1, 42);
} catch(e) {
assertEq(e instanceof TypeError, true);
assertEq(i, 149);
caught = true;
}
assertEq(i < 149 || caught, true);
}
for (let i = 0; i < 150; i++) {
let caught = false;
try {
let x = SIMD.float32x4.replaceLane(i < 149 ? f4 : i4, 0, 42);
} catch(e) {
assertEq(e instanceof TypeError, true);
assertEq(i, 149);
caught = true;
}
assertEq(i < 149 || caught, true);
}
for (let i = 0; i < 150; i++) {
let caught = false;
try {
let x = SIMD.float32x4.replaceLane(f4, i < 149 ? 0 : 4, 42);
} catch(e) {
assertEq(e instanceof TypeError, true);
assertEq(i, 149);
caught = true;
}
assertEq(i < 149 || caught, true);
}
for (let i = 0; i < 150; i++) {
let caught = false;
try {
let x = SIMD.float32x4.replaceLane(f4, i < 149 ? 0 : 1.1, 42);
} catch(e) {
assertEq(e instanceof TypeError, true);
assertEq(i, 149);
caught = true;
}
assertEq(i < 149 || caught, true);
}
}
e();

View File

@ -1,23 +0,0 @@
load(libdir + 'simd.js');
setJitCompilerOption("ion.warmup.trigger", 50);
function f() {
var f4 = SIMD.float32x4(1, 2, 3, 4);
var i4 = SIMD.int32x4(1, 2, 3, 4);
for (var i = 0; i < 150; i++) {
assertEqX4(SIMD.int32x4.withX(i4, 42), [42, 2, 3, 4]);
assertEqX4(SIMD.int32x4.withY(i4, 42), [1, 42, 3, 4]);
assertEqX4(SIMD.int32x4.withZ(i4, 42), [1, 2, 42, 4]);
assertEqX4(SIMD.int32x4.withW(i4, 42), [1, 2, 3, 42]);
assertEqX4(SIMD.float32x4.withX(f4, 42), [42, 2, 3, 4]);
assertEqX4(SIMD.float32x4.withY(f4, 42), [1, 42, 3, 4]);
assertEqX4(SIMD.float32x4.withZ(f4, 42), [1, 2, 42, 4]);
assertEqX4(SIMD.float32x4.withW(f4, 42), [1, 2, 3, 42]);
}
}
f();

View File

@ -609,37 +609,34 @@ CheckF4(F32MAXNUM, 'var x=f4(0,0,-0,-0); var y=f4(0,-0,0,-0); x=max(x,y)', [0,0,
CheckF4(F32MAXNUM + FROUND + 'var NaN = glob.NaN;', 'var x=f4(0,0,0,0); var y=f4(0,0,0,0); var n=f32(0); n=f32(NaN); x=f4(n,0.,n,0.); y=f4(n,n,0.,0.); x=max(x,y)', [NaN, 0, 0, 0]);
// With
const WXF = 'var w = f4.withX;';
const WYF = 'var w = f4.withY;';
const WZF = 'var w = f4.withZ;';
const WWF = 'var w = f4.withW;';
const RLF = 'var r = f4.replaceLane;';
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + "function f() {var x = f4(1,2,3,4); x = w(x, 1);} return f");
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + "function f() {var x = f4(1,2,3,4); x = w(x, x);} return f");
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + FROUND + "function f() {var x = f4(1,2,3,4); x = w(1, f32(1));} return f");
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + FROUND + "function f() {var x = f4(1,2,3,4); x = w(1., f32(1));} return f");
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + FROUND + "function f() {var x = f4(1,2,3,4); x = w(f32(1), f32(1));} return f");
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + WXF + FROUND + "function f() {var x = f4(1,2,3,4); var y = i4(1,2,3,4); x = w(y, f32(1));} return f");
assertAsmTypeFail('glob', USE_ASM + F32 + RLF + "function f() {var x = f4(1,2,3,4); x = r(x, 0, 1);} return f");
assertAsmTypeFail('glob', USE_ASM + F32 + RLF + "function f() {var x = f4(1,2,3,4); x = r(x, 0, x);} return f");
assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(x, 4, f32(1));} return f");
assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(x, f32(0), f32(1));} return f");
assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(1, 0, f32(1));} return f");
assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(1, 0., f32(1));} return f");
assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); x = r(f32(1), 0, f32(1));} return f");
assertAsmTypeFail('glob', USE_ASM + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); var l = 0; x = r(x, l, f32(1));} return f");
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + RLF + FROUND + "function f() {var x = f4(1,2,3,4); var y = i4(1,2,3,4); x = r(y, 0, f32(1));} return f");
CheckF4(WXF + FROUND, 'var x = f4(1,2,3,4); x = w(x, f32(13.37));', [Math.fround(13.37), 2, 3, 4]);
CheckF4(WYF + FROUND, 'var x = f4(1,2,3,4); x = w(x, f32(13.37));', [1, Math.fround(13.37), 3, 4]);
CheckF4(WZF + FROUND, 'var x = f4(1,2,3,4); x = w(x, f32(13.37));', [1, 2, Math.fround(13.37), 4]);
CheckF4(WWF + FROUND, 'var x = f4(1,2,3,4); x = w(x, f32(13.37));', [1, 2, 3, Math.fround(13.37)]);
CheckF4(WWF + FROUND, 'var x = f4(1,2,3,4); x = w(x, f32(13.37) + f32(6.63));', [1, 2, 3, Math.fround(Math.fround(13.37) + Math.fround(6.63))]);
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 0, f32(13.37));', [Math.fround(13.37), 2, 3, 4]);
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 1, f32(13.37));', [1, Math.fround(13.37), 3, 4]);
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 2, f32(13.37));', [1, 2, Math.fround(13.37), 4]);
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 3, f32(13.37));', [1, 2, 3, Math.fround(13.37)]);
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 3, f32(13.37) + f32(6.63));', [1, 2, 3, Math.fround(Math.fround(13.37) + Math.fround(6.63))]);
CheckF4(WXF + FROUND, 'var x = f4(1,2,3,4); x = w(x, 13.37);', [Math.fround(13.37), 2, 3, 4]);
CheckF4(WYF + FROUND, 'var x = f4(1,2,3,4); x = w(x, 13.37);', [1, Math.fround(13.37), 3, 4]);
CheckF4(WZF + FROUND, 'var x = f4(1,2,3,4); x = w(x, 13.37);', [1, 2, Math.fround(13.37), 4]);
CheckF4(WWF + FROUND, 'var x = f4(1,2,3,4); x = w(x, 13.37);', [1, 2, 3, Math.fround(13.37)]);
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 0, 13.37);', [Math.fround(13.37), 2, 3, 4]);
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 1, 13.37);', [1, Math.fround(13.37), 3, 4]);
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 2, 13.37);', [1, 2, Math.fround(13.37), 4]);
CheckF4(RLF + FROUND, 'var x = f4(1,2,3,4); x = r(x, 3, 13.37);', [1, 2, 3, Math.fround(13.37)]);
const WXI = 'var w = i4.withX;';
const WYI = 'var w = i4.withY;';
const WZI = 'var w = i4.withZ;';
const WWI = 'var w = i4.withW;';
CheckI4(WXI, 'var x = i4(1,2,3,4); x = w(x, 42);', [42, 2, 3, 4]);
CheckI4(WYI, 'var x = i4(1,2,3,4); x = w(x, 42);', [1, 42, 3, 4]);
CheckI4(WZI, 'var x = i4(1,2,3,4); x = w(x, 42);', [1, 2, 42, 4]);
CheckI4(WWI, 'var x = i4(1,2,3,4); x = w(x, 42);', [1, 2, 3, 42]);
const RLI = 'var r = i4.replaceLane;';
CheckI4(RLI, 'var x = i4(1,2,3,4); x = r(x, 0, 42);', [42, 2, 3, 4]);
CheckI4(RLI, 'var x = i4(1,2,3,4); x = r(x, 1, 42);', [1, 42, 3, 4]);
CheckI4(RLI, 'var x = i4(1,2,3,4); x = r(x, 2, 42);', [1, 2, 42, 4]);
CheckI4(RLI, 'var x = i4(1,2,3,4); x = r(x, 3, 42);', [1, 2, 3, 42]);
// Comparisons
// True yields all bits set to 1 (i.e as an int32, 0xFFFFFFFF === -1), false
@ -1319,4 +1316,3 @@ asmLink(asmCompile('glob', 'ffi', code), this, assertEqFFI)();
print('Error:', e)
throw e;
}

View File

@ -817,7 +817,7 @@ class IonBuilder
MSimdBinaryComp::Operation op, SimdTypeDescr::Type compType);
InliningStatus inlineUnarySimd(CallInfo& callInfo, JSNative native,
MSimdUnaryArith::Operation op, SimdTypeDescr::Type type);
InliningStatus inlineSimdWith(CallInfo& callInfo, JSNative native, SimdLane lane,
InliningStatus inlineSimdReplaceLane(CallInfo& callInfo, JSNative native,
SimdTypeDescr::Type type);
InliningStatus inlineSimdSplat(CallInfo& callInfo, JSNative native, SimdTypeDescr::Type type);
InliningStatus inlineSimdShuffle(CallInfo& callInfo, JSNative native, SimdTypeDescr::Type type,

View File

@ -313,17 +313,10 @@ IonBuilder::inlineNativeCall(CallInfo& callInfo, JSFunction* target)
COMP_COMMONX4_TO_INT32X4_SIMD_OP(INLINE_SIMD_COMPARISON_)
#undef INLINE_SIMD_COMPARISON_
#define INLINE_SIMD_SETTER_(LANE) \
if (native == js::simd_int32x4_with##LANE) \
return inlineSimdWith(callInfo, native, SimdLane::Lane##LANE, SimdTypeDescr::Int32x4); \
if (native == js::simd_float32x4_with##LANE) \
return inlineSimdWith(callInfo, native, SimdLane::Lane##LANE, SimdTypeDescr::Float32x4);
INLINE_SIMD_SETTER_(X)
INLINE_SIMD_SETTER_(Y)
INLINE_SIMD_SETTER_(Z)
INLINE_SIMD_SETTER_(W)
#undef INLINE_SIMD_SETTER_
if (native == js::simd_int32x4_replaceLane)
return inlineSimdReplaceLane(callInfo, native, SimdTypeDescr::Int32x4);
if (native == js::simd_float32x4_replaceLane)
return inlineSimdReplaceLane(callInfo, native, SimdTypeDescr::Float32x4);
if (native == js::simd_int32x4_not)
return inlineUnarySimd(callInfo, native, MSimdUnaryArith::not_, SimdTypeDescr::Int32x4);
@ -3216,17 +3209,22 @@ IonBuilder::inlineSimdSplat(CallInfo& callInfo, JSNative native, SimdTypeDescr::
}
IonBuilder::InliningStatus
IonBuilder::inlineSimdWith(CallInfo& callInfo, JSNative native, SimdLane lane,
SimdTypeDescr::Type type)
IonBuilder::inlineSimdReplaceLane(CallInfo& callInfo, JSNative native, SimdTypeDescr::Type type)
{
InlineTypedObject* templateObj = nullptr;
if (!checkInlineSimd(callInfo, native, type, 2, &templateObj))
if (!checkInlineSimd(callInfo, native, type, 3, &templateObj))
return InliningStatus_NotInlined;
MDefinition* arg = callInfo.getArg(1);
if (!arg->isConstantValue() || arg->type() != MIRType_Int32)
return InliningStatus_NotInlined;
int32_t lane = arg->constantValue().toInt32();
if (lane < 0 || lane >= 4)
return InliningStatus_NotInlined;
// See comment in inlineBinarySimd
MIRType mirType = SimdTypeDescrToMIRType(type);
MSimdInsertElement* ins = MSimdInsertElement::New(alloc(), callInfo.getArg(0),
callInfo.getArg(1), mirType, lane);
callInfo.getArg(2), mirType, SimdLane(lane));
return boxSimd(callInfo, ins, templateObj);
}

View File

@ -0,0 +1,94 @@
// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
var float32x4 = SIMD.float32x4;
var int32x4 = SIMD.int32x4;
var float64x2 = SIMD.float64x2;
function replaceLane0(arr, x) {
if (arr.length == 2)
return [x, arr[1]];
return [x, arr[1], arr[2], arr[3]];
}
function replaceLane1(arr, x) {
if (arr.length == 2)
return [arr[0], x];
return [arr[0], x, arr[2], arr[3]];
}
function replaceLane2(arr, x) {
return [arr[0], arr[1], x, arr[3]];
}
function replaceLane3(arr, x) {
return [arr[0], arr[1], arr[2], x];
}
function testReplaceLane(vec, scalar, simdFunc, func) {
var varr = simdToArray(vec);
var observed = simdToArray(simdFunc(vec, scalar));
var expected = func(varr, scalar);
for (var i = 0; i < observed.length; i++)
assertEq(observed[i], expected[i]);
}
function test() {
function testType(type, inputs) {
var length = simdToArray(inputs[0][0]).length;
for (var [vec, s] of inputs) {
testReplaceLane(vec, s, (x,y) => SIMD[type].replaceLane(x, 0, y), replaceLane0);
testReplaceLane(vec, s, (x,y) => SIMD[type].replaceLane(x, 1, y), replaceLane1);
if (length <= 2)
continue;
testReplaceLane(vec, s, (x,y) => SIMD[type].replaceLane(x, 2, y), replaceLane2);
testReplaceLane(vec, s, (x,y) => SIMD[type].replaceLane(x, 3, y), replaceLane3);
}
}
function TestError(){};
var good = {valueOf: () => 42};
var bad = {valueOf: () => {throw new TestError(); }};
var float32x4inputs = [
[float32x4(1, 2, 3, 4), 5],
[float32x4(1.87, 2.08, 3.84, 4.17), Math.fround(13.37)],
[float32x4(NaN, -0, Infinity, -Infinity), 0]
];
testType('float32x4', float32x4inputs);
var v = float32x4inputs[1][0];
assertEqX4(float32x4.replaceLane(v, 0), replaceLane0(simdToArray(v), NaN));
assertEqX4(float32x4.replaceLane(v, 0, good), replaceLane0(simdToArray(v), good | 0));
assertThrowsInstanceOf(() => float32x4.replaceLane(v, 0, bad), TestError);
assertThrowsInstanceOf(() => float32x4.replaceLane(v, 4, good), TypeError);
assertThrowsInstanceOf(() => float32x4.replaceLane(v, 1.1, good), TypeError);
var float64x2inputs = [
[float64x2(1, 2), 5],
[float64x2(1.87, 2.08), Math.fround(13.37)],
[float64x2(NaN, -0), 0]
];
testType('float64x2', float64x2inputs);
var v = float64x2inputs[1][0];
assertEqX4(float64x2.replaceLane(v, 0), replaceLane0(simdToArray(v), NaN));
assertEqX4(float64x2.replaceLane(v, 0, good), replaceLane0(simdToArray(v), good | 0));
assertThrowsInstanceOf(() => float64x2.replaceLane(v, 0, bad), TestError);
assertThrowsInstanceOf(() => float64x2.replaceLane(v, 2, good), TypeError);
assertThrowsInstanceOf(() => float64x2.replaceLane(v, 1.1, good), TypeError);
var int32x4inputs = [
[int32x4(1, 2, 3, 4), 5],
[int32x4(INT32_MIN, INT32_MAX, 3, 4), INT32_MIN],
];
testType('int32x4', int32x4inputs);
var v = int32x4inputs[1][0];
assertEqX4(int32x4.replaceLane(v, 0), replaceLane0(simdToArray(v), 0));
assertEqX4(int32x4.replaceLane(v, 0, good), replaceLane0(simdToArray(v), good | 0));
assertThrowsInstanceOf(() => int32x4.replaceLane(v, 0, bad), TestError);
assertThrowsInstanceOf(() => int32x4.replaceLane(v, 4, good), TypeError);
assertThrowsInstanceOf(() => int32x4.replaceLane(v, 1.1, good), TypeError);
if (typeof reportCompare === "function")
reportCompare(true, true);
}
test();

View File

@ -1,93 +0,0 @@
// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
var BUGNUMBER = 946042;
var float32x4 = SIMD.float32x4;
var int32x4 = SIMD.int32x4;
var float64x2 = SIMD.float64x2;
var summary = 'with{X,Y,Z,W}';
function withX(arr, x) {
if (arr.length == 2)
return [x, arr[1]];
return [x, arr[1], arr[2], arr[3]];
}
function withY(arr, x) {
if (arr.length == 2)
return [arr[0], x];
return [arr[0], x, arr[2], arr[3]];
}
function withZ(arr, x) {
return [arr[0], arr[1], x, arr[3]];
}
function withW(arr, x) {
return [arr[0], arr[1], arr[2], x];
}
function testWith(vec, scalar, simdFunc, func) {
var varr = simdToArray(vec);
var observed = simdToArray(simdFunc(vec, scalar));
var expected = func(varr, scalar);
for (var i = 0; i < observed.length; i++)
assertEq(observed[i], expected[i]);
}
function test() {
print(BUGNUMBER + ": " + summary);
function testType(type, inputs) {
var length = simdToArray(inputs[0][0]).length;
for (var [vec, s] of inputs) {
testWith(vec, s, SIMD[type].withX, withX);
testWith(vec, s, SIMD[type].withY, withY);
if (length <= 2)
continue;
testWith(vec, s, SIMD[type].withZ, withZ);
testWith(vec, s, SIMD[type].withW, withW);
}
}
function TestError(){};
var good = {valueOf: () => 42};
var bad = {valueOf: () => {throw new TestError(); }};
var float32x4inputs = [
[float32x4(1, 2, 3, 4), 5],
[float32x4(1.87, 2.08, 3.84, 4.17), Math.fround(13.37)],
[float32x4(NaN, -0, Infinity, -Infinity), 0]
];
testType('float32x4', float32x4inputs);
var v = float32x4inputs[1][0];
assertEqX4(float32x4.withX(v), withX(simdToArray(v), NaN));
assertEqX4(float32x4.withX(v, good), withX(simdToArray(v), good | 0));
assertThrowsInstanceOf(() => float32x4.withX(v, bad), TestError);
var float64x2inputs = [
[float64x2(1, 2), 5],
[float64x2(1.87, 2.08), Math.fround(13.37)],
[float64x2(NaN, -0), 0]
];
testType('float64x2', float64x2inputs);
var v = float64x2inputs[1][0];
assertEqX4(float64x2.withX(v), withX(simdToArray(v), NaN));
assertEqX4(float64x2.withX(v, good), withX(simdToArray(v), good | 0));
assertThrowsInstanceOf(() => float64x2.withX(v, bad), TestError);
var int32x4inputs = [
[int32x4(1, 2, 3, 4), 5],
[int32x4(INT32_MIN, INT32_MAX, 3, 4), INT32_MIN],
];
testType('int32x4', int32x4inputs);
var v = int32x4inputs[1][0];
assertEqX4(int32x4.withX(v), withX(simdToArray(v), 0));
assertEqX4(int32x4.withX(v, good), withX(simdToArray(v), good | 0));
assertThrowsInstanceOf(() => int32x4.withX(v, bad), TestError);
if (typeof reportCompare === "function")
reportCompare(true, true);
}
test();