зеркало из https://github.com/mozilla/gecko-dev.git
Bug 946478 - IonMonkey: Go back to just using copies to satisfy regalloc constraints for div and mod on x86/x64. r=bhackett
This commit is contained in:
Родитель
620a57d8a7
Коммит
602a4633a1
|
@ -788,14 +788,20 @@ CodeGeneratorX86Shared::visitReturnZero(ReturnZero *ool)
|
|||
bool
|
||||
CodeGeneratorX86Shared::visitUDivOrMod(LUDivOrMod *ins)
|
||||
{
|
||||
JS_ASSERT(ToRegister(ins->lhs()) == eax);
|
||||
Register lhs = ToRegister(ins->lhs());
|
||||
Register rhs = ToRegister(ins->rhs());
|
||||
Register output = ToRegister(ins->output());
|
||||
|
||||
JS_ASSERT_IF(lhs != rhs, rhs != eax);
|
||||
JS_ASSERT(rhs != edx);
|
||||
JS_ASSERT_IF(output == eax, ToRegister(ins->remainder()) == edx);
|
||||
|
||||
ReturnZero *ool = nullptr;
|
||||
|
||||
// Put the lhs in eax.
|
||||
if (lhs != eax)
|
||||
masm.mov(lhs, eax);
|
||||
|
||||
// Prevent divide by zero.
|
||||
if (ins->canBeDivideByZero()) {
|
||||
masm.testl(rhs, rhs);
|
||||
|
@ -809,6 +815,7 @@ CodeGeneratorX86Shared::visitUDivOrMod(LUDivOrMod *ins)
|
|||
}
|
||||
}
|
||||
|
||||
// Zero extend the lhs into edx to make (edx:eax), since udiv is 64-bit.
|
||||
masm.mov(ImmWord(0), edx);
|
||||
masm.udiv(rhs);
|
||||
|
||||
|
@ -892,28 +899,6 @@ CodeGeneratorX86Shared::visitDivPowTwoI(LDivPowTwoI *ins)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX86Shared::visitDivSelfI(LDivSelfI *ins)
|
||||
{
|
||||
Register op = ToRegister(ins->op());
|
||||
Register output = ToRegister(ins->output());
|
||||
MDiv *mir = ins->mir();
|
||||
|
||||
// If we can't divide by zero, lowering should have just used a constant one.
|
||||
JS_ASSERT(mir->canBeDivideByZero());
|
||||
|
||||
masm.testl(op, op);
|
||||
if (mir->isTruncated()) {
|
||||
masm.emitSet(Assembler::NonZero, output);
|
||||
} else {
|
||||
if (!bailoutIf(Assembler::Zero, ins->snapshot()))
|
||||
return false;
|
||||
masm.mov(ImmWord(1), output);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX86Shared::visitDivI(LDivI *ins)
|
||||
{
|
||||
|
@ -924,13 +909,19 @@ CodeGeneratorX86Shared::visitDivI(LDivI *ins)
|
|||
|
||||
MDiv *mir = ins->mir();
|
||||
|
||||
JS_ASSERT_IF(lhs != rhs, rhs != eax);
|
||||
JS_ASSERT(rhs != edx);
|
||||
JS_ASSERT(remainder == edx);
|
||||
JS_ASSERT(lhs == eax);
|
||||
JS_ASSERT(output == eax);
|
||||
|
||||
Label done;
|
||||
ReturnZero *ool = nullptr;
|
||||
|
||||
// Put the lhs in eax, for either the negative overflow case or the regular
|
||||
// divide case.
|
||||
if (lhs != eax)
|
||||
masm.mov(lhs, eax);
|
||||
|
||||
// Handle divide by zero.
|
||||
if (mir->canBeDivideByZero()) {
|
||||
masm.testl(rhs, rhs);
|
||||
|
@ -975,7 +966,9 @@ CodeGeneratorX86Shared::visitDivI(LDivI *ins)
|
|||
masm.bind(&nonzero);
|
||||
}
|
||||
|
||||
// Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
|
||||
// Sign extend the lhs into edx to make (edx:eax), since idiv is 64-bit.
|
||||
if (lhs != eax)
|
||||
masm.mov(lhs, eax);
|
||||
masm.cdq();
|
||||
masm.idiv(rhs);
|
||||
|
||||
|
@ -997,39 +990,6 @@ CodeGeneratorX86Shared::visitDivI(LDivI *ins)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX86Shared::visitModSelfI(LModSelfI *ins)
|
||||
{
|
||||
Register op = ToRegister(ins->op());
|
||||
Register output = ToRegister(ins->output());
|
||||
MMod *mir = ins->mir();
|
||||
|
||||
// If we're not fallible, lowering should have just used a constant zero.
|
||||
JS_ASSERT(mir->fallible());
|
||||
JS_ASSERT(mir->canBeDivideByZero() || (!mir->isUnsigned() && mir->canBeNegativeDividend()));
|
||||
|
||||
masm.testl(op, op);
|
||||
|
||||
// For a negative operand, we need to return negative zero. We can't
|
||||
// represent that as an int32, so bail if that happens.
|
||||
if (!mir->isUnsigned() && mir->canBeNegativeDividend()) {
|
||||
if (!bailoutIf(Assembler::Signed, ins->snapshot()))
|
||||
return false;
|
||||
}
|
||||
|
||||
// For a zero operand, we need to return NaN. We can't
|
||||
// represent that as an int32, so bail if that happens.
|
||||
if (mir->canBeDivideByZero()) {
|
||||
if (!bailoutIf(Assembler::Zero, ins->snapshot()))
|
||||
return false;
|
||||
}
|
||||
|
||||
// For any other value, return 0.
|
||||
masm.mov(ImmWord(0), output);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX86Shared::visitModPowTwoI(LModPowTwoI *ins)
|
||||
{
|
||||
|
@ -1114,7 +1074,8 @@ CodeGeneratorX86Shared::visitModI(LModI *ins)
|
|||
Register rhs = ToRegister(ins->rhs());
|
||||
|
||||
// Required to use idiv.
|
||||
JS_ASSERT(lhs == eax);
|
||||
JS_ASSERT_IF(lhs != rhs, rhs != eax);
|
||||
JS_ASSERT(rhs != edx);
|
||||
JS_ASSERT(remainder == edx);
|
||||
JS_ASSERT(ToRegister(ins->getTemp(0)) == eax);
|
||||
|
||||
|
@ -1122,6 +1083,10 @@ CodeGeneratorX86Shared::visitModI(LModI *ins)
|
|||
ReturnZero *ool = nullptr;
|
||||
ModOverflowCheck *overflow = nullptr;
|
||||
|
||||
// Set up eax in preparation for doing a div.
|
||||
if (lhs != eax)
|
||||
masm.mov(lhs, eax);
|
||||
|
||||
// Prevent divide by zero.
|
||||
if (ins->mir()->canBeDivideByZero()) {
|
||||
masm.testl(rhs, rhs);
|
||||
|
|
|
@ -91,10 +91,8 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
|
|||
virtual bool visitMulI(LMulI *ins);
|
||||
virtual bool visitDivI(LDivI *ins);
|
||||
virtual bool visitDivPowTwoI(LDivPowTwoI *ins);
|
||||
virtual bool visitDivSelfI(LDivSelfI *ins);
|
||||
virtual bool visitModI(LModI *ins);
|
||||
virtual bool visitModPowTwoI(LModPowTwoI *ins);
|
||||
virtual bool visitModSelfI(LModSelfI *ins);
|
||||
virtual bool visitBitNotI(LBitNotI *ins);
|
||||
virtual bool visitBitOpI(LBitOpI *ins);
|
||||
virtual bool visitShiftI(LShiftI *ins);
|
||||
|
|
|
@ -72,25 +72,6 @@ class LDivPowTwoI : public LBinaryMath<0>
|
|||
}
|
||||
};
|
||||
|
||||
// Division of a number by itself. Returns 1 unless the number is zero.
|
||||
class LDivSelfI : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(DivSelfI)
|
||||
|
||||
LDivSelfI(const LAllocation &op) {
|
||||
setOperand(0, op);
|
||||
}
|
||||
|
||||
const LAllocation *op() {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
MDiv *mir() const {
|
||||
return mir_->toDiv();
|
||||
}
|
||||
};
|
||||
|
||||
class LModI : public LBinaryMath<1>
|
||||
{
|
||||
public:
|
||||
|
@ -114,25 +95,6 @@ class LModI : public LBinaryMath<1>
|
|||
}
|
||||
};
|
||||
|
||||
// Modulo of a number by itself. Returns 0 unless the number is zero.
|
||||
class LModSelfI : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(ModSelfI)
|
||||
|
||||
LModSelfI(const LAllocation &op) {
|
||||
setOperand(0, op);
|
||||
}
|
||||
|
||||
const LAllocation *op() {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
MMod *mir() const {
|
||||
return mir_->toMod();
|
||||
}
|
||||
};
|
||||
|
||||
// This class performs a simple x86 'div', yielding either a quotient or remainder depending on
|
||||
// whether this instruction is defined to output eax (quotient) or edx (remainder).
|
||||
class LUDivOrMod : public LBinaryMath<1>
|
||||
|
|
|
@ -160,24 +160,8 @@ LIRGeneratorX86Shared::lowerDivI(MDiv *div)
|
|||
}
|
||||
}
|
||||
|
||||
// Optimize x/x. This is quaint, but it also protects the LDivI code below.
|
||||
// Since LDivI requires lhs to be in %eax, and since the register allocator
|
||||
// can't put a virtual register in two physical registers at the same time,
|
||||
// this puts rhs in %eax too, and since rhs isn't marked usedAtStart, it
|
||||
// would conflict with the %eax output register. (rhs could be marked
|
||||
// usedAtStart but for the fact that LDivI clobbers %edx early and rhs could
|
||||
// happen to be in %edx).
|
||||
if (div->lhs() == div->rhs()) {
|
||||
if (!div->canBeDivideByZero())
|
||||
return define(new(alloc()) LInteger(1), div);
|
||||
|
||||
LDivSelfI *lir = new(alloc()) LDivSelfI(useRegisterAtStart(div->lhs()));
|
||||
if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return define(lir, div);
|
||||
}
|
||||
|
||||
LDivI *lir = new(alloc()) LDivI(useFixed(div->lhs(), eax), useRegister(div->rhs()), tempFixed(edx));
|
||||
LDivI *lir = new(alloc()) LDivI(useRegister(div->lhs()), useRegister(div->rhs()),
|
||||
tempFixed(edx));
|
||||
if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return defineFixed(lir, div, LAllocation(AnyRegister(eax)));
|
||||
|
@ -200,20 +184,7 @@ LIRGeneratorX86Shared::lowerModI(MMod *mod)
|
|||
}
|
||||
}
|
||||
|
||||
// Optimize x%x. The comments in lowerDivI apply here as well, except
|
||||
// that we return 0 for all cases except when x is 0 and we're not
|
||||
// truncated.
|
||||
if (mod->rhs() == mod->lhs()) {
|
||||
if (mod->isTruncated())
|
||||
return define(new(alloc()) LInteger(0), mod);
|
||||
|
||||
LModSelfI *lir = new(alloc()) LModSelfI(useRegisterAtStart(mod->lhs()));
|
||||
if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return define(lir, mod);
|
||||
}
|
||||
|
||||
LModI *lir = new(alloc()) LModI(useFixedAtStart(mod->lhs(), eax),
|
||||
LModI *lir = new(alloc()) LModI(useRegister(mod->lhs()),
|
||||
useRegister(mod->rhs()),
|
||||
tempFixed(eax));
|
||||
if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
|
@ -237,18 +208,7 @@ LIRGeneratorX86Shared::visitAsmJSNeg(MAsmJSNeg *ins)
|
|||
bool
|
||||
LIRGeneratorX86Shared::lowerUDiv(MDiv *div)
|
||||
{
|
||||
// Optimize x/x. The comments in lowerDivI apply here as well.
|
||||
if (div->lhs() == div->rhs()) {
|
||||
if (!div->canBeDivideByZero())
|
||||
return define(new(alloc()) LInteger(1), div);
|
||||
|
||||
LDivSelfI *lir = new(alloc()) LDivSelfI(useRegisterAtStart(div->lhs()));
|
||||
if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return define(lir, div);
|
||||
}
|
||||
|
||||
LUDivOrMod *lir = new(alloc()) LUDivOrMod(useFixedAtStart(div->lhs(), eax),
|
||||
LUDivOrMod *lir = new(alloc()) LUDivOrMod(useRegister(div->lhs()),
|
||||
useRegister(div->rhs()),
|
||||
tempFixed(edx));
|
||||
if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
|
@ -259,18 +219,7 @@ LIRGeneratorX86Shared::lowerUDiv(MDiv *div)
|
|||
bool
|
||||
LIRGeneratorX86Shared::lowerUMod(MMod *mod)
|
||||
{
|
||||
// Optimize x%x. The comments in lowerModI apply here as well.
|
||||
if (mod->lhs() == mod->rhs()) {
|
||||
if (mod->isTruncated() || (mod->isUnsigned() && !mod->canBeDivideByZero()))
|
||||
return define(new(alloc()) LInteger(0), mod);
|
||||
|
||||
LModSelfI *lir = new(alloc()) LModSelfI(useRegisterAtStart(mod->lhs()));
|
||||
if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
return false;
|
||||
return define(lir, mod);
|
||||
}
|
||||
|
||||
LUDivOrMod *lir = new(alloc()) LUDivOrMod(useFixedAtStart(mod->lhs(), eax),
|
||||
LUDivOrMod *lir = new(alloc()) LUDivOrMod(useRegister(mod->lhs()),
|
||||
useRegister(mod->rhs()),
|
||||
tempFixed(eax));
|
||||
if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||
|
|
|
@ -13,10 +13,8 @@
|
|||
_(UnboxFloatingPoint) \
|
||||
_(DivI) \
|
||||
_(DivPowTwoI) \
|
||||
_(DivSelfI) \
|
||||
_(ModI) \
|
||||
_(ModPowTwoI) \
|
||||
_(ModSelfI) \
|
||||
_(PowHalfD) \
|
||||
_(AsmJSUInt32ToDouble) \
|
||||
_(AsmJSUInt32ToFloat32) \
|
||||
|
|
|
@ -14,10 +14,8 @@
|
|||
_(BoxFloatingPoint) \
|
||||
_(DivI) \
|
||||
_(DivPowTwoI) \
|
||||
_(DivSelfI) \
|
||||
_(ModI) \
|
||||
_(ModPowTwoI) \
|
||||
_(ModSelfI) \
|
||||
_(PowHalfD) \
|
||||
_(AsmJSUInt32ToDouble) \
|
||||
_(AsmJSUInt32ToFloat32) \
|
||||
|
|
Загрузка…
Ссылка в новой задаче