Bug 882565 - IonMonkey: Only skip resumepoints during truncation when no uses where removed, r=jandem

This commit is contained in:
Hannes Verschore 2013-06-15 17:05:02 +02:00
parent 369796db84
commit 92908d5e06
6 changed files with 61 additions and 10 deletions

View File

@ -324,6 +324,9 @@ MDefinition::replaceAllUsesWith(MDefinition *dom)
if (dom == this)
return;
for (size_t i = 0; i < numOperands(); i++)
getOperand(i)->setUseRemovedUnchecked();
for (MUseIterator i(usesBegin()); i != usesEnd(); ) {
JS_ASSERT(i->producer() == this);
i = i->consumer()->replaceOperand(i, dom);

View File

@ -54,7 +54,20 @@ MIRType MIRTypeFromValue(const js::Value &vp)
* points.
*/ \
_(Unused) \
_(DOMFunction) /* Contains or uses a common DOM method function */
_(DOMFunction) /* Contains or uses a common DOM method function */ \
\
/* Marks if an instruction has fewer uses than the original code.
* E.g. UCE can remove code.
* Every instruction where an use is/was removed from an instruction and
* as a result the number of operands doesn't equal the original code
* need to get marked as UseRemoved. This is important for truncation
* analysis to know, since if all original uses are still present,
* it can ignore resumepoints.
* Currently this is done for every pass after IonBuilder and before
* Truncate Doubles. So every time removeUse is called, UseRemoved needs
* to get set.
*/ \
_(UseRemoved)
class MDefinition;
class MInstruction;

View File

@ -1403,13 +1403,21 @@ MToDouble::isOperandTruncated(size_t index) const
return type() == MIRType_Int32;
}
// Ensure that all observables (non-resume point) uses can work with a truncated
// Ensure that all observables uses can work with a truncated
// version of the |candidate|'s result.
static bool
AllUsesTruncate(MInstruction *candidate)
{
for (MUseDefIterator use(candidate); use; use++) {
if (!use.def()->isOperandTruncated(use.index()))
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())
return false;
continue;
}
if (!use->consumer()->toDefinition()->isOperandTruncated(use->index()))
return false;
}

View File

@ -157,11 +157,13 @@ UnreachableCodeElimination::checkDependencyAndRemoveUsesFromUnmarkedBlocks(MDefi
rerunAliasAnalysis_ = true;
for (MUseIterator iter(instr->usesBegin()); iter != instr->usesEnd(); ) {
if (!iter->consumer()->block()->isMarked())
if (!iter->consumer()->block()->isMarked()) {
instr->setUseRemovedUnchecked();
iter = instr->removeUse(iter);
else
} else {
iter++;
}
}
}
bool
@ -235,10 +237,10 @@ UnreachableCodeElimination::removeUnmarkedBlocksAndClearDominators()
}
}
// When we remove a call, we can't leave the corresponding MPassArg in the graph.
// Since lowering will fail. Replace it with the argument for the exceptional
// case when it is kept alive in a ResumePoint.
// DCE will remove the unused MPassArg instruction.
// When we remove a call, we can't leave the corresponding MPassArg
// in the graph. Since lowering will fail. Replace it with the
// argument for the exceptional case when it is kept alive in a
// ResumePoint. DCE will remove the unused MPassArg instruction.
for (MInstructionIterator iter(block->begin()); iter != block->end(); iter++) {
if (iter->isCall()) {
MCall *call = iter->toCall();

View File

@ -0,0 +1,21 @@
function zero() { return 0; }
function f(x, a) {
var test = 0x7fffffff;
for (var i=0; i<100; i++)
{
if (i == 0) {
test += 1;
var t = (test > zero()) * (0xffffffff >>> x);
}
var test2 = test | 0;
return [test2,t];
}
}
var t = f(0, "");
assertEq(t[0], 0x80000000 | 0);
assertEq(t[1], 0xffffffff >>> 0);
var t = f(0);
assertEq(t[0], 0x80000000 | 0);
assertEq(t[1], 0xffffffff >>> 0);

View File

@ -0,0 +1,4 @@
function zero() { return 0; }
function f(x) { return (0xffffffff > zero()) * (0xffffffff >>> x); }
assertEq(f(0), 4294967295);
assertEq(f(0), 4294967295);