Bug 1138881 - IonMonkey: Allow fixing andor blocks which have MFilterTypeSet, r=bhackett

This commit is contained in:
Hannes Verschore 2015-03-25 16:15:28 +01:00
Родитель 275f9c89cf
Коммит f7921e40a3
5 изменённых файлов: 138 добавлений и 34 удалений

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

@ -94,6 +94,59 @@ BlockComputesConstant(MBasicBlock *block, MDefinition *value)
return true; 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 // Determine whether phiBlock/testBlock simply compute a phi and perform a
// test on it. // test on it.
static bool static bool
@ -131,8 +184,13 @@ BlockIsSingleTest(MBasicBlock *phiBlock, MBasicBlock *testBlock, MPhi **pphi, MT
} }
for (MPhiIterator iter = phiBlock->phisBegin(); iter != phiBlock->phisEnd(); ++iter) { for (MPhiIterator iter = phiBlock->phisBegin(); iter != phiBlock->phisEnd(); ++iter) {
if (*iter != phi) if (*iter == phi)
return false; continue;
if (IsPhiRedudantFilter(*iter))
continue;
return false;
} }
if (phiBlock != testBlock && !testBlock->phisEmpty()) if (phiBlock != testBlock && !testBlock->phisEmpty())
@ -257,6 +315,23 @@ MaybeFoldConditionBlock(MIRGraph &graph, MBasicBlock *initialBlock)
// OK, we found the desired pattern, now transform the graph. // 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. // Remove the phi from phiBlock.
phiBlock->discardPhi(*phiBlock->phisBegin()); phiBlock->discardPhi(*phiBlock->phisBegin());

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

@ -7501,36 +7501,6 @@ IonBuilder::getStaticName(JSObject *staticObject, PropertyName *name, bool *psuc
rvalType, barrier, types); 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. // Whether a write of the given value may need a post-write barrier for GC purposes.
bool bool
jit::NeedsPostBarrier(CompileInfo &info, MDefinition *value) 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); bool NeedsPostBarrier(CompileInfo &info, MDefinition *value);
} // namespace jit } // namespace jit

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

@ -1769,6 +1769,61 @@ jit::MergeTypes(MIRType *ptype, TemporaryTypeSet **ptypeSet,
return true; 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 bool
MPhi::specializeType() MPhi::specializeType()
{ {

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

@ -2826,6 +2826,12 @@ MakeSingletonTypeSet(CompilerConstraintList *constraints, JSObject *obj);
bool bool
MergeTypes(MIRType *ptype, TemporaryTypeSet **ptypeSet, MergeTypes(MIRType *ptype, TemporaryTypeSet **ptypeSet,
MIRType newType, TemporaryTypeSet *newTypeSet); 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 // Helper class to assert all GC pointers embedded in MIR instructions are
// tenured. Off-thread Ion compilation and nursery GCs can happen in parallel, // tenured. Off-thread Ion compilation and nursery GCs can happen in parallel,