Bug 806643 - Negate doubles by flipping signed bit. r=sstangl
authorTony Young <tony@rfw.name>
Tue, 30 Oct 2012 14:59:06 -0700
changeset 111962 a306ea0502f7d2e01d0950fddde6637bbfa00351
parent 111961 931e44f7f78b8862aca18f978fbfe94413e03e69
child 111963 052e32ce4bfa9591c9f2bc1f557944db6f64ba1f
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewerssstangl
bugs806643
milestone19.0a1
Bug 806643 - Negate doubles by flipping signed bit. r=sstangl
js/src/ion/LIR-Common.h
js/src/ion/LOpcodes.h
js/src/ion/Lowering.cpp
js/src/ion/arm/CodeGenerator-arm.cpp
js/src/ion/arm/CodeGenerator-arm.h
js/src/ion/shared/CodeGenerator-x86-shared.cpp
js/src/ion/shared/CodeGenerator-x86-shared.h
--- a/js/src/ion/LIR-Common.h
+++ b/js/src/ion/LIR-Common.h
@@ -1322,16 +1322,26 @@ class LMinMaxD : public LInstructionHelp
     const LDefinition *output() {
         return this->getDef(0);
     }
     MMinMax *mir() const {
         return mir_->toMinMax();
     }
 };
 
+// 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>
 {
   public:
     LIR_HEADER(AbsI);
     LAbsI(const LAllocation &num) {
         setOperand(0, num);
     }
--- a/js/src/ion/LOpcodes.h
+++ b/js/src/ion/LOpcodes.h
@@ -61,16 +61,17 @@
     _(CompareAndBranch)             \
     _(CompareDAndBranch)            \
     _(CompareB)                     \
     _(CompareBAndBranch)            \
     _(IsNullOrUndefined)            \
     _(IsNullOrUndefinedAndBranch)   \
     _(MinMaxI)                      \
     _(MinMaxD)                      \
+    _(NegD)                         \
     _(AbsI)                         \
     _(AbsD)                         \
     _(SqrtD)                        \
     _(PowI)                         \
     _(PowD)                         \
     _(Random)                       \
     _(MathFunctionD)                \
     _(NotI)                         \
--- a/js/src/ion/Lowering.cpp
+++ b/js/src/ion/Lowering.cpp
@@ -850,16 +850,25 @@ LIRGenerator::visitMul(MMul *ins)
 
     if (ins->specialization() == MIRType_Int32) {
         JS_ASSERT(lhs->type() == MIRType_Int32);
         ReorderCommutative(&lhs, &rhs);
         return lowerMulI(ins, lhs, rhs);
     }
     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);
     }
 
     return lowerBinaryV(JSOP_MUL, ins);
 }
 
 bool
 LIRGenerator::visitDiv(MDiv *ins)
--- a/js/src/ion/arm/CodeGenerator-arm.cpp
+++ b/js/src/ion/arm/CodeGenerator-arm.cpp
@@ -316,16 +316,25 @@ CodeGeneratorARM::visitMinMaxD(LMinMaxD 
     masm.bind(&returnSecond);
     masm.ma_vmov(second, output);
 
     masm.bind(&done);
     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)
 {
     FloatRegister input = ToFloatRegister(ins->input());
     JS_ASSERT(input == ToFloatRegister(ins->output()));
     masm.as_vabs(input, input);
     return true;
 }
 
--- a/js/src/ion/arm/CodeGenerator-arm.h
+++ b/js/src/ion/arm/CodeGenerator-arm.h
@@ -64,16 +64,17 @@ class CodeGeneratorARM : public CodeGene
     // true, and the false block if |cond| is false.
     void emitBranch(Assembler::Condition cond, MBasicBlock *ifTrue, MBasicBlock *ifFalse);
 
     bool emitTableSwitchDispatch(MTableSwitch *mir, const Register &index, const Register &base);
 
   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);
     virtual bool visitSubI(LSubI *ins);
     virtual bool visitBitNotI(LBitNotI *ins);
     virtual bool visitBitOpI(LBitOpI *ins);
 
     virtual bool visitMulI(LMulI *ins);
--- a/js/src/ion/shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/ion/shared/CodeGenerator-x86-shared.cpp
@@ -442,16 +442,31 @@ CodeGeneratorX86Shared::visitMinMaxD(LMi
     masm.bind(&returnSecond);
     masm.movsd(second, output);
 
     masm.bind(&done);
     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)
 {
     FloatRegister input = ToFloatRegister(ins->input());
     JS_ASSERT(input == ToFloatRegister(ins->output()));
     masm.xorpd(ScratchFloatReg, ScratchFloatReg);
     masm.subsd(input, ScratchFloatReg); // negate the sign bit.
     masm.andpd(ScratchFloatReg, input); // s & ~s
     return true;
--- a/js/src/ion/shared/CodeGenerator-x86-shared.h
+++ b/js/src/ion/shared/CodeGenerator-x86-shared.h
@@ -83,16 +83,17 @@ class CodeGeneratorX86Shared : public Co
     bool emitTableSwitchDispatch(MTableSwitch *mir, const Register &index, const Register &base);
 
   public:
     CodeGeneratorX86Shared(MIRGenerator *gen, LIRGraph &graph);
 
   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);
     virtual bool visitAddI(LAddI *ins);
     virtual bool visitSubI(LSubI *ins);
     virtual bool visitMulI(LMulI *ins);
     virtual bool visitDivI(LDivI *ins);
     virtual bool visitModI(LModI *ins);