Bug 949668 - SpiderMonkey: Add a MoveOp::FLOAT32 r=jandem

This commit is contained in:
Dan Gohman 2013-12-17 08:46:37 -08:00
parent 262ff19f9b
commit c8609b2b70
8 changed files with 90 additions and 40 deletions

View File

@ -1206,7 +1206,7 @@ CodeGenerator::visitMoveGroup(LMoveGroup *group)
case LDefinition::BOX: case LDefinition::BOX:
#endif #endif
case LDefinition::GENERAL: kind = MoveOp::GENERAL; break; case LDefinition::GENERAL: kind = MoveOp::GENERAL; break;
case LDefinition::FLOAT32: case LDefinition::FLOAT32: kind = MoveOp::FLOAT32; break;
case LDefinition::DOUBLE: kind = MoveOp::DOUBLE; break; case LDefinition::DOUBLE: kind = MoveOp::DOUBLE; break;
default: MOZ_ASSUME_UNREACHABLE("Unexpected move type"); default: MOZ_ASSUME_UNREACHABLE("Unexpected move type");
} }
@ -4124,7 +4124,7 @@ CodeGenerator::visitMathFunctionF(LMathFunctionF *ins)
JS_ASSERT(ToFloatRegister(ins->output()) == ReturnFloatReg); JS_ASSERT(ToFloatRegister(ins->output()) == ReturnFloatReg);
masm.setupUnalignedABICall(1, temp); masm.setupUnalignedABICall(1, temp);
masm.passABIArg(input, MoveOp::DOUBLE); masm.passABIArg(input, MoveOp::FLOAT32);
void *funptr = nullptr; void *funptr = nullptr;
switch (ins->mir()->function()) { switch (ins->mir()->function()) {
@ -4141,7 +4141,7 @@ CodeGenerator::visitMathFunctionF(LMathFunctionF *ins)
MOZ_ASSUME_UNREACHABLE("Unknown or unsupported float32 math function"); MOZ_ASSUME_UNREACHABLE("Unknown or unsupported float32 math function");
} }
masm.callWithABI(funptr, MoveOp::DOUBLE); masm.callWithABI(funptr, MoveOp::FLOAT32);
return true; return true;
} }

View File

@ -115,6 +115,7 @@ class MoveOp
public: public:
enum Kind { enum Kind {
GENERAL, GENERAL,
FLOAT32,
DOUBLE DOUBLE
}; };

View File

@ -2152,9 +2152,19 @@ GetIntArgStackDisp(uint32_t usedIntArgs, uint32_t usedFloatArgs, uint32_t *paddi
} }
static inline uint32_t static inline uint32_t
GetFloatArgStackDisp(uint32_t usedIntArgs, uint32_t usedFloatArgs, uint32_t *padding) GetFloat32ArgStackDisp(uint32_t usedIntArgs, uint32_t usedFloatArgs, uint32_t *padding)
{ {
JS_ASSERT(usedFloatArgs >= NumFloatArgRegs);
uint32_t intSlots = 0;
if (usedIntArgs > NumIntArgRegs)
intSlots = usedIntArgs - NumIntArgRegs;
uint32_t float32Slots = usedFloatArgs - NumFloatArgRegs;
return (intSlots + float32Slots + *padding) * STACK_SLOT_SIZE;
}
static inline uint32_t
GetDoubleArgStackDisp(uint32_t usedIntArgs, uint32_t usedFloatArgs, uint32_t *padding)
{
JS_ASSERT(usedFloatArgs >= NumFloatArgRegs); JS_ASSERT(usedFloatArgs >= NumFloatArgRegs);
uint32_t intSlots = 0; uint32_t intSlots = 0;
if (usedIntArgs > NumIntArgRegs) { if (usedIntArgs > NumIntArgRegs) {

View File

@ -3515,18 +3515,20 @@ MacroAssemblerARMCompat::passABIArg(const MoveOperand &from, MoveOp::Kind kind)
if (!enoughMemory_) if (!enoughMemory_)
return; return;
switch (kind) { switch (kind) {
case MoveOp::FLOAT32:
case MoveOp::DOUBLE: { case MoveOp::DOUBLE: {
FloatRegister fr; FloatRegister fr;
if (GetFloatArgReg(usedIntSlots_, usedFloatSlots_, &fr)) { if (GetFloatArgReg(usedIntSlots_, usedFloatSlots_, &fr)) {
if (!from.isFloatReg() || from.floatReg() != fr) { if (from.isFloatReg() && from.floatReg() == fr) {
enoughMemory_ = moveResolver_.addMove(from, MoveOperand(fr), MoveOp::DOUBLE); // Nothing to do; the value is in the right register already
return;
} }
// else nothing to do; the value is in the right register already to = MoveOperand(fr);
} else { } else {
// If (and only if) the integer registers have started spilling, do we // If (and only if) the integer registers have started spilling, do we
// need to take the double register's alignment into account // need to take the register's alignment into account
uint32_t disp = GetFloatArgStackDisp(usedIntSlots_, usedFloatSlots_, &padding_); uint32_t disp = GetFloatArgStackDisp(usedIntSlots_, usedFloatSlots_, &padding_);
enoughMemory_ = moveResolver_.addMove(from, MoveOperand(sp, disp), MoveOp::DOUBLE); to = MoveOperand(sp, disp);
} }
usedFloatSlots_++; usedFloatSlots_++;
break; break;
@ -3534,13 +3536,14 @@ MacroAssemblerARMCompat::passABIArg(const MoveOperand &from, MoveOp::Kind kind)
case MoveOp::GENERAL: { case MoveOp::GENERAL: {
Register r; Register r;
if (GetIntArgReg(usedIntSlots_, usedFloatSlots_, &r)) { if (GetIntArgReg(usedIntSlots_, usedFloatSlots_, &r)) {
if (!from.isGeneralReg() || from.reg() != r) { if (from.isGeneralReg() && from.reg() == r) {
enoughMemory_ = moveResolver_.addMove(from, MoveOperand(r), MoveOp::GENERAL); // Nothing to do; the value is in the right register already
return;
} }
// else nothing to do; the value is in the right register already to = MoveOperand(r);
} else { } else {
uint32_t disp = GetIntArgStackDisp(usedIntSlots_, usedFloatSlots_, &padding_); uint32_t disp = GetIntArgStackDisp(usedIntSlots_, usedFloatSlots_, &padding_);
enoughMemory_ = moveResolver_.addMove(from, MoveOperand(sp, disp), MoveOp::GENERAL); to = MoveOperand(sp, disp);
} }
usedIntSlots_++; usedIntSlots_++;
break; break;
@ -3549,6 +3552,7 @@ MacroAssemblerARMCompat::passABIArg(const MoveOperand &from, MoveOp::Kind kind)
MOZ_ASSUME_UNREACHABLE("Unexpected argument kind"); MOZ_ASSUME_UNREACHABLE("Unexpected argument kind");
} }
enoughMemory_ = moveResolver_.addMove(from, to, kind);
} }
#else #else
@ -3566,6 +3570,7 @@ MacroAssemblerARMCompat::passABIArg(const MoveOperand &from, MoveOp::Kind kind)
usedSlots_ = (usedSlots_ + 1) & ~1; usedSlots_ = (usedSlots_ + 1) & ~1;
increment = 2; increment = 2;
break; break;
case MoveOp::FLOAT32:
case MoveOp::GENERAL: case MoveOp::GENERAL:
break; break;
default: default:
@ -3575,7 +3580,7 @@ MacroAssemblerARMCompat::passABIArg(const MoveOperand &from, MoveOp::Kind kind)
Register destReg; Register destReg;
MoveOperand dest; MoveOperand dest;
if (GetIntArgReg(usedSlots_, 0, &destReg)) { if (GetIntArgReg(usedSlots_, 0, &destReg)) {
if (kind == MoveOp::DOUBLE) { if (kind == MoveOp::DOUBLE || kind == MoveOp::FLOAT32) {
floatArgsInGPR[destReg.code() >> 1] = from; floatArgsInGPR[destReg.code() >> 1] = from;
floatArgsInGPRValid[destReg.code() >> 1] = true; floatArgsInGPRValid[destReg.code() >> 1] = true;
useResolver = false; useResolver = false;

View File

@ -108,7 +108,9 @@ MoveEmitterARM::breakCycle(const MoveOperand &from, const MoveOperand &to, MoveO
// //
// This case handles (A -> B), which we reach first. We save B, then allow // This case handles (A -> B), which we reach first. We save B, then allow
// the original move to continue. // the original move to continue.
if (kind == MoveOp::DOUBLE) { switch (kind) {
case MoveOp::FLOAT32:
case MoveOp::DOUBLE:
if (to.isMemory()) { if (to.isMemory()) {
FloatRegister temp = ScratchFloatReg; FloatRegister temp = ScratchFloatReg;
masm.ma_vldr(toOperand(to, true), temp); masm.ma_vldr(toOperand(to, true), temp);
@ -116,7 +118,8 @@ MoveEmitterARM::breakCycle(const MoveOperand &from, const MoveOperand &to, MoveO
} else { } else {
masm.ma_vstr(to.floatReg(), cycleSlot()); masm.ma_vstr(to.floatReg(), cycleSlot());
} }
} else { break;
case MoveOp::GENERAL:
// an non-vfp value // an non-vfp value
if (to.isMemory()) { if (to.isMemory()) {
Register temp = tempReg(); Register temp = tempReg();
@ -130,6 +133,9 @@ MoveEmitterARM::breakCycle(const MoveOperand &from, const MoveOperand &to, MoveO
} }
masm.ma_str(to.reg(), cycleSlot()); masm.ma_str(to.reg(), cycleSlot());
} }
break;
default:
MOZ_ASSUME_UNREACHABLE("Unexpected move kind");
} }
} }
@ -142,7 +148,9 @@ MoveEmitterARM::completeCycle(const MoveOperand &from, const MoveOperand &to, Mo
// //
// This case handles (B -> A), which we reach last. We emit a move from the // This case handles (B -> A), which we reach last. We emit a move from the
// saved value of B, to A. // saved value of B, to A.
if (kind == MoveOp::DOUBLE) { switch (kind) {
case MoveOp::FLOAT32:
case MoveOp::DOUBLE:
if (to.isMemory()) { if (to.isMemory()) {
FloatRegister temp = ScratchFloatReg; FloatRegister temp = ScratchFloatReg;
masm.ma_vldr(cycleSlot(), temp); masm.ma_vldr(cycleSlot(), temp);
@ -150,7 +158,8 @@ MoveEmitterARM::completeCycle(const MoveOperand &from, const MoveOperand &to, Mo
} else { } else {
masm.ma_vldr(cycleSlot(), to.floatReg()); masm.ma_vldr(cycleSlot(), to.floatReg());
} }
} else { break;
case MoveOp::GENERAL:
if (to.isMemory()) { if (to.isMemory()) {
Register temp = tempReg(); Register temp = tempReg();
masm.ma_ldr(cycleSlot(), temp); masm.ma_ldr(cycleSlot(), temp);
@ -162,6 +171,9 @@ MoveEmitterARM::completeCycle(const MoveOperand &from, const MoveOperand &to, Mo
} }
masm.ma_ldr(cycleSlot(), to.reg()); masm.ma_ldr(cycleSlot(), to.reg());
} }
break;
default:
MOZ_ASSUME_UNREACHABLE("Unexpected move kind");
} }
} }
@ -248,10 +260,17 @@ MoveEmitterARM::emit(const MoveOp &move)
inCycle_ = true; inCycle_ = true;
} }
if (move.kind() == MoveOp::DOUBLE) switch (move.kind()) {
case MoveOp::FLOAT32:
case MoveOp::DOUBLE:
emitDoubleMove(from, to); emitDoubleMove(from, to);
else break;
case MoveOp::GENERAL:
emitMove(from, to); emitMove(from, to);
break;
default:
MOZ_ASSUME_UNREACHABLE("Unexpected move kind");
}
} }
void void

View File

@ -128,10 +128,17 @@ MoveEmitterX86::emit(const MoveResolver &moves)
} }
// A normal move which is not part of a cycle. // A normal move which is not part of a cycle.
if (move.kind() == MoveOp::DOUBLE) switch (move.kind()) {
case MoveOp::FLOAT32:
case MoveOp::DOUBLE:
emitDoubleMove(from, to); emitDoubleMove(from, to);
else break;
case MoveOp::GENERAL:
emitGeneralMove(from, to); emitGeneralMove(from, to);
break;
default:
MOZ_ASSUME_UNREACHABLE("Unexpected move kind");
}
} }
} }
@ -212,15 +219,21 @@ MoveEmitterX86::breakCycle(const MoveOperand &to, MoveOp::Kind kind)
// //
// This case handles (A -> B), which we reach first. We save B, then allow // This case handles (A -> B), which we reach first. We save B, then allow
// the original move to continue. // the original move to continue.
if (kind == MoveOp::DOUBLE) { switch (kind) {
case MoveOp::FLOAT32:
case MoveOp::DOUBLE:
if (to.isMemory()) { if (to.isMemory()) {
masm.loadDouble(toAddress(to), ScratchFloatReg); masm.loadDouble(toAddress(to), ScratchFloatReg);
masm.storeDouble(ScratchFloatReg, cycleSlot()); masm.storeDouble(ScratchFloatReg, cycleSlot());
} else { } else {
masm.storeDouble(to.floatReg(), cycleSlot()); masm.storeDouble(to.floatReg(), cycleSlot());
} }
} else { break;
case MoveOp::GENERAL:
masm.Push(toOperand(to)); masm.Push(toOperand(to));
break;
default:
MOZ_ASSUME_UNREACHABLE("Unexpected move kind");
} }
} }
@ -233,19 +246,25 @@ MoveEmitterX86::completeCycle(const MoveOperand &to, MoveOp::Kind kind)
// //
// This case handles (B -> A), which we reach last. We emit a move from the // This case handles (B -> A), which we reach last. We emit a move from the
// saved value of B, to A. // saved value of B, to A.
if (kind == MoveOp::DOUBLE) { switch (kind) {
case MoveOp::FLOAT32:
case MoveOp::DOUBLE:
if (to.isMemory()) { if (to.isMemory()) {
masm.loadDouble(cycleSlot(), ScratchFloatReg); masm.loadDouble(cycleSlot(), ScratchFloatReg);
masm.storeDouble(ScratchFloatReg, toAddress(to)); masm.storeDouble(ScratchFloatReg, toAddress(to));
} else { } else {
masm.loadDouble(cycleSlot(), to.floatReg()); masm.loadDouble(cycleSlot(), to.floatReg());
} }
} else { break;
case MoveOp::GENERAL:
if (to.isMemory()) { if (to.isMemory()) {
masm.Pop(toPopOperand(to)); masm.Pop(toPopOperand(to));
} else { } else {
masm.Pop(to.reg()); masm.Pop(to.reg());
} }
break;
default:
MOZ_ASSUME_UNREACHABLE("Unexpected move kind");
} }
} }

View File

@ -138,6 +138,7 @@ MacroAssemblerX64::passABIArg(const MoveOperand &from, MoveOp::Kind kind)
{ {
MoveOperand to; MoveOperand to;
switch (kind) { switch (kind) {
case MoveOp::FLOAT32:
case MoveOp::DOUBLE: { case MoveOp::DOUBLE: {
FloatRegister dest; FloatRegister dest;
if (GetFloatArgReg(passedIntArgs_, passedFloatArgs_++, &dest)) { if (GetFloatArgReg(passedIntArgs_, passedFloatArgs_++, &dest)) {
@ -149,11 +150,11 @@ MacroAssemblerX64::passABIArg(const MoveOperand &from, MoveOp::Kind kind)
} else { } else {
to = MoveOperand(StackPointer, stackForCall_); to = MoveOperand(StackPointer, stackForCall_);
switch (kind) { switch (kind) {
case MoveOp::FLOAT32: stackForCall_ += sizeof(float); break;
case MoveOp::DOUBLE: stackForCall_ += sizeof(double); break; case MoveOp::DOUBLE: stackForCall_ += sizeof(double); break;
default: MOZ_ASSUME_UNREACHABLE("Unexpected float register class argument kind"); default: MOZ_ASSUME_UNREACHABLE("Unexpected float register class argument kind");
} }
} }
enoughMemory_ = moveResolver_.addMove(from, to, MoveOp::DOUBLE);
break; break;
} }
case MoveOp::GENERAL: { case MoveOp::GENERAL: {
@ -168,12 +169,13 @@ MacroAssemblerX64::passABIArg(const MoveOperand &from, MoveOp::Kind kind)
to = MoveOperand(StackPointer, stackForCall_); to = MoveOperand(StackPointer, stackForCall_);
stackForCall_ += sizeof(int64_t); stackForCall_ += sizeof(int64_t);
} }
enoughMemory_ = moveResolver_.addMove(from, to, MoveOp::GENERAL);
break; break;
} }
default: default:
MOZ_ASSUME_UNREACHABLE("Unexpected argument kind"); MOZ_ASSUME_UNREACHABLE("Unexpected argument kind");
} }
enoughMemory_ = moveResolver_.addMove(from, to, kind);
} }
void void

View File

@ -168,17 +168,12 @@ MacroAssemblerX86::passABIArg(const MoveOperand &from, MoveOp::Kind kind)
++passedArgs_; ++passedArgs_;
MoveOperand to = MoveOperand(StackPointer, stackForCall_); MoveOperand to = MoveOperand(StackPointer, stackForCall_);
switch (kind) { switch (kind) {
case MoveOp::DOUBLE: case MoveOp::FLOAT32: stackForCall_ += sizeof(float); break;
stackForCall_ += sizeof(double); case MoveOp::DOUBLE: stackForCall_ += sizeof(double); break;
enoughMemory_ &= moveResolver_.addMove(from, to, MoveOp::DOUBLE); case MoveOp::GENERAL: stackForCall_ += sizeof(int32_t); break;
break; default: MOZ_ASSUME_UNREACHABLE("Unexpected argument kind");
case MoveOp::GENERAL:
stackForCall_ += sizeof(int32_t);
enoughMemory_ &= moveResolver_.addMove(from, to, MoveOp::GENERAL);
break;
default:
MOZ_ASSUME_UNREACHABLE("Unexpected argument kind");
} }
enoughMemory_ &= moveResolver_.addMove(from, to, kind);
} }
void void
@ -243,8 +238,7 @@ MacroAssemblerX86::callWithABIPost(uint32_t stackAdjust, MoveOp::Kind result)
fstp(Operand(esp, 0)); fstp(Operand(esp, 0));
loadDouble(Operand(esp, 0), ReturnFloatReg); loadDouble(Operand(esp, 0), ReturnFloatReg);
freeStack(sizeof(double)); freeStack(sizeof(double));
} } else if (result == MoveOp::FLOAT32) {
if (result == MoveOp::FLOAT32) {
reserveStack(sizeof(float)); reserveStack(sizeof(float));
fstp32(Operand(esp, 0)); fstp32(Operand(esp, 0));
loadFloat(Operand(esp, 0), ReturnFloatReg); loadFloat(Operand(esp, 0), ReturnFloatReg);