mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1054972 - IonMonkey: Truncation for phis r=nbp
This commit is contained in:
parent
d81de203d4
commit
1249756aa3
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user