mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Bug 1134638: 14. Inline SIMD getters (signMask, .x, .y, .z, .w) in Ion; r=nbp
--HG-- extra : rebase_source : ef4b04965069c83dc0c129cc86013fb484e7a1bd
This commit is contained in:
parent
d9f3eae184
commit
1c09b86cc2
@ -18,6 +18,8 @@ namespace JS {
|
||||
"getprop inferred constant") \
|
||||
_(GetProp_Constant, \
|
||||
"getprop constant") \
|
||||
_(GetProp_SimdGetter, \
|
||||
"getprop SIMD getter") \
|
||||
_(GetProp_TypedObject, \
|
||||
"getprop TypedObject") \
|
||||
_(GetProp_DefiniteSlot, \
|
||||
@ -144,8 +146,10 @@ namespace JS {
|
||||
"TypedObject array of unknown length") \
|
||||
_(AccessNotDense, \
|
||||
"access not on dense native (check receiver, index, and result types)") \
|
||||
_(AccessNotSimdObject, \
|
||||
"access not on SIMD object (check receiver)") \
|
||||
_(AccessNotTypedObject, \
|
||||
"access not on typed array (check receiver and index types)") \
|
||||
"access not on typed object (check receiver and index types)") \
|
||||
_(AccessNotTypedArray, \
|
||||
"access not on typed array (check receiver, index, and result types)") \
|
||||
_(AccessNotString, \
|
||||
@ -164,6 +168,12 @@ namespace JS {
|
||||
"index type must be int32, string, or symbol") \
|
||||
_(SetElemNonDenseNonTANotCached, \
|
||||
"setelem on non-dense non-TAs are not inline cached") \
|
||||
_(NoSimdJitSupport, \
|
||||
"SIMD isn't optimized in Ion on this platform yet") \
|
||||
_(SimdTypeNotOptimized, \
|
||||
"given SIMD type isn't optimized in Ion yet") \
|
||||
_(UnknownSimdProperty, \
|
||||
"getelem on an unknown SIMD property ") \
|
||||
\
|
||||
_(CantInlineGeneric, \
|
||||
"can't inline") \
|
||||
|
29
js/src/jit-test/tests/SIMD/getters.js
Normal file
29
js/src/jit-test/tests/SIMD/getters.js
Normal file
@ -0,0 +1,29 @@
|
||||
load(libdir + 'simd.js');
|
||||
|
||||
setJitCompilerOption("ion.warmup.trigger", 50);
|
||||
|
||||
function f() {
|
||||
var i4 = SIMD.int32x4(1, -2, 3, -4);
|
||||
|
||||
var v = Math.fround(13.37);
|
||||
var f4 = SIMD.float32x4(13.37, NaN, Infinity, -0);
|
||||
|
||||
for (var i = 0; i < 150; i++) {
|
||||
assertEq(i4.x, 1);
|
||||
assertEq(i4.y, -2);
|
||||
assertEq(i4.z, 3);
|
||||
assertEq(i4.w, -4);
|
||||
|
||||
assertEq(i4.signMask, 0b1010);
|
||||
|
||||
assertEq(f4.x, v);
|
||||
assertEq(f4.y, NaN);
|
||||
assertEq(f4.z, Infinity);
|
||||
assertEq(f4.w, -0);
|
||||
|
||||
assertEq(f4.signMask, 0b1000);
|
||||
}
|
||||
}
|
||||
|
||||
f();
|
||||
|
@ -9870,6 +9870,11 @@ IonBuilder::jsop_getprop(PropertyName *name)
|
||||
if (!getPropTryConstant(&emitted, obj, name, types) || emitted)
|
||||
return emitted;
|
||||
|
||||
// Try to emit SIMD getter loads
|
||||
trackOptimizationAttempt(TrackedStrategy::GetProp_SimdGetter);
|
||||
if (!getPropTrySimdGetter(&emitted, obj, name) || emitted)
|
||||
return emitted;
|
||||
|
||||
// Try to emit loads from known binary data blocks
|
||||
trackOptimizationAttempt(TrackedStrategy::GetProp_TypedObject);
|
||||
if (!getPropTryTypedObject(&emitted, obj, name) || emitted)
|
||||
@ -10061,6 +10066,81 @@ IonBuilder::getPropTryConstant(bool *emitted, MDefinition *obj, PropertyName *na
|
||||
return true;
|
||||
}
|
||||
|
||||
MIRType
|
||||
IonBuilder::SimdTypeDescrToMIRType(SimdTypeDescr::Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case SimdTypeDescr::TYPE_INT32: return MIRType_Int32x4;
|
||||
case SimdTypeDescr::TYPE_FLOAT32: return MIRType_Float32x4;
|
||||
case SimdTypeDescr::TYPE_FLOAT64: return MIRType_Undefined;
|
||||
}
|
||||
MOZ_CRASH("unimplemented MIR type for a SimdTypeDescr::Type");
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTrySimdGetter(bool *emitted, MDefinition *obj, PropertyName *name)
|
||||
{
|
||||
MOZ_ASSERT(!*emitted);
|
||||
|
||||
if (!JitSupportsSimd()) {
|
||||
trackOptimizationOutcome(TrackedOutcome::NoSimdJitSupport);
|
||||
return true;
|
||||
}
|
||||
|
||||
TypedObjectPrediction objPrediction = typedObjectPrediction(obj);
|
||||
if (objPrediction.isUseless()) {
|
||||
trackOptimizationOutcome(TrackedOutcome::AccessNotTypedObject);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (objPrediction.kind() != type::Simd) {
|
||||
trackOptimizationOutcome(TrackedOutcome::AccessNotSimdObject);
|
||||
return true;
|
||||
}
|
||||
|
||||
MIRType type = SimdTypeDescrToMIRType(objPrediction.simdType());
|
||||
if (type == MIRType_Undefined) {
|
||||
trackOptimizationOutcome(TrackedOutcome::SimdTypeNotOptimized);
|
||||
return true;
|
||||
}
|
||||
|
||||
const JSAtomState &names = compartment->runtime()->names();
|
||||
|
||||
// Reading the signMask property.
|
||||
if (name == names.signMask) {
|
||||
MSimdSignMask *ins = MSimdSignMask::New(alloc(), obj, type);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
trackOptimizationSuccess();
|
||||
*emitted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Reading a lane property.
|
||||
SimdLane lane;
|
||||
if (name == names.x) {
|
||||
lane = LaneX;
|
||||
} else if (name == names.y) {
|
||||
lane = LaneY;
|
||||
} else if (name == names.z) {
|
||||
lane = LaneZ;
|
||||
} else if (name == names.w) {
|
||||
lane = LaneW;
|
||||
} else {
|
||||
// Unknown getprop access on a SIMD value
|
||||
trackOptimizationOutcome(TrackedOutcome::UnknownSimdProperty);
|
||||
return true;
|
||||
}
|
||||
|
||||
MIRType scalarType = SimdTypeToScalarType(type);
|
||||
MSimdExtractElement *ins = MSimdExtractElement::New(alloc(), obj, type, scalarType, lane);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
trackOptimizationSuccess();
|
||||
*emitted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTryTypedObject(bool *emitted,
|
||||
MDefinition *obj,
|
||||
|
@ -435,6 +435,7 @@ class IonBuilder
|
||||
TemporaryTypeSet *types);
|
||||
bool getPropTryInlineAccess(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
BarrierKind barrier, TemporaryTypeSet *types);
|
||||
bool getPropTrySimdGetter(bool *emitted, MDefinition *obj, PropertyName *name);
|
||||
bool getPropTryTypedObject(bool *emitted, MDefinition *obj, PropertyName *name);
|
||||
bool getPropTryScalarPropOfTypedObject(bool *emitted, MDefinition *typedObj,
|
||||
int32_t fieldOffset,
|
||||
@ -810,6 +811,7 @@ class IonBuilder
|
||||
InliningStatus inlineConstructSimdObject(CallInfo &callInfo, SimdTypeDescr *target);
|
||||
|
||||
// helpers
|
||||
static MIRType SimdTypeDescrToMIRType(SimdTypeDescr::Type type);
|
||||
bool checkInlineSimd(CallInfo &callInfo, JSNative native, SimdTypeDescr::Type type,
|
||||
unsigned numArgs, InlineTypedObject **templateObj);
|
||||
IonBuilder::InliningStatus boxSimd(CallInfo &callInfo, MInstruction *ins,
|
||||
|
@ -2882,17 +2882,11 @@ IonBuilder::inlineConstructSimdObject(CallInfo &callInfo, SimdTypeDescr *descr)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// Generic constructor of SIMD valuesX4.
|
||||
MIRType simdType = MIRType(-1); // initialize to silence GCC warning
|
||||
switch (descr->type()) {
|
||||
case SimdTypeDescr::TYPE_INT32:
|
||||
simdType = MIRType_Int32x4;
|
||||
break;
|
||||
case SimdTypeDescr::TYPE_FLOAT32:
|
||||
simdType = MIRType_Float32x4;
|
||||
break;
|
||||
case SimdTypeDescr::TYPE_FLOAT64:
|
||||
return InliningStatus_NotInlined; // :TODO: NYI (Bug 1124205)
|
||||
}
|
||||
MIRType simdType = SimdTypeDescrToMIRType(descr->type());
|
||||
|
||||
// TODO Happens for TYPE_FLOAT64 (Bug 1124205)
|
||||
if (simdType == MIRType_Undefined)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// We do not inline SIMD constructors if the number of arguments does not
|
||||
// match the number of lanes.
|
||||
@ -2925,17 +2919,6 @@ IonBuilder::inlineConstructSimdObject(CallInfo &callInfo, SimdTypeDescr *descr)
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
static MIRType
|
||||
SimdTypeDescrToMIRType(SimdTypeDescr::Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case SimdTypeDescr::TYPE_FLOAT32: return MIRType_Float32x4;
|
||||
case SimdTypeDescr::TYPE_INT32: return MIRType_Int32x4;
|
||||
case SimdTypeDescr::TYPE_FLOAT64: break;
|
||||
}
|
||||
MOZ_CRASH("unexpected SimdTypeDescr");
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::checkInlineSimd(CallInfo &callInfo, JSNative native, SimdTypeDescr::Type type,
|
||||
unsigned numArgs, InlineTypedObject **templateObj)
|
||||
|
@ -1589,27 +1589,36 @@ class MSimdReinterpretCast
|
||||
// Extracts a lane element from a given vector type, given by its lane symbol.
|
||||
class MSimdExtractElement
|
||||
: public MUnaryInstruction,
|
||||
public NoTypePolicy::Data
|
||||
public SimdPolicy<0>::Data
|
||||
{
|
||||
protected:
|
||||
SimdLane lane_;
|
||||
|
||||
MSimdExtractElement(MDefinition *obj, MIRType type, SimdLane lane)
|
||||
MSimdExtractElement(MDefinition *obj, MIRType vecType, MIRType scalarType, SimdLane lane)
|
||||
: MUnaryInstruction(obj), lane_(lane)
|
||||
{
|
||||
MOZ_ASSERT(IsSimdType(obj->type()));
|
||||
MOZ_ASSERT(uint32_t(lane) < SimdTypeToLength(obj->type()));
|
||||
MOZ_ASSERT(!IsSimdType(type));
|
||||
MOZ_ASSERT(SimdTypeToScalarType(obj->type()) == type);
|
||||
setResultType(type);
|
||||
MOZ_ASSERT(IsSimdType(vecType));
|
||||
MOZ_ASSERT(uint32_t(lane) < SimdTypeToLength(vecType));
|
||||
MOZ_ASSERT(!IsSimdType(scalarType));
|
||||
MOZ_ASSERT(SimdTypeToScalarType(vecType) == scalarType);
|
||||
|
||||
specialization_ = vecType;
|
||||
setResultType(scalarType);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(SimdExtractElement)
|
||||
|
||||
static MSimdExtractElement *NewAsmJS(TempAllocator &alloc, MDefinition *obj, MIRType type,
|
||||
SimdLane lane)
|
||||
{
|
||||
return new(alloc) MSimdExtractElement(obj, type, lane);
|
||||
return new(alloc) MSimdExtractElement(obj, obj->type(), type, lane);
|
||||
}
|
||||
|
||||
static MSimdExtractElement *New(TempAllocator &alloc, MDefinition *obj, MIRType vecType,
|
||||
MIRType scalarType, SimdLane lane)
|
||||
{
|
||||
return new(alloc) MSimdExtractElement(obj, vecType, scalarType, lane);
|
||||
}
|
||||
|
||||
SimdLane lane() const {
|
||||
@ -1703,22 +1712,29 @@ class MSimdInsertElement
|
||||
// Extracts the sign bits from a given vector, returning an MIRType_Int32.
|
||||
class MSimdSignMask
|
||||
: public MUnaryInstruction,
|
||||
public NoTypePolicy::Data
|
||||
public SimdPolicy<0>::Data
|
||||
{
|
||||
protected:
|
||||
explicit MSimdSignMask(MDefinition *obj)
|
||||
explicit MSimdSignMask(MDefinition *obj, MIRType type)
|
||||
: MUnaryInstruction(obj)
|
||||
{
|
||||
MOZ_ASSERT(IsSimdType(obj->type()));
|
||||
setResultType(MIRType_Int32);
|
||||
specialization_ = type;
|
||||
setMovable();
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(SimdSignMask)
|
||||
|
||||
static MSimdSignMask *NewAsmJS(TempAllocator &alloc, MDefinition *obj)
|
||||
{
|
||||
return new(alloc) MSimdSignMask(obj);
|
||||
MOZ_ASSERT(IsSimdType(obj->type()));
|
||||
return new(alloc) MSimdSignMask(obj, obj->type());
|
||||
}
|
||||
|
||||
static MSimdSignMask *New(TempAllocator &alloc, MDefinition *obj, MIRType type)
|
||||
{
|
||||
return new(alloc) MSimdSignMask(obj, type);
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const MOZ_OVERRIDE {
|
||||
|
@ -164,7 +164,7 @@ class TypedObjectPrediction {
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Simple operations
|
||||
//
|
||||
// Only valid when |kind()| is Scalar, Reference, or x4 (as appropriate).
|
||||
// Only valid when |kind()| is Scalar, Reference, or Simd (as appropriate).
|
||||
|
||||
ScalarTypeDescr::Type scalarType() const;
|
||||
ReferenceTypeDescr::Type referenceType() const;
|
||||
|
Loading…
Reference in New Issue
Block a user