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:
Dan Gohman 2014-02-19 11:37:25 -05:00
Родитель 620a57d8a7
Коммит 602a4633a1
6 изменённых файлов: 29 добавлений и 159 удалений

Просмотреть файл

@ -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) \