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:
Benjamin Bouvier 2015-02-26 12:08:16 +01:00
Родитель d9f3eae184
Коммит 1c09b86cc2
7 изменённых файлов: 156 добавлений и 36 удалений

Просмотреть файл

@ -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") \

Просмотреть файл

@ -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;