diff --git a/js/src/ion/LIR-Common.h b/js/src/ion/LIR-Common.h index d6dbe58c75de..e3f3688cef6c 100644 --- a/js/src/ion/LIR-Common.h +++ b/js/src/ion/LIR-Common.h @@ -1327,6 +1327,16 @@ class LMinMaxD : public LInstructionHelper<1, 2, 0> } }; +// Negative of a double. +class LNegD : public LInstructionHelper<1, 1, 0> +{ + public: + LIR_HEADER(NegD); + LNegD(const LAllocation &num) { + setOperand(0, num); + } +}; + // Absolute value of an integer. class LAbsI : public LInstructionHelper<1, 1, 0> { diff --git a/js/src/ion/LOpcodes.h b/js/src/ion/LOpcodes.h index 7b4348ccc674..5cb03d90fc3c 100644 --- a/js/src/ion/LOpcodes.h +++ b/js/src/ion/LOpcodes.h @@ -66,6 +66,7 @@ _(IsNullOrUndefinedAndBranch) \ _(MinMaxI) \ _(MinMaxD) \ + _(NegD) \ _(AbsI) \ _(AbsD) \ _(SqrtD) \ diff --git a/js/src/ion/Lowering.cpp b/js/src/ion/Lowering.cpp index dc9fcfa2ed2d..5e30015a171a 100644 --- a/js/src/ion/Lowering.cpp +++ b/js/src/ion/Lowering.cpp @@ -855,6 +855,15 @@ LIRGenerator::visitMul(MMul *ins) } if (ins->specialization() == MIRType_Double) { JS_ASSERT(lhs->type() == MIRType_Double); + + // If our LHS is a constant -1.0, we can optimize to an LNegD. + if (lhs->isConstant() && lhs->toConstant()->value() == DoubleValue(-1.0)) + return defineReuseInput(new LNegD(useRegisterAtStart(rhs)), ins, 0); + + // We can do the same for the RHS, if we just swap the operands. + if (rhs->isConstant() && rhs->toConstant()->value() == DoubleValue(-1.0)) + return defineReuseInput(new LNegD(useRegisterAtStart(lhs)), ins, 0); + return lowerForFPU(new LMathD(JSOP_MUL), ins, lhs, rhs); } diff --git a/js/src/ion/arm/CodeGenerator-arm.cpp b/js/src/ion/arm/CodeGenerator-arm.cpp index 839ad7e02b0d..35c8d1b02263 100644 --- a/js/src/ion/arm/CodeGenerator-arm.cpp +++ b/js/src/ion/arm/CodeGenerator-arm.cpp @@ -320,6 +320,15 @@ CodeGeneratorARM::visitMinMaxD(LMinMaxD *ins) return true; } +bool +CodeGeneratorARM::visitNegD(LNegD *ins) +{ + FloatRegister input = ToFloatRegister(ins->input()); + JS_ASSERT(input == ToFloatRegister(ins->output())); + masm.as_vneg(input, input); + return true; +} + bool CodeGeneratorARM::visitAbsD(LAbsD *ins) { diff --git a/js/src/ion/arm/CodeGenerator-arm.h b/js/src/ion/arm/CodeGenerator-arm.h index a040b7ba9686..e80e794bfeff 100644 --- a/js/src/ion/arm/CodeGenerator-arm.h +++ b/js/src/ion/arm/CodeGenerator-arm.h @@ -69,6 +69,7 @@ class CodeGeneratorARM : public CodeGeneratorShared public: // Instruction visitors. virtual bool visitMinMaxD(LMinMaxD *ins); + virtual bool visitNegD(LNegD *ins); virtual bool visitAbsD(LAbsD *ins); virtual bool visitSqrtD(LSqrtD *ins); virtual bool visitAddI(LAddI *ins); diff --git a/js/src/ion/shared/CodeGenerator-x86-shared.cpp b/js/src/ion/shared/CodeGenerator-x86-shared.cpp index 3c370dc5d782..8b9ae0f37ee7 100644 --- a/js/src/ion/shared/CodeGenerator-x86-shared.cpp +++ b/js/src/ion/shared/CodeGenerator-x86-shared.cpp @@ -446,6 +446,21 @@ CodeGeneratorX86Shared::visitMinMaxD(LMinMaxD *ins) return true; } +bool +CodeGeneratorX86Shared::visitNegD(LNegD *ins) +{ + // XOR the float in a float register with -0.0. + FloatRegister input = ToFloatRegister(ins->input()); + JS_ASSERT(input == ToFloatRegister(ins->output())); + + // From MacroAssemblerX86Shared::maybeInlineDouble + masm.pcmpeqw(ScratchFloatReg, ScratchFloatReg); + masm.psllq(Imm32(63), ScratchFloatReg); + + masm.xorpd(ScratchFloatReg, input); // s ^ 0x80000000000000 + return true; +} + bool CodeGeneratorX86Shared::visitAbsD(LAbsD *ins) { diff --git a/js/src/ion/shared/CodeGenerator-x86-shared.h b/js/src/ion/shared/CodeGenerator-x86-shared.h index 61d99a247238..961bc517f2d3 100644 --- a/js/src/ion/shared/CodeGenerator-x86-shared.h +++ b/js/src/ion/shared/CodeGenerator-x86-shared.h @@ -88,6 +88,7 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared public: // Instruction visitors. virtual bool visitMinMaxD(LMinMaxD *ins); + virtual bool visitNegD(LNegD *ins); virtual bool visitAbsD(LAbsD *ins); virtual bool visitSqrtD(LSqrtD *ins); virtual bool visitPowHalfD(LPowHalfD *ins);