mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 07:15:46 +00:00
Bug 1302367
- Use unsigned integer modulo instead of ModD opcode. r=nbp, r=jandem
--HG-- extra : rebase_source : 63337ef0e28137e69e7d7894cb21dcc5c3300c5e
This commit is contained in:
parent
299f264eae
commit
acb9b45ad4
@ -2736,6 +2736,20 @@ MBinaryBitwiseInstruction::foldsTo(TempAllocator& alloc)
|
||||
MDefinition*
|
||||
MBinaryBitwiseInstruction::foldUnnecessaryBitop()
|
||||
{
|
||||
// Fold unsigned shift right operator when the second operand is zero and
|
||||
// the only use is an unsigned modulo. Thus, the expression
|
||||
// |(x >>> 0) % y| becomes |x % y|.
|
||||
if (isUrsh() && hasOneDefUse() && getOperand(1)->isConstant()) {
|
||||
MConstant* constant = getOperand(1)->toConstant();
|
||||
if (constant->type() == MIRType::Int32 && constant->toInt32() == 0) {
|
||||
for (MUseDefIterator use(this); use; use++) {
|
||||
if (use.def()->isMod() && use.def()->toMod()->isUnsigned())
|
||||
return getOperand(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (specialization_ != MIRType::Int32)
|
||||
return this;
|
||||
|
||||
|
@ -7139,23 +7139,51 @@ class MDiv : public MBinaryArithInstruction
|
||||
|
||||
class MMod : public MBinaryArithInstruction
|
||||
{
|
||||
public:
|
||||
enum class PossiblyUnsigned {
|
||||
NotPossible,
|
||||
LHSPossible,
|
||||
RHSPossible,
|
||||
BothPossible,
|
||||
};
|
||||
|
||||
protected:
|
||||
bool unsigned_;
|
||||
bool canBeNegativeDividend_;
|
||||
bool canBePowerOfTwoDivisor_;
|
||||
bool canBeDivideByZero_;
|
||||
bool trapOnError_;
|
||||
|
||||
PossiblyUnsigned possiblyUnsigned_;
|
||||
|
||||
MMod(MDefinition* left, MDefinition* right, MIRType type)
|
||||
: MBinaryArithInstruction(left, right),
|
||||
unsigned_(false),
|
||||
canBeNegativeDividend_(true),
|
||||
canBePowerOfTwoDivisor_(true),
|
||||
canBeDivideByZero_(true),
|
||||
trapOnError_(false)
|
||||
trapOnError_(false),
|
||||
possiblyUnsigned_(PossiblyUnsigned::NotPossible)
|
||||
{
|
||||
if (type != MIRType::Value)
|
||||
specialization_ = type;
|
||||
setResultType(type);
|
||||
|
||||
if (left->isUrsh() && left->getOperand(1)->isConstant()) {
|
||||
MConstant* constant = left->getOperand(1)->toConstant();
|
||||
if (constant->type() == MIRType::Int32 && constant->toInt32() == 0)
|
||||
possiblyUnsigned_ = PossiblyUnsigned::LHSPossible;
|
||||
}
|
||||
|
||||
if (right->isUrsh() && right->getOperand(1)->isConstant()) {
|
||||
MConstant* constant = right->getOperand(1)->toConstant();
|
||||
if (constant->type() == MIRType::Int32 && constant->toInt32() == 0) {
|
||||
if (possiblyUnsigned_ == PossiblyUnsigned::NotPossible)
|
||||
possiblyUnsigned_ = PossiblyUnsigned::RHSPossible;
|
||||
else
|
||||
possiblyUnsigned_ = PossiblyUnsigned::BothPossible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -1561,13 +1561,40 @@ MMod::computeRange(TempAllocator& alloc)
|
||||
|
||||
// If either operand is a NaN, the result is NaN. This also conservatively
|
||||
// handles Infinity cases.
|
||||
if (!lhs.hasInt32Bounds() || !rhs.hasInt32Bounds())
|
||||
if ((possiblyUnsigned_ == PossiblyUnsigned::NotPossible &&
|
||||
!lhs.hasInt32Bounds()) || !rhs.hasInt32Bounds())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If RHS can be zero, the result can be NaN.
|
||||
if (rhs.lower() <= 0 && rhs.upper() >= 0)
|
||||
return;
|
||||
|
||||
// (x >>> 0) % y is an unsigned modulo operation but the lhs' range is not
|
||||
// always >= 0. The lhs range assumes a signed integer 32 bit while the
|
||||
// value is unsigned 32 bit. That breaks the assumption that range >= 0.
|
||||
if (specialization() == MIRType::Int32) {
|
||||
switch (possiblyUnsigned_) {
|
||||
case PossiblyUnsigned::NotPossible:
|
||||
break;
|
||||
case PossiblyUnsigned::LHSPossible:
|
||||
if (rhs.lower() > 0 && !rhs.canHaveFractionalPart())
|
||||
unsigned_ = true;
|
||||
break;
|
||||
case PossiblyUnsigned::RHSPossible:
|
||||
if (lhs.lower() >= 0 && !lhs.canHaveFractionalPart())
|
||||
unsigned_ = true;
|
||||
break;
|
||||
case PossiblyUnsigned::BothPossible:
|
||||
if (lhs.lower() >= 0 && !lhs.canHaveFractionalPart())
|
||||
unsigned_ = true;
|
||||
else if (rhs.lower() > 0 && !rhs.canHaveFractionalPart())
|
||||
unsigned_ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If both operands are non-negative integers, we can optimize this to an
|
||||
// unsigned mod.
|
||||
if (specialization() == MIRType::Int32 && lhs.lower() >= 0 && rhs.lower() > 0 &&
|
||||
|
Loading…
Reference in New Issue
Block a user