mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1861983 - Part 6: Add more MinMax folding. r=jandem
This reduces the `MMinMax` operations in `s.substring(1, 3)` from four to just two. Depends on D192224 Differential Revision: https://phabricator.services.mozilla.com/D192225
This commit is contained in:
parent
830bee2c73
commit
f97fefcba8
@ -2710,36 +2710,6 @@ MDefinition* MMinMax::foldsTo(TempAllocator& alloc) {
|
|||||||
return lhs();
|
return lhs();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fold min/max operations with same inputs.
|
|
||||||
if (lhs()->isMinMax() || rhs()->isMinMax()) {
|
|
||||||
auto* other = lhs()->isMinMax() ? lhs()->toMinMax() : rhs()->toMinMax();
|
|
||||||
auto* operand = lhs()->isMinMax() ? rhs() : lhs();
|
|
||||||
|
|
||||||
if (operand == other->lhs() || operand == other->rhs()) {
|
|
||||||
if (isMax() == other->isMax()) {
|
|
||||||
// min(x, min(x, y)) = min(x, y)
|
|
||||||
// max(x, max(x, y)) = max(x, y)
|
|
||||||
return other;
|
|
||||||
}
|
|
||||||
if (!IsFloatingPointType(type())) {
|
|
||||||
// When neither value is NaN:
|
|
||||||
// max(x, min(x, y)) = x
|
|
||||||
// min(x, max(x, y)) = x
|
|
||||||
|
|
||||||
// Ensure that any bailouts that we depend on to guarantee that |y| is
|
|
||||||
// Int32 are not removed.
|
|
||||||
auto* otherOp = operand == other->lhs() ? other->rhs() : other->lhs();
|
|
||||||
otherOp->setGuardRangeBailoutsUnchecked();
|
|
||||||
|
|
||||||
return operand;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lhs()->isConstant() && !rhs()->isConstant()) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto foldConstants = [&alloc](MDefinition* lhs, MDefinition* rhs,
|
auto foldConstants = [&alloc](MDefinition* lhs, MDefinition* rhs,
|
||||||
bool isMax) -> MConstant* {
|
bool isMax) -> MConstant* {
|
||||||
MOZ_ASSERT(lhs->type() == rhs->type());
|
MOZ_ASSERT(lhs->type() == rhs->type());
|
||||||
@ -2772,6 +2742,77 @@ MDefinition* MMinMax::foldsTo(TempAllocator& alloc) {
|
|||||||
return MConstant::New(alloc, DoubleValue(result));
|
return MConstant::New(alloc, DoubleValue(result));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Try to fold the following patterns when |x| and |y| are constants.
|
||||||
|
//
|
||||||
|
// min(min(x, z), min(y, z)) = min(min(x, y), z)
|
||||||
|
// max(max(x, z), max(y, z)) = max(max(x, y), z)
|
||||||
|
// max(min(x, z), min(y, z)) = min(max(x, y), z)
|
||||||
|
// min(max(x, z), max(y, z)) = max(min(x, y), z)
|
||||||
|
if (lhs()->isMinMax() && rhs()->isMinMax()) {
|
||||||
|
do {
|
||||||
|
auto* left = lhs()->toMinMax();
|
||||||
|
auto* right = rhs()->toMinMax();
|
||||||
|
if (left->isMax() != right->isMax()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
MDefinition* x;
|
||||||
|
MDefinition* y;
|
||||||
|
MDefinition* z;
|
||||||
|
if (left->lhs() == right->lhs()) {
|
||||||
|
std::tie(x, y, z) = std::tuple{left->rhs(), right->rhs(), left->lhs()};
|
||||||
|
} else if (left->lhs() == right->rhs()) {
|
||||||
|
std::tie(x, y, z) = std::tuple{left->rhs(), right->lhs(), left->lhs()};
|
||||||
|
} else if (left->rhs() == right->lhs()) {
|
||||||
|
std::tie(x, y, z) = std::tuple{left->lhs(), right->rhs(), left->rhs()};
|
||||||
|
} else if (left->rhs() == right->rhs()) {
|
||||||
|
std::tie(x, y, z) = std::tuple{left->lhs(), right->lhs(), left->rhs()};
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!x->isConstant() || !x->toConstant()->isTypeRepresentableAsDouble() ||
|
||||||
|
!y->isConstant() || !y->toConstant()->isTypeRepresentableAsDouble()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto* folded = foldConstants(x, y, isMax())) {
|
||||||
|
block()->insertBefore(this, folded);
|
||||||
|
return MMinMax::New(alloc, folded, z, type(), left->isMax());
|
||||||
|
}
|
||||||
|
} while (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fold min/max operations with same inputs.
|
||||||
|
if (lhs()->isMinMax() || rhs()->isMinMax()) {
|
||||||
|
auto* other = lhs()->isMinMax() ? lhs()->toMinMax() : rhs()->toMinMax();
|
||||||
|
auto* operand = lhs()->isMinMax() ? rhs() : lhs();
|
||||||
|
|
||||||
|
if (operand == other->lhs() || operand == other->rhs()) {
|
||||||
|
if (isMax() == other->isMax()) {
|
||||||
|
// min(x, min(x, y)) = min(x, y)
|
||||||
|
// max(x, max(x, y)) = max(x, y)
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
if (!IsFloatingPointType(type())) {
|
||||||
|
// When neither value is NaN:
|
||||||
|
// max(x, min(x, y)) = x
|
||||||
|
// min(x, max(x, y)) = x
|
||||||
|
|
||||||
|
// Ensure that any bailouts that we depend on to guarantee that |y| is
|
||||||
|
// Int32 are not removed.
|
||||||
|
auto* otherOp = operand == other->lhs() ? other->rhs() : other->lhs();
|
||||||
|
otherOp->setGuardRangeBailoutsUnchecked();
|
||||||
|
|
||||||
|
return operand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lhs()->isConstant() && !rhs()->isConstant()) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
// Directly apply math utility to compare the rhs() and lhs() when
|
// Directly apply math utility to compare the rhs() and lhs() when
|
||||||
// they are both constants.
|
// they are both constants.
|
||||||
if (lhs()->isConstant() && rhs()->isConstant()) {
|
if (lhs()->isConstant() && rhs()->isConstant()) {
|
||||||
|
Loading…
Reference in New Issue
Block a user