Title: [189136] trunk/Source/_javascript_Core
Revision
189136
Author
[email protected]
Date
2015-08-28 18:57:05 -0700 (Fri, 28 Aug 2015)

Log Message

[JSC][x86] Improve the compare functions when comparing with zero
https://bugs.webkit.org/show_bug.cgi?id=148536

Patch by Benjamin Poulain <[email protected]> on 2015-08-28
Reviewed by Geoffrey Garen.

This patch has two parts:
1) The macro assembler gets an additional cmp->test optimization
   for LessThan and GreaterThanOrEqual.
   Instead of comparing the value with an immediate, test the value
   with itself and use the flag.
2) Extend the DFG JIT optimization of compare.
   In particular, use the same optimization in compileInt32Compare()
   as we have in compilePeepHoleBooleanBranch().
   The generator compileInt32Compare() is unfortunately very
   common due to MoveHints placed between the Compare node and the Branch
   node.

* assembler/MacroAssembler.h:
(JSC::MacroAssembler::compare32):
* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::branch32):
(JSC::MacroAssemblerX86Common::compare32):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compilePeepHoleBooleanBranch):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compileInt32Compare):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (189135 => 189136)


--- trunk/Source/_javascript_Core/ChangeLog	2015-08-29 00:14:54 UTC (rev 189135)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-08-29 01:57:05 UTC (rev 189136)
@@ -1,3 +1,32 @@
+2015-08-28  Benjamin Poulain  <[email protected]>
+
+        [JSC][x86] Improve the compare functions when comparing with zero
+        https://bugs.webkit.org/show_bug.cgi?id=148536
+
+        Reviewed by Geoffrey Garen.
+
+        This patch has two parts:
+        1) The macro assembler gets an additional cmp->test optimization
+           for LessThan and GreaterThanOrEqual.
+           Instead of comparing the value with an immediate, test the value
+           with itself and use the flag.
+        2) Extend the DFG JIT optimization of compare.
+           In particular, use the same optimization in compileInt32Compare()
+           as we have in compilePeepHoleBooleanBranch().
+           The generator compileInt32Compare() is unfortunately very
+           common due to MoveHints placed between the Compare node and the Branch
+           node.
+
+        * assembler/MacroAssembler.h:
+        (JSC::MacroAssembler::compare32):
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::branch32):
+        (JSC::MacroAssemblerX86Common::compare32):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compilePeepHoleBooleanBranch):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compileInt32Compare):
+
 2015-08-28  Mark Lam  <[email protected]>
 
         Add MacroAssemblerPrinter support for printing memory.

Modified: trunk/Source/_javascript_Core/assembler/MacroAssembler.h (189135 => 189136)


--- trunk/Source/_javascript_Core/assembler/MacroAssembler.h	2015-08-29 00:14:54 UTC (rev 189135)
+++ trunk/Source/_javascript_Core/assembler/MacroAssembler.h	2015-08-29 01:57:05 UTC (rev 189136)
@@ -112,6 +112,7 @@
     using MacroAssemblerBase::pop;
     using MacroAssemblerBase::jump;
     using MacroAssemblerBase::branch32;
+    using MacroAssemblerBase::compare32;
     using MacroAssemblerBase::move;
     using MacroAssemblerBase::add32;
     using MacroAssemblerBase::and32;
@@ -329,6 +330,11 @@
         return branch32(commute(cond), right, left);
     }
 
+    void compare32(RelationalCondition cond, Imm32 left, RegisterID right, RegisterID dest)
+    {
+        compare32(commute(cond), right, left, dest);
+    }
+
     void branchTestPtr(ResultCondition cond, RegisterID reg, Label target)
     {
         branchTestPtr(cond, reg).linkTo(target, this);
@@ -1509,6 +1515,24 @@
         return branch32(cond, left, right.asTrustedImm32());
     }
 
+    void compare32(RelationalCondition cond, RegisterID left, Imm32 right, RegisterID dest)
+    {
+        if (shouldBlind(right)) {
+            if (haveScratchRegisterForBlinding()) {
+                loadXorBlindedConstant(xorBlindConstant(right), scratchRegisterForBlinding());
+                compare32(cond, left, scratchRegisterForBlinding(), dest);
+            }
+            // If we don't have a scratch register available for use, we'll just
+            // place a random number of nops.
+            uint32_t nopCount = random() & 3;
+            while (nopCount--)
+                nop();
+            compare32(cond, left, right.asTrustedImm32(), dest);
+        }
+
+        compare32(cond, left, right.asTrustedImm32(), dest);
+    }
+
     Jump branchAdd32(ResultCondition cond, RegisterID src, Imm32 imm, RegisterID dest)
     {
         if (src == dest)

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h (189135 => 189136)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h	2015-08-29 00:14:54 UTC (rev 189135)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h	2015-08-29 01:57:05 UTC (rev 189136)
@@ -1305,7 +1305,7 @@
 private:
 
     // Should we be using TEQ for equal/not-equal?
-    void compare32(RegisterID left, TrustedImm32 right)
+    void compare32AndSetFlags(RegisterID left, TrustedImm32 right)
     {
         int32_t imm = right.m_value;
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm);
@@ -1363,7 +1363,7 @@
 
     Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right)
     {
-        compare32(left, right);
+        compare32AndSetFlags(left, right);
         return Jump(makeBranch(cond));
     }
 
@@ -1421,7 +1421,7 @@
 
     Jump branch8(RelationalCondition cond, RegisterID left, TrustedImm32 right)
     {
-        compare32(left, right);
+        compare32AndSetFlags(left, right);
         return Jump(makeBranch(cond));
     }
 
@@ -1721,7 +1721,7 @@
 
     void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
     {
-        compare32(left, right);
+        compare32AndSetFlags(left, right);
         m_assembler.it(armV7Condition(cond), false);
         m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(1));
         m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0));

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (189135 => 189136)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2015-08-29 00:14:54 UTC (rev 189135)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2015-08-29 01:57:05 UTC (rev 189136)
@@ -1124,10 +1124,28 @@
 
     Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right)
     {
-        if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
+        if (!right.m_value && (cond == Equal || cond == NotEqual || cond == LessThan || cond == GreaterThanOrEqual)) {
+            ResultCondition resultCondition;
+            switch (cond) {
+            case Equal:
+                resultCondition = Zero;
+                break;
+            case NotEqual:
+                resultCondition = NonZero;
+                break;
+            case LessThan:
+                resultCondition = Signed;
+                break;
+            case GreaterThanOrEqual:
+                resultCondition = PositiveOrZero;
+                break;
+            default:
+                RELEASE_ASSERT_NOT_REACHED();
+            }
             m_assembler.testl_rr(left, left);
-        else
-            m_assembler.cmpl_ir(right.m_value, left);
+            return Jump(m_assembler.jCC(x86Condition(resultCondition)));
+        }
+        m_assembler.cmpl_ir(right.m_value, left);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
     
@@ -1437,10 +1455,29 @@
 
     void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
     {
-        if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
+        if (!right.m_value && (cond == Equal || cond == NotEqual || cond == LessThan || cond == GreaterThanOrEqual)) {
+            ResultCondition resultCondition;
+            switch (cond) {
+            case Equal:
+                resultCondition = Zero;
+                break;
+            case NotEqual:
+                resultCondition = NonZero;
+                break;
+            case LessThan:
+                resultCondition = Signed;
+                break;
+            case GreaterThanOrEqual:
+                resultCondition = PositiveOrZero;
+                break;
+            default:
+                RELEASE_ASSERT_NOT_REACHED();
+            }
             m_assembler.testl_rr(left, left);
-        else
-            m_assembler.cmpl_ir(right.m_value, left);
+            set32(x86Condition(resultCondition), dest);
+            return;
+        }
+        m_assembler.cmpl_ir(right.m_value, left);
         set32(x86Condition(cond), dest);
     }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (189135 => 189136)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2015-08-29 00:14:54 UTC (rev 189135)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2015-08-29 01:57:05 UTC (rev 189136)
@@ -1278,14 +1278,14 @@
         notTaken = tmp;
     }
 
-    if (node->child1()->isBooleanConstant()) {
-        bool imm = node->child1()->asBoolean();
+    if (node->child1()->isInt32Constant()) {
+        int32_t imm = node->child1()->asInt32();
         SpeculateBooleanOperand op2(this, node->child2());
-        branch32(condition, JITCompiler::Imm32(static_cast<int32_t>(JSValue::encode(jsBoolean(imm)))), op2.gpr(), taken);
-    } else if (node->child2()->isBooleanConstant()) {
+        branch32(condition, JITCompiler::Imm32(imm), op2.gpr(), taken);
+    } else if (node->child2()->isInt32Constant()) {
         SpeculateBooleanOperand op1(this, node->child1());
-        bool imm = node->child2()->asBoolean();
-        branch32(condition, op1.gpr(), JITCompiler::Imm32(static_cast<int32_t>(JSValue::encode(jsBoolean(imm)))), taken);
+        int32_t imm = node->child2()->asInt32();
+        branch32(condition, op1.gpr(), JITCompiler::Imm32(imm), taken);
     } else {
         SpeculateBooleanOperand op1(this, node->child1());
         SpeculateBooleanOperand op2(this, node->child2());

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (189135 => 189136)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2015-08-29 00:14:54 UTC (rev 189135)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2015-08-29 01:57:05 UTC (rev 189136)
@@ -1470,15 +1470,34 @@
 
 void SpeculativeJIT::compileInt32Compare(Node* node, MacroAssembler::RelationalCondition condition)
 {
-    SpeculateInt32Operand op1(this, node->child1());
-    SpeculateInt32Operand op2(this, node->child2());
-    GPRTemporary result(this, Reuse, op1, op2);
-    
-    m_jit.compare32(condition, op1.gpr(), op2.gpr(), result.gpr());
-    
-    // If we add a DataFormatBool, we should use it here.
-    m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
-    jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
+    if (node->child1()->isInt32Constant()) {
+        SpeculateInt32Operand op2(this, node->child2());
+        GPRTemporary result(this, Reuse, op2);
+        int32_t imm = node->child1()->asInt32();
+        m_jit.compare32(condition, JITCompiler::Imm32(imm), op2.gpr(), result.gpr());
+
+        // If we add a DataFormatBool, we should use it here.
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+        jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
+    } else if (node->child2()->isInt32Constant()) {
+        SpeculateInt32Operand op1(this, node->child1());
+        GPRTemporary result(this, Reuse, op1);
+        int32_t imm = node->child2()->asInt32();
+        m_jit.compare32(condition, op1.gpr(), JITCompiler::Imm32(imm), result.gpr());
+
+        // If we add a DataFormatBool, we should use it here.
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+        jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
+    } else {
+        SpeculateInt32Operand op1(this, node->child1());
+        SpeculateInt32Operand op2(this, node->child2());
+        GPRTemporary result(this, Reuse, op1, op2);
+        m_jit.compare32(condition, op1.gpr(), op2.gpr(), result.gpr());
+
+        // If we add a DataFormatBool, we should use it here.
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+        jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
+    }
 }
 
 void SpeculativeJIT::compileInt52Compare(Node* node, MacroAssembler::RelationalCondition condition)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to