зеркало из 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;
|
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,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче