Bug 1054972 - IonMonkey: Truncation for phis r=nbp

This commit is contained in:
Dan Gohman 2014-09-02 13:01:31 -07:00
parent d81de203d4
commit 1249756aa3
2 changed files with 65 additions and 17 deletions

View File

@ -5781,6 +5781,7 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineListNode<MPhi>
{
js::Vector<MUse, 2, IonAllocPolicy> inputs_;
TruncateKind truncateKind_;
bool hasBackedgeType_;
bool triedToSpecialize_;
bool isIterator_;
@ -5810,6 +5811,7 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineListNode<MPhi>
MPhi(TempAllocator &alloc, MIRType resultType)
: inputs_(alloc),
truncateKind_(NoTruncate),
hasBackedgeType_(false),
triedToSpecialize_(false),
isIterator_(false),
@ -5929,6 +5931,9 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineListNode<MPhi>
void setCanConsumeFloat32(bool can) {
canConsumeFloat32_ = can;
}
TruncateKind operandTruncateKind(size_t index) const;
bool truncate(TruncateKind kind);
};
// The goal of a Beta node is to split a def at a conditionally taken

View File

@ -2163,6 +2163,20 @@ MConstant::truncate(TruncateKind kind)
return true;
}
bool
MPhi::truncate(TruncateKind kind)
{
if (type() == MIRType_Double || type() == MIRType_Int32) {
truncateKind_ = kind;
setResultType(MIRType_Int32);
if (kind >= IndirectTruncate && range())
range()->wrapAroundToInt32();
return true;
}
return false;
}
bool
MAdd::truncate(TruncateKind kind)
{
@ -2302,6 +2316,14 @@ MDefinition::operandTruncateKind(size_t index) const
return NoTruncate;
}
MDefinition::TruncateKind
MPhi::operandTruncateKind(size_t index) const
{
// The truncation applied to a phi is effectively applied to the phi's
// operands.
return truncateKind_;
}
MDefinition::TruncateKind
MTruncateToInt32::operandTruncateKind(size_t index) const
{
@ -2460,7 +2482,7 @@ TruncateTest(TempAllocator &alloc, MTest *test)
// Examine all the users of |candidate| and determine the most aggressive
// truncate kind that satisfies all of them.
static MDefinition::TruncateKind
ComputeRequestedTruncateKind(MInstruction *candidate)
ComputeRequestedTruncateKind(MDefinition *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
@ -2491,7 +2513,7 @@ ComputeRequestedTruncateKind(MInstruction *candidate)
}
static MDefinition::TruncateKind
ComputeTruncateKind(MInstruction *candidate)
ComputeTruncateKind(MDefinition *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.
@ -2518,7 +2540,7 @@ ComputeTruncateKind(MInstruction *candidate)
}
static void
RemoveTruncatesOnOutput(MInstruction *truncated)
RemoveTruncatesOnOutput(MDefinition *truncated)
{
// Compare returns a boolean so it doen't have any output truncates.
if (truncated->isCompare())
@ -2537,7 +2559,7 @@ RemoveTruncatesOnOutput(MInstruction *truncated)
}
static void
AdjustTruncatedInputs(TempAllocator &alloc, MInstruction *truncated)
AdjustTruncatedInputs(TempAllocator &alloc, MDefinition *truncated)
{
MBasicBlock *block = truncated->block();
for (size_t i = 0, e = truncated->numOperands(); i < e; i++) {
@ -2552,20 +2574,26 @@ AdjustTruncatedInputs(TempAllocator &alloc, MInstruction *truncated)
if (input->isToDouble() && input->getOperand(0)->type() == MIRType_Int32) {
JS_ASSERT(input->range()->isInt32());
truncated->replaceOperand(i, input->getOperand(0));
} else if (kind == MDefinition::TruncateAfterBailouts) {
MToInt32 *op = MToInt32::New(alloc, truncated->getOperand(i));
block->insertBefore(truncated, op);
truncated->replaceOperand(i, op);
} else {
MTruncateToInt32 *op = MTruncateToInt32::New(alloc, truncated->getOperand(i));
block->insertBefore(truncated, op);
MInstruction *op;
if (kind == MDefinition::TruncateAfterBailouts)
op = MToInt32::New(alloc, truncated->getOperand(i));
else
op = MTruncateToInt32::New(alloc, truncated->getOperand(i));
if (truncated->isPhi()) {
MBasicBlock *pred = op->block()->getPredecessor(i);
pred->insertBefore(pred->lastIns(), op);
} else {
block->insertBefore(truncated->toInstruction(), op);
}
truncated->replaceOperand(i, op);
}
}
if (truncated->isToDouble()) {
truncated->replaceAllUsesWith(truncated->getOperand(0));
block->discard(truncated);
truncated->replaceAllUsesWith(truncated->toToDouble()->getOperand(0));
block->discard(truncated->toToDouble());
}
}
@ -2591,7 +2619,7 @@ RangeAnalysis::truncate()
// any automatic truncations.
MOZ_ASSERT(!mir->compilingAsmJS());
Vector<MInstruction *, 16, SystemAllocPolicy> worklist;
Vector<MDefinition *, 16, SystemAllocPolicy> worklist;
Vector<MBinaryBitwiseInstruction *, 16, SystemAllocPolicy> bitops;
for (PostorderIterator block(graph_.poBegin()); block != graph_.poEnd(); block++) {
@ -2629,15 +2657,30 @@ RangeAnalysis::truncate()
if (!worklist.append(*iter))
return false;
}
for (MPhiIterator iter(block->phisBegin()), end(block->phisEnd()); iter != end; ++iter) {
MDefinition::TruncateKind kind = ComputeTruncateKind(*iter);
if (kind == MDefinition::NoTruncate)
continue;
// Truncate this phi if possible.
if (!iter->truncate(kind))
continue;
// Delay updates of inputs/outputs to avoid creating node which
// would be removed by the truncation of the next operations.
iter->setInWorklist();
if (!worklist.append(*iter))
return false;
}
}
// Update inputs/outputs of truncated instructions.
JitSpew(JitSpew_Range, "Do graph type fixup (dequeue)");
while (!worklist.empty()) {
MInstruction *ins = worklist.popCopy();
ins->setNotInWorklist();
RemoveTruncatesOnOutput(ins);
AdjustTruncatedInputs(alloc(), ins);
MDefinition *def = worklist.popCopy();
def->setNotInWorklist();
RemoveTruncatesOnOutput(def);
AdjustTruncatedInputs(alloc(), def);
}
// Fold any unnecessary bitops in the graph, such as (x | 0) on an integer