Bug 1630779 - Fix DefinitelyDifferentValue. r=iain

I think using MConstant::equals was /probably/ fine, but I find it hard to reason about.
This also potentially allows comparing double 1.0 to int32 1 or similar.

Differential Revision: https://phabricator.services.mozilla.com/D71240
This commit is contained in:
Tom Schuster 2020-04-17 22:33:50 +00:00
Родитель e245496607
Коммит 3d95c82e6e
1 изменённых файлов: 42 добавлений и 18 удалений

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

@ -4967,31 +4967,55 @@ static bool AddIsANonZeroAdditionOf(MAdd* add, MDefinition* ins) {
return true;
}
// Skip over instructions that usually appear between the actual index
// value being used and the MLoadElement.
// They don't modify the index value in a meaningful way.
static MDefinition* SkipUninterestingInstructions(MDefinition* ins) {
// Drop the MToNumberInt32 added by the TypePolicy for double and float
// values.
if (ins->isToNumberInt32()) {
return SkipUninterestingInstructions(ins->toToNumberInt32()->input());
}
// Ignore the bounds check, which don't modify the index.
if (ins->isBoundsCheck()) {
return SkipUninterestingInstructions(ins->toBoundsCheck()->index());
}
// Masking the index for Spectre-mitigation is not observable.
if (ins->isSpectreMaskIndex()) {
return SkipUninterestingInstructions(ins->toSpectreMaskIndex()->index());
}
return ins;
}
static bool DefinitelyDifferentValue(MDefinition* ins1, MDefinition* ins2) {
ins1 = SkipUninterestingInstructions(ins1);
ins2 = SkipUninterestingInstructions(ins2);
if (ins1 == ins2) {
return false;
}
// Drop the MToNumberInt32 added by the TypePolicy for double and float
// values.
if (ins1->isToNumberInt32()) {
return DefinitelyDifferentValue(ins1->toToNumberInt32()->input(), ins2);
}
if (ins2->isToNumberInt32()) {
return DefinitelyDifferentValue(ins2->toToNumberInt32()->input(), ins1);
}
// Ignore the bounds check, which in most cases will contain the same info.
if (ins1->isBoundsCheck()) {
return DefinitelyDifferentValue(ins1->toBoundsCheck()->index(), ins2);
}
if (ins2->isBoundsCheck()) {
return DefinitelyDifferentValue(ins2->toBoundsCheck()->index(), ins1);
}
// For constants check they are not equal.
if (ins1->isConstant() && ins2->isConstant()) {
return !ins1->toConstant()->equals(ins2->toConstant());
MConstant* cst1 = ins1->toConstant();
MConstant* cst2 = ins2->toConstant();
if (!cst1->isTypeRepresentableAsDouble() ||
!cst2->isTypeRepresentableAsDouble()) {
return false;
}
// Be conservative and only allow values that fit into int32.
int32_t n1, n2;
if (!mozilla::NumberIsInt32(cst1->numberToDouble(), &n1) ||
!mozilla::NumberIsInt32(cst2->numberToDouble(), &n2)) {
return false;
}
return n1 != n2;
}
// Check if "ins1 = ins2 + cte", which would make both instructions