Bug 1492921 : [MIPS] Fix MacroAssemblerMIPS::ma_[add | sub]TestOverflow behavior when both input and output registers are the same ; r=froydnj
authordragan.mladjenovic <dragan.mladjenovic@rt-rk.com>
Thu, 20 Sep 2018 10:53:00 +0300
changeset 495185 27ba9965ff0aa4224c22b72aeae19cf8f6e09aa8
parent 495184 ac7be31e4ad61f8e35f87ce95952415ae4f52896
child 495186 9b895fc1db953deda5967953c578908195f01029
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1492921
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1492921 : [MIPS] Fix MacroAssemblerMIPS::ma_[add | sub]TestOverflow behavior when both input and output registers are the same ; r=froydnj
js/src/jit/mips32/MacroAssembler-mips32.cpp
--- a/js/src/jit/mips32/MacroAssembler-mips32.cpp
+++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp
@@ -218,70 +218,103 @@ MacroAssemblerMIPS::ma_liPatchable(Regis
 }
 
 // Arithmetic-based ops.
 
 // Add.
 void
 MacroAssemblerMIPS::ma_addTestOverflow(Register rd, Register rs, Register rt, Label* overflow)
 {
-    Label goodAddition;
+    MOZ_ASSERT_IF(rs == rd, rs != rt);
+    MOZ_ASSERT(rs != ScratchRegister);
+    MOZ_ASSERT(rt != ScratchRegister);
+    MOZ_ASSERT(rd != rt);
+    MOZ_ASSERT(rd != ScratchRegister);
+    MOZ_ASSERT(rd != SecondScratchReg);
+
+    if (rs == rt) {
+       as_addu(rd, rs, rs);
+       as_xor(SecondScratchReg, rs, rd);
+       ma_b(SecondScratchReg, Imm32(0), overflow, Assembler::LessThan);
+       return;
+    }
+
+    // If different sign, no overflow
+    as_xor(ScratchRegister, rs, rt);
+
     as_addu(rd, rs, rt);
-
-    as_xor(ScratchRegister, rs, rt); // If different sign, no overflow
-    ma_b(ScratchRegister, Imm32(0), &goodAddition, Assembler::LessThan, ShortJump);
-
+    as_nor(ScratchRegister, ScratchRegister, zero);
     // If different sign, then overflow
-    as_xor(ScratchRegister, rs, rd);
-    ma_b(ScratchRegister, Imm32(0), overflow, Assembler::LessThan);
-
-    bind(&goodAddition);
+    as_xor(SecondScratchReg, rt, rd);
+    as_and(SecondScratchReg, SecondScratchReg, ScratchRegister);
+    ma_b(SecondScratchReg, Imm32(0), overflow, Assembler::LessThan);
+
 }
 
 void
 MacroAssemblerMIPS::ma_addTestOverflow(Register rd, Register rs, Imm32 imm, Label* overflow)
 {
-    // Check for signed range because of as_addiu
-    // Check for unsigned range because of as_xori
-    if (Imm16::IsInSignedRange(imm.value) && Imm16::IsInUnsignedRange(imm.value)) {
-        Label goodAddition;
+    MOZ_ASSERT(rs != ScratchRegister);
+    MOZ_ASSERT(rs != SecondScratchReg);
+    MOZ_ASSERT(rd != ScratchRegister);
+    MOZ_ASSERT(rd != SecondScratchReg);
+
+    Register rs_copy = rs;
+
+    if (imm.value > 0) {
+        as_nor(ScratchRegister, rs, zero);
+    } else if (rs == rd) {
+        ma_move(ScratchRegister, rs);
+        rs_copy = ScratchRegister;
+    }
+
+    if (Imm16::IsInSignedRange(imm.value)) {
         as_addiu(rd, rs, imm.value);
-
-        // If different sign, no overflow
-        as_xori(ScratchRegister, rs, imm.value);
-        ma_b(ScratchRegister, Imm32(0), &goodAddition, Assembler::LessThan, ShortJump);
-
-        // If different sign, then overflow
-        as_xor(ScratchRegister, rs, rd);
-        ma_b(ScratchRegister, Imm32(0), overflow, Assembler::LessThan);
-
-        bind(&goodAddition);
     } else {
-        ma_li(ScratchRegister, imm);
-        ma_addTestOverflow(rd, rs, ScratchRegister, overflow);
+        ma_li(SecondScratchReg, imm);
+        as_addu(rd, rs, SecondScratchReg);
     }
+
+    if (imm.value > 0) {
+        as_and(ScratchRegister, ScratchRegister, rd);
+    } else {
+        as_nor(SecondScratchReg, rd, zero);
+        as_and(ScratchRegister, rs_copy, SecondScratchReg);
+    }
+
+    ma_b(ScratchRegister, Imm32(0), overflow, Assembler::LessThan);
 }
 
 // Subtract.
 void
 MacroAssemblerMIPS::ma_subTestOverflow(Register rd, Register rs, Register rt, Label* overflow)
 {
-    Label goodSubtraction;
-    // Use second scratch. The instructions generated by ma_b don't use the
-    // second scratch register.
+    // The rs == rt case should probably be folded at MIR stage.
+    // Happens for Number_isInteger*. Not worth specializing here.
+    MOZ_ASSERT_IF(rs == rd, rs != rt);
+    MOZ_ASSERT(rs != SecondScratchReg);
+    MOZ_ASSERT(rt != SecondScratchReg);
+    MOZ_ASSERT(rd != rt);
+    MOZ_ASSERT(rd != ScratchRegister);
+    MOZ_ASSERT(rd != SecondScratchReg);
+
+    Register rs_copy = rs;
+
+    if (rs == rd) {
+       ma_move(SecondScratchReg, rs);
+       rs_copy = SecondScratchReg;
+    }
+
     as_subu(rd, rs, rt);
-
-    as_xor(ScratchRegister, rs, rt); // If same sign, no overflow
-    ma_b(ScratchRegister, Imm32(0), &goodSubtraction, Assembler::GreaterThanOrEqual, ShortJump);
-
+    // If same sign, no overflow
+    as_xor(ScratchRegister, rs_copy, rt);
     // If different sign, then overflow
-    as_xor(ScratchRegister, rs, rd);
-    ma_b(ScratchRegister, Imm32(0), overflow, Assembler::LessThan);
-
-    bind(&goodSubtraction);
+    as_xor(SecondScratchReg, rs_copy, rd);
+    as_and(SecondScratchReg, SecondScratchReg, ScratchRegister);
+    ma_b(SecondScratchReg, Imm32(0), overflow, Assembler::LessThan);
 }
 
 // Memory.
 
 void
 MacroAssemblerMIPS::ma_load(Register dest, Address address,
                             LoadStoreSize size, LoadStoreExtension extension)
 {