зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1122402 - Flag fallible instructions as guards if used by UCE. r=sunfish
This commit is contained in:
Родитель
410ac1f6e2
Коммит
d6db7cbeca
|
@ -0,0 +1,11 @@
|
||||||
|
// |jit-test| error:TypeError
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
let r
|
||||||
|
g = function(x) {
|
||||||
|
((-0x80000000 + (x >>> 0)) != 0) ? 0 : x()
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
|
g(NaN)
|
||||||
|
g(0x80000000);
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
function f(y) {
|
||||||
|
var x1 = Math.max(-2147483649 >> 0, y >>> 0);
|
||||||
|
var x2 = x1 | 0;
|
||||||
|
return (x2 >= 0) ? 1 : 0;
|
||||||
|
}
|
||||||
|
assertEq(f(0), 1);
|
||||||
|
assertEq(f(-1), 0);
|
|
@ -3218,6 +3218,8 @@ RangeAnalysis::prepareForUCE(bool *shouldRemoveDeadCode)
|
||||||
{
|
{
|
||||||
*shouldRemoveDeadCode = false;
|
*shouldRemoveDeadCode = false;
|
||||||
|
|
||||||
|
MDefinitionVector deadConditions(alloc());
|
||||||
|
|
||||||
for (ReversePostorderIterator iter(graph_.rpoBegin()); iter != graph_.rpoEnd(); iter++) {
|
for (ReversePostorderIterator iter(graph_.rpoBegin()); iter != graph_.rpoEnd(); iter++) {
|
||||||
MBasicBlock *block = *iter;
|
MBasicBlock *block = *iter;
|
||||||
|
|
||||||
|
@ -3232,6 +3234,7 @@ RangeAnalysis::prepareForUCE(bool *shouldRemoveDeadCode)
|
||||||
// chosen based which of the successors has the unreachable flag which is
|
// chosen based which of the successors has the unreachable flag which is
|
||||||
// added by MBeta::computeRange on its own block.
|
// added by MBeta::computeRange on its own block.
|
||||||
MTest *test = cond->toTest();
|
MTest *test = cond->toTest();
|
||||||
|
MDefinition *condition = test->input();
|
||||||
MConstant *constant = nullptr;
|
MConstant *constant = nullptr;
|
||||||
if (block == test->ifTrue()) {
|
if (block == test->ifTrue()) {
|
||||||
constant = MConstant::New(alloc(), BooleanValue(false));
|
constant = MConstant::New(alloc(), BooleanValue(false));
|
||||||
|
@ -3239,7 +3242,15 @@ RangeAnalysis::prepareForUCE(bool *shouldRemoveDeadCode)
|
||||||
MOZ_ASSERT(block == test->ifFalse());
|
MOZ_ASSERT(block == test->ifFalse());
|
||||||
constant = MConstant::New(alloc(), BooleanValue(true));
|
constant = MConstant::New(alloc(), BooleanValue(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DeadIfUnused(condition) && !condition->isInWorklist()) {
|
||||||
|
condition->setInWorklist();
|
||||||
|
if (!deadConditions.append(condition))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
test->block()->insertBefore(test, constant);
|
test->block()->insertBefore(test, constant);
|
||||||
|
|
||||||
test->replaceOperand(0, constant);
|
test->replaceOperand(0, constant);
|
||||||
JitSpew(JitSpew_Range, "Update condition of %d to reflect unreachable branches.",
|
JitSpew(JitSpew_Range, "Update condition of %d to reflect unreachable branches.",
|
||||||
test->id());
|
test->id());
|
||||||
|
@ -3247,5 +3258,55 @@ RangeAnalysis::prepareForUCE(bool *shouldRemoveDeadCode)
|
||||||
*shouldRemoveDeadCode = true;
|
*shouldRemoveDeadCode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Flag all fallible instructions which were indirectly used in the
|
||||||
|
// computation of the condition, such that we do not ignore
|
||||||
|
// bailout-paths which are used to shrink the input range of the
|
||||||
|
// operands of the condition.
|
||||||
|
for (size_t i = 0; i < deadConditions.length(); i++) {
|
||||||
|
MDefinition *cond = deadConditions[i];
|
||||||
|
|
||||||
|
// If this instruction is a guard, then there is not need to continue on
|
||||||
|
// this instruction.
|
||||||
|
if (cond->isGuard())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cond->range()) {
|
||||||
|
// Filter the range of the instruction based on its MIRType.
|
||||||
|
Range typeFilteredRange(cond);
|
||||||
|
|
||||||
|
// If the filtered range is updated by adding the original range,
|
||||||
|
// then the MIRType act as an effectful filter. As we do not know if
|
||||||
|
// this filtered Range might change or not the result of the
|
||||||
|
// previous comparison, we have to keep this instruction as a guard
|
||||||
|
// because it has to bailout in order to restrict the Range to its
|
||||||
|
// MIRType.
|
||||||
|
if (typeFilteredRange.update(cond->range())) {
|
||||||
|
cond->setGuard();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t op = 0, e = cond->numOperands(); op < e; op++) {
|
||||||
|
MDefinition *operand = cond->getOperand(op);
|
||||||
|
if (!DeadIfUnused(operand) || operand->isInWorklist())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// If the operand has no range, then its range is always infered
|
||||||
|
// from its MIRType, so it cannot be used change the result deduced
|
||||||
|
// by Range Analysis.
|
||||||
|
if (!operand->range())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
operand->setInWorklist();
|
||||||
|
if (!deadConditions.append(operand))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!deadConditions.empty()) {
|
||||||
|
MDefinition *cond = deadConditions.popCopy();
|
||||||
|
cond->setNotInWorklist();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче