mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-04 16:15:25 +00:00
Bug 829277: Limit the number of instructions that the truncation optimization can work on. (r=dvander)
This commit is contained in:
parent
852f5abcdc
commit
0a9b951217
@ -61,9 +61,12 @@ EdgeCaseAnalysis::analyzeEarly()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
int
|
||||
EdgeCaseAnalysis::AllUsesTruncate(MInstruction *m)
|
||||
{
|
||||
// If all uses truncate, the return value must be at least 1. If anything doesn't truncate
|
||||
// 0 is explicitly returned.
|
||||
int ret = 1;
|
||||
for (MUseIterator use = m->usesBegin(); use != m->usesEnd(); use++) {
|
||||
// See #809485 why this is allowed
|
||||
if (use->node()->isResumePoint())
|
||||
@ -84,12 +87,16 @@ EdgeCaseAnalysis::AllUsesTruncate(MInstruction *m)
|
||||
continue;
|
||||
if (def->isBitNot())
|
||||
continue;
|
||||
if (def->isAdd() && def->toAdd()->isTruncated())
|
||||
if (def->isAdd() && def->toAdd()->isTruncated()) {
|
||||
ret = Max(ret, def->toAdd()->isTruncated() + 1);
|
||||
continue;
|
||||
if (def->isSub() && def->toSub()->isTruncated())
|
||||
}
|
||||
if (def->isSub() && def->toSub()->isTruncated()) {
|
||||
ret = Max(ret, def->toSub()->isTruncated() + 1);
|
||||
continue;
|
||||
}
|
||||
// cannot use divide, since |truncate(int32(x/y) + int32(a/b)) != truncate(x/y+a/b)|
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ class EdgeCaseAnalysis
|
||||
EdgeCaseAnalysis(MIRGenerator *mir, MIRGraph &graph);
|
||||
bool analyzeEarly();
|
||||
bool analyzeLate();
|
||||
static bool AllUsesTruncate(MInstruction *m);
|
||||
static int AllUsesTruncate(MInstruction *m);
|
||||
};
|
||||
|
||||
|
||||
|
@ -818,8 +818,8 @@ MDiv::analyzeEdgeCasesBackward()
|
||||
void
|
||||
MDiv::analyzeTruncateBackward()
|
||||
{
|
||||
if (!isTruncated() && js::ion::EdgeCaseAnalysis::AllUsesTruncate(this))
|
||||
setTruncated(true);
|
||||
if (!isTruncated())
|
||||
setTruncated(js::ion::EdgeCaseAnalysis::AllUsesTruncate(this));
|
||||
}
|
||||
|
||||
bool
|
||||
@ -829,7 +829,8 @@ MDiv::updateForReplacement(MDefinition *ins_)
|
||||
MDiv *ins = ins_->toDiv();
|
||||
// Since EdgeCaseAnalysis is not being run before GVN, its information does
|
||||
// not need to be merged here.
|
||||
setTruncated(isTruncated() && ins->isTruncated());
|
||||
if (isTruncated())
|
||||
setTruncated(Max(isTruncated(), ins->isTruncated()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -856,8 +857,8 @@ MMod::foldsTo(bool useValueNumbers)
|
||||
void
|
||||
MAdd::analyzeTruncateBackward()
|
||||
{
|
||||
if (!isTruncated() && js::ion::EdgeCaseAnalysis::AllUsesTruncate(this))
|
||||
setTruncated(true);
|
||||
if (!isTruncated())
|
||||
setTruncated(js::ion::EdgeCaseAnalysis::AllUsesTruncate(this));
|
||||
}
|
||||
|
||||
bool
|
||||
@ -865,21 +866,29 @@ MAdd::updateForReplacement(MDefinition *ins_)
|
||||
{
|
||||
JS_ASSERT(ins_->isAdd());
|
||||
MAdd *ins = ins_->toAdd();
|
||||
setTruncated(isTruncated() && ins->isTruncated());
|
||||
if (isTruncated())
|
||||
setTruncated(Max(isTruncated(), ins->isTruncated()));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MAdd::fallible()
|
||||
{
|
||||
return !isTruncated() && (!range() || !range()->isFinite());
|
||||
// the add is fallible if range analysis does not say that it is finite, AND
|
||||
// either the truncation analysis shows that there are non-truncated uses, or
|
||||
// there are more than 20 operations before it gets truncated. 20 was chosen
|
||||
// for two reasons. First, it is a nice sane number. Second, the largest int32
|
||||
// can be (about) 2^31. The smallest integer that cannot be exactly represented
|
||||
// as a double is 2^53 + 1 by doing something simple, like x = x + x, it takes
|
||||
// 23 additions toget from 2^31 to 2^53 + 1. 20 is simply a conservative estimate of that.
|
||||
return (!isTruncated() || isTruncated() > 20) && (!range() || !range()->isFinite());
|
||||
}
|
||||
|
||||
void
|
||||
MSub::analyzeTruncateBackward()
|
||||
{
|
||||
if (!isTruncated() && js::ion::EdgeCaseAnalysis::AllUsesTruncate(this))
|
||||
setTruncated(true);
|
||||
if (!isTruncated())
|
||||
setTruncated(js::ion::EdgeCaseAnalysis::AllUsesTruncate(this));
|
||||
}
|
||||
|
||||
bool
|
||||
@ -887,14 +896,16 @@ MSub::updateForReplacement(MDefinition *ins_)
|
||||
{
|
||||
JS_ASSERT(ins_->isSub());
|
||||
MSub *ins = ins_->toSub();
|
||||
setTruncated(isTruncated() && ins->isTruncated());
|
||||
if (isTruncated())
|
||||
setTruncated(Max(isTruncated(), ins->isTruncated()));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MSub::fallible()
|
||||
{
|
||||
return !isTruncated() && (!range() || !range()->isFinite());
|
||||
// see comment in MAdd::fallible()
|
||||
return (!isTruncated() || isTruncated() > 20) && (!range() || !range()->isFinite());
|
||||
}
|
||||
|
||||
MDefinition *
|
||||
|
@ -2559,11 +2559,11 @@ class MMathFunction
|
||||
|
||||
class MAdd : public MBinaryArithInstruction
|
||||
{
|
||||
bool implicitTruncate_;
|
||||
int implicitTruncate_;
|
||||
|
||||
MAdd(MDefinition *left, MDefinition *right)
|
||||
: MBinaryArithInstruction(left, right),
|
||||
implicitTruncate_(false)
|
||||
implicitTruncate_(0)
|
||||
{
|
||||
setResultType(MIRType_Value);
|
||||
}
|
||||
@ -2575,10 +2575,10 @@ class MAdd : public MBinaryArithInstruction
|
||||
}
|
||||
void analyzeTruncateBackward();
|
||||
|
||||
bool isTruncated() const {
|
||||
int isTruncated() const {
|
||||
return implicitTruncate_;
|
||||
}
|
||||
void setTruncated(bool truncate) {
|
||||
void setTruncated(int truncate) {
|
||||
implicitTruncate_ = truncate;
|
||||
}
|
||||
bool updateForReplacement(MDefinition *ins);
|
||||
@ -2592,7 +2592,7 @@ class MAdd : public MBinaryArithInstruction
|
||||
|
||||
class MSub : public MBinaryArithInstruction
|
||||
{
|
||||
bool implicitTruncate_;
|
||||
int implicitTruncate_;
|
||||
MSub(MDefinition *left, MDefinition *right)
|
||||
: MBinaryArithInstruction(left, right),
|
||||
implicitTruncate_(false)
|
||||
@ -2607,10 +2607,10 @@ class MSub : public MBinaryArithInstruction
|
||||
}
|
||||
|
||||
void analyzeTruncateBackward();
|
||||
bool isTruncated() const {
|
||||
int isTruncated() const {
|
||||
return implicitTruncate_;
|
||||
}
|
||||
void setTruncated(bool truncate) {
|
||||
void setTruncated(int truncate) {
|
||||
implicitTruncate_ = truncate;
|
||||
}
|
||||
bool updateForReplacement(MDefinition *ins);
|
||||
@ -2725,7 +2725,7 @@ class MDiv : public MBinaryArithInstruction
|
||||
bool canBeNegativeZero_;
|
||||
bool canBeNegativeOverflow_;
|
||||
bool canBeDivideByZero_;
|
||||
bool implicitTruncate_;
|
||||
int implicitTruncate_;
|
||||
|
||||
MDiv(MDefinition *left, MDefinition *right, MIRType type)
|
||||
: MBinaryArithInstruction(left, right),
|
||||
@ -2759,10 +2759,10 @@ class MDiv : public MBinaryArithInstruction
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool isTruncated() const {
|
||||
int isTruncated() const {
|
||||
return implicitTruncate_;
|
||||
}
|
||||
void setTruncated(bool truncate) {
|
||||
void setTruncated(int truncate) {
|
||||
implicitTruncate_ = truncate;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user