mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 943303 - IonMonkey: Convert floating-point comparisons to integer using range analysis. r=nbp
This commit is contained in:
parent
209e679b9b
commit
9fe7d6389b
@ -2308,6 +2308,8 @@ class MCompare
|
||||
|
||||
void trySpecializeFloat32(TempAllocator &alloc);
|
||||
bool isFloat32Commutative() const { return true; }
|
||||
bool truncate();
|
||||
bool isOperandTruncated(size_t index) const;
|
||||
|
||||
# ifdef DEBUG
|
||||
bool isConsistentFloat32Use() const {
|
||||
|
@ -2327,16 +2327,45 @@ MStoreTypedArrayElementStatic::isOperandTruncated(size_t index) const
|
||||
return index == 1 && !isFloatArray();
|
||||
}
|
||||
|
||||
bool
|
||||
MCompare::truncate()
|
||||
{
|
||||
if (!isDoubleComparison())
|
||||
return false;
|
||||
|
||||
// If both operands are naturally in the int32 range, we can convert from
|
||||
// a double comparison to being an int32 comparison.
|
||||
if (!Range(lhs()).isInt32() || !Range(rhs()).isInt32())
|
||||
return false;
|
||||
|
||||
compareType_ = Compare_Int32;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MCompare::isOperandTruncated(size_t index) const
|
||||
{
|
||||
return compareType() == Compare_Int32;
|
||||
}
|
||||
|
||||
// Ensure that all observables uses can work with a truncated
|
||||
// version of the |candidate|'s result.
|
||||
static bool
|
||||
AllUsesTruncate(MInstruction *candidate)
|
||||
{
|
||||
// If the value naturally produces an int32 value (before bailout checks)
|
||||
// that needs no conversion, we don't have to worry about resume points
|
||||
// seeing truncated values.
|
||||
bool needsConversion = !candidate->range() || !candidate->range()->isInt32();
|
||||
|
||||
for (MUseIterator use(candidate->usesBegin()); use != candidate->usesEnd(); use++) {
|
||||
if (!use->consumer()->isDefinition()) {
|
||||
// We can only skip testing resume points, if all original uses are still present.
|
||||
// Only than testing all uses is enough to guarantee the truncation isn't observerable.
|
||||
if (candidate->isUseRemoved())
|
||||
// We can only skip testing resume points, if all original uses are
|
||||
// still present, or if the value does not need conversion.
|
||||
// Otherwise a branch removed by UCE might rely on the non-truncated
|
||||
// value, and any bailout with a truncated value might lead an
|
||||
// incorrect value.
|
||||
if (candidate->isUseRemoved() && needsConversion)
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
@ -2348,9 +2377,40 @@ AllUsesTruncate(MInstruction *candidate)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
CanTruncate(MInstruction *candidate)
|
||||
{
|
||||
// Compare operations might coerce its inputs to int32 if the ranges are
|
||||
// correct. So we do not need to check if all uses are coerced.
|
||||
if (candidate->isCompare())
|
||||
return true;
|
||||
|
||||
// Set truncated flag if range analysis ensure that it has no
|
||||
// rounding errors and no fractional part. Note that we can't use
|
||||
// the MDefinition Range constructor, because we need to know if
|
||||
// the value will have rounding errors before any bailout checks.
|
||||
const Range *r = candidate->range();
|
||||
bool canHaveRoundingErrors = !r || r->canHaveRoundingErrors();
|
||||
|
||||
// Special case integer division: the result of a/b can be infinite
|
||||
// but cannot actually have rounding errors induced by truncation.
|
||||
if (candidate->isDiv() && candidate->toDiv()->specialization() == MIRType_Int32)
|
||||
canHaveRoundingErrors = false;
|
||||
|
||||
if (canHaveRoundingErrors)
|
||||
return false;
|
||||
|
||||
// Ensure all observable uses are truncated.
|
||||
return AllUsesTruncate(candidate);
|
||||
}
|
||||
|
||||
static void
|
||||
RemoveTruncatesOnOutput(MInstruction *truncated)
|
||||
{
|
||||
// Compare returns a boolean so it doen't have any output truncates.
|
||||
if (truncated->isCompare())
|
||||
return;
|
||||
|
||||
JS_ASSERT(truncated->type() == MIRType_Int32);
|
||||
JS_ASSERT(Range(truncated).isInt32());
|
||||
|
||||
@ -2370,12 +2430,19 @@ AdjustTruncatedInputs(TempAllocator &alloc, MInstruction *truncated)
|
||||
for (size_t i = 0, e = truncated->numOperands(); i < e; i++) {
|
||||
if (!truncated->isOperandTruncated(i))
|
||||
continue;
|
||||
if (truncated->getOperand(i)->type() == MIRType_Int32)
|
||||
|
||||
MDefinition *input = truncated->getOperand(i);
|
||||
if (input->type() == MIRType_Int32)
|
||||
continue;
|
||||
|
||||
MTruncateToInt32 *op = MTruncateToInt32::New(alloc, truncated->getOperand(i));
|
||||
block->insertBefore(truncated, op);
|
||||
truncated->replaceOperand(i, op);
|
||||
if (input->isToDouble() && input->getOperand(0)->type() == MIRType_Int32) {
|
||||
JS_ASSERT(input->range()->isInt32());
|
||||
truncated->replaceOperand(i, input->getOperand(0));
|
||||
} else {
|
||||
MTruncateToInt32 *op = MTruncateToInt32::New(alloc, truncated->getOperand(i));
|
||||
block->insertBefore(truncated, op);
|
||||
truncated->replaceOperand(i, op);
|
||||
}
|
||||
}
|
||||
|
||||
if (truncated->isToDouble()) {
|
||||
@ -2421,23 +2488,7 @@ RangeAnalysis::truncate()
|
||||
default:;
|
||||
}
|
||||
|
||||
// Set truncated flag if range analysis ensure that it has no
|
||||
// rounding errors and no fractional part. Note that we can't use
|
||||
// the MDefinition Range constructor, because we need to know if
|
||||
// the value will have rounding errors before any bailout checks.
|
||||
const Range *r = iter->range();
|
||||
bool canHaveRoundingErrors = !r || r->canHaveRoundingErrors();
|
||||
|
||||
// Special case integer division: the result of a/b can be infinite
|
||||
// but cannot actually have rounding errors induced by truncation.
|
||||
if (iter->isDiv() && iter->toDiv()->specialization() == MIRType_Int32)
|
||||
canHaveRoundingErrors = false;
|
||||
|
||||
if (canHaveRoundingErrors)
|
||||
continue;
|
||||
|
||||
// Ensure all observable uses are truncated.
|
||||
if (!AllUsesTruncate(*iter))
|
||||
if (!CanTruncate(*iter))
|
||||
continue;
|
||||
|
||||
// Truncate this instruction if possible.
|
||||
|
Loading…
Reference in New Issue
Block a user