зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1138881 - IonMonkey: Allow fixing andor blocks which have MFilterTypeSet, r=bhackett
This commit is contained in:
Родитель
275f9c89cf
Коммит
f7921e40a3
|
@ -94,6 +94,59 @@ BlockComputesConstant(MBasicBlock *block, MDefinition *value)
|
|||
return true;
|
||||
}
|
||||
|
||||
// Find phis that are redudant:
|
||||
//
|
||||
// 1) phi(a, a)
|
||||
// can get replaced by a
|
||||
//
|
||||
// 2) phi(filtertypeset(a, type1), filtertypeset(a, type1))
|
||||
// equals filtertypeset(a, type1)
|
||||
//
|
||||
// 3) phi(a, filtertypeset(a, type1))
|
||||
// equals filtertypeset(a, type1 union type(a))
|
||||
// equals filtertypeset(a, type(a))
|
||||
// equals a
|
||||
//
|
||||
// 4) phi(filtertypeset(a, type1), filtertypeset(a, type2))
|
||||
// equals filtertypeset(a, type1 union type2)
|
||||
//
|
||||
// This is the special case. We can only replace this with 'a' iif
|
||||
// type(a) == type1 union type2. Since optimizations could have
|
||||
// happened based on a more specific phi type.
|
||||
static bool
|
||||
IsPhiRedudantFilter(MPhi *phi)
|
||||
{
|
||||
// Handle (1) and (2)
|
||||
if (phi->operandIfRedundant())
|
||||
return true;
|
||||
|
||||
// Handle (3)
|
||||
bool onlyFilters = false;
|
||||
MDefinition *a = phi->getOperand(0);
|
||||
if (a->isFilterTypeSet()) {
|
||||
a = a->toFilterTypeSet()->input();
|
||||
onlyFilters = true;
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < phi->numOperands(); i++) {
|
||||
MDefinition *operand = phi->getOperand(i);
|
||||
if (operand == a) {
|
||||
onlyFilters = false;
|
||||
continue;
|
||||
}
|
||||
if (operand->isFilterTypeSet() && operand->toFilterTypeSet()->input() == a)
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
if (!onlyFilters)
|
||||
return true;
|
||||
|
||||
// Handle (4)
|
||||
MOZ_ASSERT(onlyFilters);
|
||||
return EqualTypes(a->type(), a->resultTypeSet(),
|
||||
phi->type(), phi->resultTypeSet());
|
||||
}
|
||||
|
||||
// Determine whether phiBlock/testBlock simply compute a phi and perform a
|
||||
// test on it.
|
||||
static bool
|
||||
|
@ -131,8 +184,13 @@ BlockIsSingleTest(MBasicBlock *phiBlock, MBasicBlock *testBlock, MPhi **pphi, MT
|
|||
}
|
||||
|
||||
for (MPhiIterator iter = phiBlock->phisBegin(); iter != phiBlock->phisEnd(); ++iter) {
|
||||
if (*iter != phi)
|
||||
return false;
|
||||
if (*iter == phi)
|
||||
continue;
|
||||
|
||||
if (IsPhiRedudantFilter(*iter))
|
||||
continue;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (phiBlock != testBlock && !testBlock->phisEmpty())
|
||||
|
@ -257,6 +315,23 @@ MaybeFoldConditionBlock(MIRGraph &graph, MBasicBlock *initialBlock)
|
|||
|
||||
// OK, we found the desired pattern, now transform the graph.
|
||||
|
||||
// Patch up phis that filter their input.
|
||||
for (MPhiIterator iter = phiBlock->phisBegin(); iter != phiBlock->phisEnd(); ++iter) {
|
||||
if (*iter == phi)
|
||||
continue;
|
||||
|
||||
MOZ_ASSERT(IsPhiRedudantFilter(*iter));
|
||||
MDefinition *redundant = (*iter)->operandIfRedundant();
|
||||
|
||||
if (!redundant) {
|
||||
redundant = (*iter)->getOperand(0);
|
||||
if (redundant->isFilterTypeSet())
|
||||
redundant = redundant->toFilterTypeSet()->input();
|
||||
}
|
||||
|
||||
(*iter)->replaceAllUsesWith(redundant);
|
||||
}
|
||||
|
||||
// Remove the phi from phiBlock.
|
||||
phiBlock->discardPhi(*phiBlock->phisBegin());
|
||||
|
||||
|
|
|
@ -7501,36 +7501,6 @@ IonBuilder::getStaticName(JSObject *staticObject, PropertyName *name, bool *psuc
|
|||
rvalType, barrier, types);
|
||||
}
|
||||
|
||||
// Whether 'types' includes all possible values represented by input/inputTypes.
|
||||
bool
|
||||
jit::TypeSetIncludes(TypeSet *types, MIRType input, TypeSet *inputTypes)
|
||||
{
|
||||
if (!types)
|
||||
return inputTypes && inputTypes->empty();
|
||||
|
||||
switch (input) {
|
||||
case MIRType_Undefined:
|
||||
case MIRType_Null:
|
||||
case MIRType_Boolean:
|
||||
case MIRType_Int32:
|
||||
case MIRType_Double:
|
||||
case MIRType_Float32:
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol:
|
||||
case MIRType_MagicOptimizedArguments:
|
||||
return types->hasType(TypeSet::PrimitiveType(ValueTypeFromMIRType(input)));
|
||||
|
||||
case MIRType_Object:
|
||||
return types->unknownObject() || (inputTypes && inputTypes->isSubset(types));
|
||||
|
||||
case MIRType_Value:
|
||||
return types->unknown() || (inputTypes && inputTypes->isSubset(types));
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Bad input type");
|
||||
}
|
||||
}
|
||||
|
||||
// Whether a write of the given value may need a post-write barrier for GC purposes.
|
||||
bool
|
||||
jit::NeedsPostBarrier(CompileInfo &info, MDefinition *value)
|
||||
|
|
|
@ -1350,8 +1350,6 @@ class CallInfo
|
|||
}
|
||||
};
|
||||
|
||||
bool TypeSetIncludes(TypeSet *types, MIRType input, TypeSet *inputTypes);
|
||||
|
||||
bool NeedsPostBarrier(CompileInfo &info, MDefinition *value);
|
||||
|
||||
} // namespace jit
|
||||
|
|
|
@ -1769,6 +1769,61 @@ jit::MergeTypes(MIRType *ptype, TemporaryTypeSet **ptypeSet,
|
|||
return true;
|
||||
}
|
||||
|
||||
// Tests whether 'types' includes all possible values represented by
|
||||
// input/inputTypes.
|
||||
bool
|
||||
jit::TypeSetIncludes(TypeSet *types, MIRType input, TypeSet *inputTypes)
|
||||
{
|
||||
if (!types)
|
||||
return inputTypes && inputTypes->empty();
|
||||
|
||||
switch (input) {
|
||||
case MIRType_Undefined:
|
||||
case MIRType_Null:
|
||||
case MIRType_Boolean:
|
||||
case MIRType_Int32:
|
||||
case MIRType_Double:
|
||||
case MIRType_Float32:
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol:
|
||||
case MIRType_MagicOptimizedArguments:
|
||||
return types->hasType(TypeSet::PrimitiveType(ValueTypeFromMIRType(input)));
|
||||
|
||||
case MIRType_Object:
|
||||
return types->unknownObject() || (inputTypes && inputTypes->isSubset(types));
|
||||
|
||||
case MIRType_Value:
|
||||
return types->unknown() || (inputTypes && inputTypes->isSubset(types));
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Bad input type");
|
||||
}
|
||||
}
|
||||
|
||||
// Tests if two type combos (type/typeset) are equal.
|
||||
bool
|
||||
jit::EqualTypes(MIRType type1, TemporaryTypeSet *typeset1,
|
||||
MIRType type2, TemporaryTypeSet *typeset2)
|
||||
{
|
||||
// Types should equal.
|
||||
if (type1 != type2)
|
||||
return false;
|
||||
|
||||
// Both have equal type and no typeset.
|
||||
if (!typeset1 && !typeset2)
|
||||
return true;
|
||||
|
||||
// If only one instructions has a typeset.
|
||||
// Test if the typset contains the same information as the MIRType.
|
||||
if (typeset1 && !typeset2)
|
||||
return TypeSetIncludes(typeset1, type2, nullptr);
|
||||
if (!typeset1 && typeset2)
|
||||
return TypeSetIncludes(typeset2, type1, nullptr);
|
||||
|
||||
// Typesets should equal.
|
||||
return typeset1->equals(typeset2);
|
||||
}
|
||||
|
||||
bool
|
||||
MPhi::specializeType()
|
||||
{
|
||||
|
|
|
@ -2826,6 +2826,12 @@ MakeSingletonTypeSet(CompilerConstraintList *constraints, JSObject *obj);
|
|||
bool
|
||||
MergeTypes(MIRType *ptype, TemporaryTypeSet **ptypeSet,
|
||||
MIRType newType, TemporaryTypeSet *newTypeSet);
|
||||
bool
|
||||
TypeSetIncludes(TypeSet *types, MIRType input, TypeSet *inputTypes);
|
||||
|
||||
bool
|
||||
EqualTypes(MIRType type1, TemporaryTypeSet *typeset1,
|
||||
MIRType type2, TemporaryTypeSet *typeset2);
|
||||
|
||||
// Helper class to assert all GC pointers embedded in MIR instructions are
|
||||
// tenured. Off-thread Ion compilation and nursery GCs can happen in parallel,
|
||||
|
|
Загрузка…
Ссылка в новой задаче