зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1244254 - Check SIMD arguments in IonBuilder. r=nbp
When inlining SIMD operations that take a SIMD type as an argument, explicitly insert a type checking MSimdUnbox using the new unboxSimd() function. This requires passing down the SimdType argument from inlineSimd(). - Remove SimdSign and other arguments that can be inferred from the SimdType. - Add a new function inlineSimdShift() to handle the shift operations where the second argument is a scalar. - Add a GetSimdLanes() function to SIMD.h which counts the number of lanes in a SIMD type. --HG-- extra : commitid : 8GFBUY1ifsW
This commit is contained in:
Родитель
5cf4a711a8
Коммит
8299c348d0
|
@ -872,6 +872,37 @@ GetBooleanSimdType(SimdType t)
|
|||
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Bad SIMD type");
|
||||
}
|
||||
|
||||
// Get the number of lanes in a SIMD type.
|
||||
inline unsigned
|
||||
GetSimdLanes(SimdType t)
|
||||
{
|
||||
switch(t) {
|
||||
case SimdType::Int8x16:
|
||||
case SimdType::Uint8x16:
|
||||
case SimdType::Bool8x16:
|
||||
return 16;
|
||||
|
||||
case SimdType::Int16x8:
|
||||
case SimdType::Uint16x8:
|
||||
case SimdType::Bool16x8:
|
||||
return 8;
|
||||
|
||||
case SimdType::Int32x4:
|
||||
case SimdType::Uint32x4:
|
||||
case SimdType::Float32x4:
|
||||
case SimdType::Bool32x4:
|
||||
return 4;
|
||||
|
||||
case SimdType::Float64x2:
|
||||
case SimdType::Bool64x2:
|
||||
return 2;
|
||||
|
||||
case SimdType::Count:
|
||||
break;
|
||||
}
|
||||
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Bad SIMD type");
|
||||
}
|
||||
|
||||
// Complete set of SIMD operations.
|
||||
//
|
||||
// No SIMD types implement all of these operations.
|
||||
|
|
|
@ -868,32 +868,32 @@ class IonBuilder
|
|||
|
||||
template <typename T>
|
||||
InliningStatus inlineSimdBinary(CallInfo& callInfo, JSNative native,
|
||||
typename T::Operation op, MIRType mirType);
|
||||
typename T::Operation op, SimdType type);
|
||||
InliningStatus inlineSimdShift(CallInfo& callInfo, JSNative native, MSimdShift::Operation op,
|
||||
SimdType type);
|
||||
InliningStatus inlineSimdComp(CallInfo& callInfo, JSNative native,
|
||||
MSimdBinaryComp::Operation op,
|
||||
MIRType compType, SimdSign sign);
|
||||
MSimdBinaryComp::Operation op, SimdType type);
|
||||
InliningStatus inlineSimdUnary(CallInfo& callInfo, JSNative native,
|
||||
MSimdUnaryArith::Operation op, MIRType mirType);
|
||||
InliningStatus inlineSimdExtractLane(CallInfo& callInfo, JSNative native,
|
||||
MIRType vecType, SimdSign sign);
|
||||
InliningStatus inlineSimdReplaceLane(CallInfo& callInfo, JSNative native, MIRType mirType);
|
||||
InliningStatus inlineSimdSplat(CallInfo& callInfo, JSNative native, MIRType mirType);
|
||||
InliningStatus inlineSimdShuffle(CallInfo& callInfo, JSNative native, MIRType type,
|
||||
unsigned numVectors, unsigned numLanes);
|
||||
MSimdUnaryArith::Operation op, SimdType type);
|
||||
InliningStatus inlineSimdExtractLane(CallInfo& callInfo, JSNative native, SimdType type);
|
||||
InliningStatus inlineSimdReplaceLane(CallInfo& callInfo, JSNative native, SimdType type);
|
||||
InliningStatus inlineSimdSplat(CallInfo& callInfo, JSNative native, SimdType type);
|
||||
InliningStatus inlineSimdShuffle(CallInfo& callInfo, JSNative native, SimdType type,
|
||||
unsigned numVectors);
|
||||
InliningStatus inlineSimdCheck(CallInfo& callInfo, JSNative native, SimdType type);
|
||||
InliningStatus inlineSimdConvert(CallInfo& callInfo, JSNative native, bool isCast,
|
||||
MIRType from, MIRType to,
|
||||
SimdSign sign = SimdSign::NotApplicable);
|
||||
InliningStatus inlineSimdSelect(CallInfo& callInfo, JSNative native, MIRType type);
|
||||
SimdType from, SimdType to);
|
||||
InliningStatus inlineSimdSelect(CallInfo& callInfo, JSNative native, SimdType type);
|
||||
|
||||
bool prepareForSimdLoadStore(CallInfo& callInfo, Scalar::Type simdType, MInstruction** elements,
|
||||
MDefinition** index, Scalar::Type* arrayType);
|
||||
InliningStatus inlineSimdLoad(CallInfo& callInfo, JSNative native, MIRType type,
|
||||
InliningStatus inlineSimdLoad(CallInfo& callInfo, JSNative native, SimdType type,
|
||||
unsigned numElems);
|
||||
InliningStatus inlineSimdStore(CallInfo& callInfo, JSNative native, MIRType type,
|
||||
InliningStatus inlineSimdStore(CallInfo& callInfo, JSNative native, SimdType type,
|
||||
unsigned numElems);
|
||||
|
||||
InliningStatus inlineSimdAnyAllTrue(CallInfo& callInfo, bool IsAllTrue, JSNative native);
|
||||
InliningStatus inlineSimdAnyAllTrue(CallInfo& callInfo, bool IsAllTrue, JSNative native,
|
||||
SimdType type);
|
||||
|
||||
// Utility intrinsics.
|
||||
InliningStatus inlineIsCallable(CallInfo& callInfo);
|
||||
|
|
|
@ -3074,9 +3074,6 @@ IonBuilder::inlineSimd(CallInfo& callInfo, JSFunction* target, SimdType type)
|
|||
MOZ_ASSERT(jitInfo && jitInfo->type() == JSJitInfo::InlinableNative);
|
||||
SimdOperation simdOp = SimdOperation(jitInfo->nativeOp);
|
||||
|
||||
MIRType simdType = SimdTypeToMIRType(type);
|
||||
SimdSign sign = GetSimdSign(type);
|
||||
|
||||
switch(simdOp) {
|
||||
case SimdOperation::Constructor:
|
||||
// SIMD constructor calls are handled via inlineNonFunctionCall(), so
|
||||
|
@ -3086,148 +3083,140 @@ IonBuilder::inlineSimd(CallInfo& callInfo, JSFunction* target, SimdType type)
|
|||
case SimdOperation::Fn_check:
|
||||
return inlineSimdCheck(callInfo, native, type);
|
||||
case SimdOperation::Fn_splat:
|
||||
return inlineSimdSplat(callInfo, native, simdType);
|
||||
return inlineSimdSplat(callInfo, native, type);
|
||||
case SimdOperation::Fn_extractLane:
|
||||
return inlineSimdExtractLane(callInfo, native, simdType, sign);
|
||||
return inlineSimdExtractLane(callInfo, native, type);
|
||||
case SimdOperation::Fn_replaceLane:
|
||||
return inlineSimdReplaceLane(callInfo, native, simdType);
|
||||
return inlineSimdReplaceLane(callInfo, native, type);
|
||||
case SimdOperation::Fn_select:
|
||||
return inlineSimdSelect(callInfo, native, simdType);
|
||||
return inlineSimdSelect(callInfo, native, type);
|
||||
case SimdOperation::Fn_swizzle:
|
||||
return inlineSimdShuffle(callInfo, native, simdType, 1, SimdTypeToLength(simdType));
|
||||
return inlineSimdShuffle(callInfo, native, type, 1);
|
||||
case SimdOperation::Fn_shuffle:
|
||||
return inlineSimdShuffle(callInfo, native, simdType, 2, SimdTypeToLength(simdType));
|
||||
return inlineSimdShuffle(callInfo, native, type, 2);
|
||||
|
||||
// Unary arithmetic.
|
||||
case SimdOperation::Fn_abs:
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::abs, simdType);
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::abs, type);
|
||||
case SimdOperation::Fn_neg:
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::neg, simdType);
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::neg, type);
|
||||
case SimdOperation::Fn_not:
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::not_, simdType);
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::not_, type);
|
||||
case SimdOperation::Fn_reciprocalApproximation:
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::reciprocalApproximation,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_reciprocalSqrtApproximation:
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::reciprocalSqrtApproximation,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_sqrt:
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::sqrt, simdType);
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::sqrt, type);
|
||||
|
||||
// Binary arithmetic.
|
||||
case SimdOperation::Fn_add:
|
||||
return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_add,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_sub:
|
||||
return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_sub,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_mul:
|
||||
return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_mul,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_div:
|
||||
return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_div,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_max:
|
||||
return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_max,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_min:
|
||||
return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_min,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_maxNum:
|
||||
return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_maxNum,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_minNum:
|
||||
return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_minNum,
|
||||
simdType);
|
||||
type);
|
||||
|
||||
// Binary bitwise.
|
||||
case SimdOperation::Fn_and:
|
||||
return inlineSimdBinary<MSimdBinaryBitwise>(callInfo, native, MSimdBinaryBitwise::and_,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_or:
|
||||
return inlineSimdBinary<MSimdBinaryBitwise>(callInfo, native, MSimdBinaryBitwise::or_,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_xor:
|
||||
return inlineSimdBinary<MSimdBinaryBitwise>(callInfo, native, MSimdBinaryBitwise::xor_,
|
||||
simdType);
|
||||
type);
|
||||
|
||||
// Shifts.
|
||||
case SimdOperation::Fn_shiftLeftByScalar:
|
||||
return inlineSimdBinary<MSimdShift>(callInfo, native, MSimdShift::lsh, simdType);
|
||||
return inlineSimdShift(callInfo, native, MSimdShift::lsh, type);
|
||||
case SimdOperation::Fn_shiftRightByScalar:
|
||||
return inlineSimdBinary<MSimdShift>(callInfo, native, MSimdShift::rshForSign(sign),
|
||||
simdType);
|
||||
return inlineSimdShift(callInfo, native, MSimdShift::rshForSign(GetSimdSign(type)), type);
|
||||
case SimdOperation::Fn_shiftRightArithmeticByScalar:
|
||||
return inlineSimdBinary<MSimdShift>(callInfo, native, MSimdShift::rsh, simdType);
|
||||
return inlineSimdShift(callInfo, native, MSimdShift::rsh, type);
|
||||
case SimdOperation::Fn_shiftRightLogicalByScalar:
|
||||
return inlineSimdBinary<MSimdShift>(callInfo, native, MSimdShift::ursh, simdType);
|
||||
return inlineSimdShift(callInfo, native, MSimdShift::ursh, type);
|
||||
|
||||
// Boolean unary.
|
||||
case SimdOperation::Fn_allTrue:
|
||||
return inlineSimdAnyAllTrue(callInfo, /* IsAllTrue= */true, native);
|
||||
return inlineSimdAnyAllTrue(callInfo, /* IsAllTrue= */true, native, type);
|
||||
case SimdOperation::Fn_anyTrue:
|
||||
return inlineSimdAnyAllTrue(callInfo, /* IsAllTrue= */false, native);
|
||||
return inlineSimdAnyAllTrue(callInfo, /* IsAllTrue= */false, native, type);
|
||||
|
||||
// Comparisons.
|
||||
case SimdOperation::Fn_lessThan:
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::lessThan,
|
||||
simdType, sign);
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::lessThan, type);
|
||||
case SimdOperation::Fn_lessThanOrEqual:
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::lessThanOrEqual,
|
||||
simdType, sign);
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::lessThanOrEqual, type);
|
||||
case SimdOperation::Fn_equal:
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::equal,
|
||||
simdType, sign);
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::equal, type);
|
||||
case SimdOperation::Fn_notEqual:
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::notEqual,
|
||||
simdType, sign);
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::notEqual, type);
|
||||
case SimdOperation::Fn_greaterThan:
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::greaterThan,
|
||||
simdType, sign);
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::greaterThan, type);
|
||||
case SimdOperation::Fn_greaterThanOrEqual:
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::greaterThanOrEqual,
|
||||
simdType, sign);
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::greaterThanOrEqual, type);
|
||||
|
||||
// Int <-> Float conversions.
|
||||
case SimdOperation::Fn_fromInt32x4:
|
||||
return inlineSimdConvert(callInfo, native, false, MIRType_Int32x4,
|
||||
simdType, SimdSign::Signed);
|
||||
return inlineSimdConvert(callInfo, native, false, SimdType::Int32x4, type);
|
||||
case SimdOperation::Fn_fromUint32x4:
|
||||
return inlineSimdConvert(callInfo, native, false, MIRType_Int32x4,
|
||||
simdType, SimdSign::Unsigned);
|
||||
return inlineSimdConvert(callInfo, native, false, SimdType::Uint32x4, type);
|
||||
case SimdOperation::Fn_fromFloat32x4:
|
||||
return inlineSimdConvert(callInfo, native, false, MIRType_Float32x4, simdType, sign);
|
||||
return inlineSimdConvert(callInfo, native, false, SimdType::Float32x4, type);
|
||||
|
||||
// Load/store.
|
||||
case SimdOperation::Fn_load:
|
||||
return inlineSimdLoad(callInfo, native, simdType, SimdTypeToLength(simdType));
|
||||
return inlineSimdLoad(callInfo, native, type, GetSimdLanes(type));
|
||||
case SimdOperation::Fn_load1:
|
||||
return inlineSimdLoad(callInfo, native, simdType, 1);
|
||||
return inlineSimdLoad(callInfo, native, type, 1);
|
||||
case SimdOperation::Fn_load2:
|
||||
return inlineSimdLoad(callInfo, native, simdType, 2);
|
||||
return inlineSimdLoad(callInfo, native, type, 2);
|
||||
case SimdOperation::Fn_load3:
|
||||
return inlineSimdLoad(callInfo, native, simdType, 3);
|
||||
return inlineSimdLoad(callInfo, native, type, 3);
|
||||
case SimdOperation::Fn_store:
|
||||
return inlineSimdStore(callInfo, native, simdType, SimdTypeToLength(simdType));
|
||||
return inlineSimdStore(callInfo, native, type, GetSimdLanes(type));
|
||||
case SimdOperation::Fn_store1:
|
||||
return inlineSimdStore(callInfo, native, simdType, 1);
|
||||
return inlineSimdStore(callInfo, native, type, 1);
|
||||
case SimdOperation::Fn_store2:
|
||||
return inlineSimdStore(callInfo, native, simdType, 2);
|
||||
return inlineSimdStore(callInfo, native, type, 2);
|
||||
case SimdOperation::Fn_store3:
|
||||
return inlineSimdStore(callInfo, native, simdType, 3);
|
||||
return inlineSimdStore(callInfo, native, type, 3);
|
||||
|
||||
// Bitcasts. One for each type with a memory representation.
|
||||
case SimdOperation::Fn_fromInt8x16Bits:
|
||||
case SimdOperation::Fn_fromInt16x8Bits:
|
||||
return InliningStatus_NotInlined;
|
||||
case SimdOperation::Fn_fromInt32x4Bits:
|
||||
return inlineSimdConvert(callInfo, native, true, SimdType::Int32x4, type);
|
||||
case SimdOperation::Fn_fromUint32x4Bits:
|
||||
return inlineSimdConvert(callInfo, native, true, MIRType_Int32x4, simdType);
|
||||
return inlineSimdConvert(callInfo, native, true, SimdType::Uint32x4, type);
|
||||
case SimdOperation::Fn_fromUint8x16Bits:
|
||||
case SimdOperation::Fn_fromUint16x8Bits:
|
||||
return InliningStatus_NotInlined;
|
||||
case SimdOperation::Fn_fromFloat32x4Bits:
|
||||
return inlineSimdConvert(callInfo, native, true, MIRType_Float32x4, simdType);
|
||||
return inlineSimdConvert(callInfo, native, true, SimdType::Float32x4, type);
|
||||
case SimdOperation::Fn_fromFloat64x2Bits:
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
@ -3403,65 +3392,75 @@ IonBuilder::boxSimd(CallInfo& callInfo, MDefinition* ins, InlineTypedObject* tem
|
|||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
// Inline a binary SIMD operation where both arguments are SIMD types.
|
||||
template<typename T>
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdBinary(CallInfo& callInfo, JSNative native, typename T::Operation op,
|
||||
MIRType mirType)
|
||||
SimdType type)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 2, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// If the type of any of the arguments is neither a SIMD type, an Object
|
||||
// type, or a Value, then the applyTypes phase will add a fallible box &
|
||||
// unbox sequence. This does not matter much as all binary SIMD
|
||||
// instructions are supposed to produce a TypeError when they're called
|
||||
// with non SIMD-arguments.
|
||||
T* ins = T::New(alloc(), callInfo.getArg(0), callInfo.getArg(1), op, mirType);
|
||||
MDefinition* lhs = unboxSimd(callInfo.getArg(0), type);
|
||||
MDefinition* rhs = unboxSimd(callInfo.getArg(1), type);
|
||||
|
||||
T* ins = T::New(alloc(), lhs, rhs, op, lhs->type());
|
||||
return boxSimd(callInfo, ins, templateObj);
|
||||
}
|
||||
|
||||
// Inline a SIMD shiftByScalar operation.
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdShift(CallInfo& callInfo, JSNative native, MSimdShift::Operation op,
|
||||
SimdType type)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 2, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MDefinition* vec = unboxSimd(callInfo.getArg(0), type);
|
||||
|
||||
MInstruction* ins = MSimdShift::New(alloc(), vec, callInfo.getArg(1), op, vec->type());
|
||||
return boxSimd(callInfo, ins, templateObj);
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdComp(CallInfo& callInfo, JSNative native, MSimdBinaryComp::Operation op,
|
||||
MIRType mirType, SimdSign sign)
|
||||
SimdType type)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 2, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// If the type of any of the arguments is neither a SIMD type, an Object
|
||||
// type, or a Value, then the applyTypes phase will add a fallible box &
|
||||
// unbox sequence. This does not matter much as all binary SIMD
|
||||
// instructions are supposed to produce a TypeError when they're called
|
||||
// with non SIMD-arguments.
|
||||
MDefinition* lhs = callInfo.getArg(0);
|
||||
MDefinition* rhs = callInfo.getArg(1);
|
||||
MInstruction* ins =
|
||||
MSimdBinaryComp::AddLegalized(alloc(), current, lhs, rhs, op, mirType, sign);
|
||||
MDefinition* lhs = unboxSimd(callInfo.getArg(0), type);
|
||||
MDefinition* rhs = unboxSimd(callInfo.getArg(1), type);
|
||||
MInstruction* ins = MSimdBinaryComp::AddLegalized(alloc(), current, lhs, rhs, op, lhs->type(),
|
||||
GetSimdSign(type));
|
||||
return boxSimd(callInfo, ins, templateObj);
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdUnary(CallInfo& callInfo, JSNative native, MSimdUnaryArith::Operation op,
|
||||
MIRType mirType)
|
||||
SimdType type)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 1, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// See comment in inlineSimdBinary
|
||||
MSimdUnaryArith* ins = MSimdUnaryArith::New(alloc(), callInfo.getArg(0), op, mirType);
|
||||
MDefinition* arg = unboxSimd(callInfo.getArg(0), type);
|
||||
|
||||
MSimdUnaryArith* ins = MSimdUnaryArith::New(alloc(), arg, op, arg->type());
|
||||
return boxSimd(callInfo, ins, templateObj);
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdSplat(CallInfo& callInfo, JSNative native, MIRType mirType)
|
||||
IonBuilder::inlineSimdSplat(CallInfo& callInfo, JSNative native, SimdType type)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 1, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// See comment in inlineSimdBinary
|
||||
MIRType mirType = SimdTypeToMIRType(type);
|
||||
MDefinition* arg = callInfo.getArg(0);
|
||||
|
||||
// Convert to 0 / -1 before splatting a boolean lane.
|
||||
|
@ -3473,8 +3472,7 @@ IonBuilder::inlineSimdSplat(CallInfo& callInfo, JSNative native, MIRType mirType
|
|||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdExtractLane(CallInfo& callInfo, JSNative native,
|
||||
MIRType vecType, SimdSign sign)
|
||||
IonBuilder::inlineSimdExtractLane(CallInfo& callInfo, JSNative native, SimdType type)
|
||||
{
|
||||
// extractLane() returns a scalar, so don't use canInlineSimd() which looks
|
||||
// for a template object.
|
||||
|
@ -3483,22 +3481,26 @@ IonBuilder::inlineSimdExtractLane(CallInfo& callInfo, JSNative native,
|
|||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
// Lane index.
|
||||
MDefinition* arg = callInfo.getArg(1);
|
||||
if (!arg->isConstantValue() || arg->type() != MIRType_Int32)
|
||||
return InliningStatus_NotInlined;
|
||||
int32_t lane = callInfo.getArg(1)->constantValue().toInt32();
|
||||
int32_t lane = arg->constantValue().toInt32();
|
||||
if (lane < 0 || lane >= 4)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// See comment in inlineSimdBinary
|
||||
// Original vector.
|
||||
MDefinition* orig = unboxSimd(callInfo.getArg(0), type);
|
||||
MIRType vecType = orig->type();
|
||||
MIRType laneType = SimdTypeToLaneType(vecType);
|
||||
SimdSign sign = GetSimdSign(type);
|
||||
|
||||
// An Uint32 lane can't be represented in MIRType_Int32. Get it as a double.
|
||||
if (sign == SimdSign::Unsigned && vecType == MIRType_Int32x4)
|
||||
if (type == SimdType::Uint32x4)
|
||||
laneType = MIRType_Double;
|
||||
|
||||
MSimdExtractElement* ins = MSimdExtractElement::New(alloc(), callInfo.getArg(0),
|
||||
vecType, laneType, SimdLane(lane), sign);
|
||||
MSimdExtractElement* ins =
|
||||
MSimdExtractElement::New(alloc(), orig, vecType, laneType, SimdLane(lane), sign);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
|
@ -3506,12 +3508,13 @@ IonBuilder::inlineSimdExtractLane(CallInfo& callInfo, JSNative native,
|
|||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdReplaceLane(CallInfo& callInfo, JSNative native, MIRType mirType)
|
||||
IonBuilder::inlineSimdReplaceLane(CallInfo& callInfo, JSNative native, SimdType type)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 3, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// Lane index.
|
||||
MDefinition* arg = callInfo.getArg(1);
|
||||
if (!arg->isConstantValue() || arg->type() != MIRType_Int32)
|
||||
return InliningStatus_NotInlined;
|
||||
|
@ -3520,13 +3523,17 @@ IonBuilder::inlineSimdReplaceLane(CallInfo& callInfo, JSNative native, MIRType m
|
|||
if (lane < 0 || lane >= 4)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// Original vector.
|
||||
MDefinition* orig = unboxSimd(callInfo.getArg(0), type);
|
||||
MIRType vecType = orig->type();
|
||||
|
||||
// Convert to 0 / -1 before inserting a boolean lane.
|
||||
MDefinition* value = callInfo.getArg(2);
|
||||
if (SimdTypeToLaneType(mirType) == MIRType_Boolean)
|
||||
if (SimdTypeToLaneType(vecType) == MIRType_Boolean)
|
||||
value = convertToBooleanSimdLane(value);
|
||||
|
||||
MSimdInsertElement* ins =
|
||||
MSimdInsertElement::New(alloc(), callInfo.getArg(0), value, mirType, SimdLane(lane));
|
||||
MSimdInsertElement::New(alloc(), orig, value, vecType, SimdLane(lane));
|
||||
return boxSimd(callInfo, ins, templateObj);
|
||||
}
|
||||
|
||||
|
@ -3534,54 +3541,66 @@ IonBuilder::inlineSimdReplaceLane(CallInfo& callInfo, JSNative native, MIRType m
|
|||
// must be floating point and the other integer. In this case, sign indicates if
|
||||
// the integer lanes should be treated as signed or unsigned integers.
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdConvert(CallInfo& callInfo, JSNative native, bool isCast,
|
||||
MIRType fromType, MIRType toType, SimdSign sign)
|
||||
IonBuilder::inlineSimdConvert(CallInfo& callInfo, JSNative native, bool isCast, SimdType fromType,
|
||||
SimdType toType)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 1, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// See comment in inlineSimdBinary
|
||||
MDefinition* arg = unboxSimd(callInfo.getArg(0), fromType);
|
||||
MIRType mirType = SimdTypeToMIRType(toType);
|
||||
|
||||
MInstruction* ins;
|
||||
if (isCast)
|
||||
if (isCast) {
|
||||
// Signed/Unsigned doesn't matter for bitcasts.
|
||||
ins = MSimdReinterpretCast::New(alloc(), callInfo.getArg(0), fromType, toType);
|
||||
else
|
||||
ins = MSimdReinterpretCast::New(alloc(), arg, arg->type(), mirType);
|
||||
} else {
|
||||
// Exactly one of fromType, toType must be an integer type.
|
||||
SimdSign sign = GetSimdSign(fromType);
|
||||
if (sign == SimdSign::NotApplicable)
|
||||
sign = GetSimdSign(toType);
|
||||
|
||||
// Possibly expand into multiple instructions.
|
||||
ins = MSimdConvert::AddLegalized(alloc(), current, callInfo.getArg(0),
|
||||
fromType, toType, sign);
|
||||
ins = MSimdConvert::AddLegalized(alloc(), current, arg, arg->type(), mirType, sign);
|
||||
}
|
||||
|
||||
return boxSimd(callInfo, ins, templateObj);
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdSelect(CallInfo& callInfo, JSNative native, MIRType mirType)
|
||||
IonBuilder::inlineSimdSelect(CallInfo& callInfo, JSNative native, SimdType type)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 3, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// See comment in inlineSimdBinary
|
||||
MSimdSelect* ins = MSimdSelect::New(alloc(), callInfo.getArg(0), callInfo.getArg(1),
|
||||
callInfo.getArg(2), mirType);
|
||||
MDefinition* mask = unboxSimd(callInfo.getArg(0), GetBooleanSimdType(type));
|
||||
MDefinition* tval = unboxSimd(callInfo.getArg(1), type);
|
||||
MDefinition* fval = unboxSimd(callInfo.getArg(2), type);
|
||||
|
||||
MSimdSelect* ins = MSimdSelect::New(alloc(), mask, tval, fval, tval->type());
|
||||
return boxSimd(callInfo, ins, templateObj);
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdShuffle(CallInfo& callInfo, JSNative native, MIRType mirType,
|
||||
unsigned numVectors, unsigned numLanes)
|
||||
IonBuilder::inlineSimdShuffle(CallInfo& callInfo, JSNative native, SimdType type,
|
||||
unsigned numVectors)
|
||||
{
|
||||
unsigned numLanes = GetSimdLanes(type);
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, numVectors + numLanes, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MIRType mirType = SimdTypeToMIRType(type);
|
||||
|
||||
MSimdGeneralShuffle* ins = MSimdGeneralShuffle::New(alloc(), numVectors, numLanes, mirType);
|
||||
|
||||
if (!ins->init(alloc()))
|
||||
return InliningStatus_Error;
|
||||
|
||||
for (unsigned i = 0; i < numVectors; i++)
|
||||
ins->setVector(i, callInfo.getArg(i));
|
||||
ins->setVector(i, unboxSimd(callInfo.getArg(i), type));
|
||||
for (size_t i = 0; i < numLanes; i++)
|
||||
ins->setLane(i, callInfo.getArg(numVectors + i));
|
||||
|
||||
|
@ -3589,7 +3608,8 @@ IonBuilder::inlineSimdShuffle(CallInfo& callInfo, JSNative native, MIRType mirTy
|
|||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdAnyAllTrue(CallInfo& callInfo, bool IsAllTrue, JSNative native)
|
||||
IonBuilder::inlineSimdAnyAllTrue(CallInfo& callInfo, bool IsAllTrue, JSNative native,
|
||||
SimdType type)
|
||||
{
|
||||
// anyTrue() / allTrue() return a scalar, so don't use canInlineSimd() which looks
|
||||
// for a template object.
|
||||
|
@ -3598,11 +3618,13 @@ IonBuilder::inlineSimdAnyAllTrue(CallInfo& callInfo, bool IsAllTrue, JSNative na
|
|||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
MDefinition* arg = unboxSimd(callInfo.getArg(0), type);
|
||||
|
||||
MUnaryInstruction* ins;
|
||||
if (IsAllTrue)
|
||||
ins = MSimdAllTrue::New(alloc(), callInfo.getArg(0), MIRType_Bool32x4);
|
||||
ins = MSimdAllTrue::New(alloc(), arg, arg->type());
|
||||
else
|
||||
ins = MSimdAnyTrue::New(alloc(), callInfo.getArg(0), MIRType_Bool32x4);
|
||||
ins = MSimdAnyTrue::New(alloc(), arg, arg->type());
|
||||
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
|
@ -3613,11 +3635,12 @@ IonBuilder::inlineSimdAnyAllTrue(CallInfo& callInfo, bool IsAllTrue, JSNative na
|
|||
// Get the typed array element type corresponding to the lanes in a SIMD vector type.
|
||||
// This only applies to SIMD types that can be loaded and stored to a typed array.
|
||||
static Scalar::Type
|
||||
SimdTypeToArrayElementType(MIRType type)
|
||||
SimdTypeToArrayElementType(SimdType type)
|
||||
{
|
||||
switch (type) {
|
||||
case MIRType_Float32x4: return Scalar::Float32x4;
|
||||
case MIRType_Int32x4: return Scalar::Int32x4;
|
||||
case SimdType::Float32x4: return Scalar::Float32x4;
|
||||
case SimdType::Int32x4:
|
||||
case SimdType::Uint32x4: return Scalar::Int32x4;
|
||||
default: MOZ_CRASH("unexpected simd type");
|
||||
}
|
||||
}
|
||||
|
@ -3667,7 +3690,7 @@ IonBuilder::prepareForSimdLoadStore(CallInfo& callInfo, Scalar::Type simdType, M
|
|||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdLoad(CallInfo& callInfo, JSNative native, MIRType type, unsigned numElems)
|
||||
IonBuilder::inlineSimdLoad(CallInfo& callInfo, JSNative native, SimdType type, unsigned numElems)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 2, &templateObj))
|
||||
|
@ -3682,14 +3705,14 @@ IonBuilder::inlineSimdLoad(CallInfo& callInfo, JSNative native, MIRType type, un
|
|||
return InliningStatus_NotInlined;
|
||||
|
||||
MLoadUnboxedScalar* load = MLoadUnboxedScalar::New(alloc(), elements, index, arrayType);
|
||||
load->setResultType(type);
|
||||
load->setResultType(SimdTypeToMIRType(type));
|
||||
load->setSimdRead(elemType, numElems);
|
||||
|
||||
return boxSimd(callInfo, load, templateObj);
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdStore(CallInfo& callInfo, JSNative native, MIRType type, unsigned numElems)
|
||||
IonBuilder::inlineSimdStore(CallInfo& callInfo, JSNative native, SimdType type, unsigned numElems)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 3, &templateObj))
|
||||
|
@ -3703,14 +3726,16 @@ IonBuilder::inlineSimdStore(CallInfo& callInfo, JSNative native, MIRType type, u
|
|||
if (!prepareForSimdLoadStore(callInfo, elemType, &elements, &index, &arrayType))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MDefinition* valueToWrite = callInfo.getArg(2);
|
||||
MDefinition* valueToWrite = unboxSimd(callInfo.getArg(2), type);
|
||||
MStoreUnboxedScalar* store = MStoreUnboxedScalar::New(alloc(), elements, index,
|
||||
valueToWrite, arrayType,
|
||||
MStoreUnboxedScalar::TruncateInput);
|
||||
store->setSimdWrite(elemType, numElems);
|
||||
|
||||
current->add(store);
|
||||
current->push(valueToWrite);
|
||||
// Produce the original boxed value as our return value.
|
||||
// This is unlikely to be used, so don't bother reboxing valueToWrite.
|
||||
current->push(callInfo.getArg(2));
|
||||
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче