Title: [208848] trunk/Source/_javascript_Core
Revision
208848
Author
[email protected]
Date
2016-11-17 09:52:03 -0800 (Thu, 17 Nov 2016)

Log Message

Add support for rotate in B3 and the relevant assemblers
https://bugs.webkit.org/show_bug.cgi?id=164869

Reviewed by Geoffrey Garen.

This patch runs RotR and RotL (rotate right and left respectively)
through B3 and B3's assemblers. One thing of note is that ARM64 does
not support rotate left instead it allows negative right rotations.

This patch also fixes a theoretical bug in the assembler where
on X86 doing someShiftOp(reg, edx) would instead shift the shift
amount by the value. Additionally, this patch refactors some
of the X86 assembler to use templates when deciding how to format
the appropriate shift instruction.

* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::rotateRight32):
(JSC::MacroAssemblerARM64::rotateRight64):
* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::rotateRight32):
(JSC::MacroAssemblerX86Common::rotateLeft32):
* assembler/MacroAssemblerX86_64.h:
(JSC::MacroAssemblerX86_64::lshift64):
(JSC::MacroAssemblerX86_64::rshift64):
(JSC::MacroAssemblerX86_64::urshift64):
(JSC::MacroAssemblerX86_64::rotateRight64):
(JSC::MacroAssemblerX86_64::rotateLeft64):
(JSC::MacroAssemblerX86_64::or64):
* assembler/X86Assembler.h:
(JSC::X86Assembler::xorq_rm):
(JSC::X86Assembler::shiftInstruction32):
(JSC::X86Assembler::sarl_i8r):
(JSC::X86Assembler::shrl_i8r):
(JSC::X86Assembler::shll_i8r):
(JSC::X86Assembler::rorl_i8r):
(JSC::X86Assembler::rorl_CLr):
(JSC::X86Assembler::roll_i8r):
(JSC::X86Assembler::roll_CLr):
(JSC::X86Assembler::shiftInstruction64):
(JSC::X86Assembler::sarq_CLr):
(JSC::X86Assembler::sarq_i8r):
(JSC::X86Assembler::shrq_i8r):
(JSC::X86Assembler::shlq_i8r):
(JSC::X86Assembler::rorq_i8r):
(JSC::X86Assembler::rorq_CLr):
(JSC::X86Assembler::rolq_i8r):
(JSC::X86Assembler::rolq_CLr):
* b3/B3Common.h:
(JSC::B3::rotateRight):
(JSC::B3::rotateLeft):
* b3/B3Const32Value.cpp:
(JSC::B3::Const32Value::rotRConstant):
(JSC::B3::Const32Value::rotLConstant):
* b3/B3Const32Value.h:
* b3/B3Const64Value.cpp:
(JSC::B3::Const64Value::rotRConstant):
(JSC::B3::Const64Value::rotLConstant):
* b3/B3Const64Value.h:
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::lower):
* b3/B3Opcode.cpp:
(WTF::printInternal):
* b3/B3Opcode.h:
* b3/B3ReduceStrength.cpp:
* b3/B3Validate.cpp:
* b3/B3Value.cpp:
(JSC::B3::Value::rotRConstant):
(JSC::B3::Value::rotLConstant):
(JSC::B3::Value::effects):
(JSC::B3::Value::key):
(JSC::B3::Value::typeFor):
* b3/B3Value.h:
* b3/B3ValueKey.cpp:
(JSC::B3::ValueKey::materialize):
* b3/air/AirInstInlines.h:
(JSC::B3::Air::isRotateRight32Valid):
(JSC::B3::Air::isRotateLeft32Valid):
(JSC::B3::Air::isRotateRight64Valid):
(JSC::B3::Air::isRotateLeft64Valid):
* b3/air/AirOpcode.opcodes:
* b3/testb3.cpp:
(JSC::B3::testRotR):
(JSC::B3::testRotL):
(JSC::B3::testRotRWithImmShift):
(JSC::B3::testRotLWithImmShift):
(JSC::B3::run):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (208847 => 208848)


--- trunk/Source/_javascript_Core/ChangeLog	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-11-17 17:52:03 UTC (rev 208848)
@@ -1,3 +1,92 @@
+2016-11-17  Keith Miller  <[email protected]>
+
+        Add support for rotate in B3 and the relevant assemblers
+        https://bugs.webkit.org/show_bug.cgi?id=164869
+
+        Reviewed by Geoffrey Garen.
+
+        This patch runs RotR and RotL (rotate right and left respectively)
+        through B3 and B3's assemblers. One thing of note is that ARM64 does
+        not support rotate left instead it allows negative right rotations.
+
+        This patch also fixes a theoretical bug in the assembler where
+        on X86 doing someShiftOp(reg, edx) would instead shift the shift
+        amount by the value. Additionally, this patch refactors some
+        of the X86 assembler to use templates when deciding how to format
+        the appropriate shift instruction.
+
+        * assembler/MacroAssemblerARM64.h:
+        (JSC::MacroAssemblerARM64::rotateRight32):
+        (JSC::MacroAssemblerARM64::rotateRight64):
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::rotateRight32):
+        (JSC::MacroAssemblerX86Common::rotateLeft32):
+        * assembler/MacroAssemblerX86_64.h:
+        (JSC::MacroAssemblerX86_64::lshift64):
+        (JSC::MacroAssemblerX86_64::rshift64):
+        (JSC::MacroAssemblerX86_64::urshift64):
+        (JSC::MacroAssemblerX86_64::rotateRight64):
+        (JSC::MacroAssemblerX86_64::rotateLeft64):
+        (JSC::MacroAssemblerX86_64::or64):
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::xorq_rm):
+        (JSC::X86Assembler::shiftInstruction32):
+        (JSC::X86Assembler::sarl_i8r):
+        (JSC::X86Assembler::shrl_i8r):
+        (JSC::X86Assembler::shll_i8r):
+        (JSC::X86Assembler::rorl_i8r):
+        (JSC::X86Assembler::rorl_CLr):
+        (JSC::X86Assembler::roll_i8r):
+        (JSC::X86Assembler::roll_CLr):
+        (JSC::X86Assembler::shiftInstruction64):
+        (JSC::X86Assembler::sarq_CLr):
+        (JSC::X86Assembler::sarq_i8r):
+        (JSC::X86Assembler::shrq_i8r):
+        (JSC::X86Assembler::shlq_i8r):
+        (JSC::X86Assembler::rorq_i8r):
+        (JSC::X86Assembler::rorq_CLr):
+        (JSC::X86Assembler::rolq_i8r):
+        (JSC::X86Assembler::rolq_CLr):
+        * b3/B3Common.h:
+        (JSC::B3::rotateRight):
+        (JSC::B3::rotateLeft):
+        * b3/B3Const32Value.cpp:
+        (JSC::B3::Const32Value::rotRConstant):
+        (JSC::B3::Const32Value::rotLConstant):
+        * b3/B3Const32Value.h:
+        * b3/B3Const64Value.cpp:
+        (JSC::B3::Const64Value::rotRConstant):
+        (JSC::B3::Const64Value::rotLConstant):
+        * b3/B3Const64Value.h:
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::lower):
+        * b3/B3Opcode.cpp:
+        (WTF::printInternal):
+        * b3/B3Opcode.h:
+        * b3/B3ReduceStrength.cpp:
+        * b3/B3Validate.cpp:
+        * b3/B3Value.cpp:
+        (JSC::B3::Value::rotRConstant):
+        (JSC::B3::Value::rotLConstant):
+        (JSC::B3::Value::effects):
+        (JSC::B3::Value::key):
+        (JSC::B3::Value::typeFor):
+        * b3/B3Value.h:
+        * b3/B3ValueKey.cpp:
+        (JSC::B3::ValueKey::materialize):
+        * b3/air/AirInstInlines.h:
+        (JSC::B3::Air::isRotateRight32Valid):
+        (JSC::B3::Air::isRotateLeft32Valid):
+        (JSC::B3::Air::isRotateRight64Valid):
+        (JSC::B3::Air::isRotateLeft64Valid):
+        * b3/air/AirOpcode.opcodes:
+        * b3/testb3.cpp:
+        (JSC::B3::testRotR):
+        (JSC::B3::testRotL):
+        (JSC::B3::testRotRWithImmShift):
+        (JSC::B3::testRotLWithImmShift):
+        (JSC::B3::run):
+
 2016-11-17  Saam Barati  <[email protected]>
 
         Remove async/await compile time flag and enable tests

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h (208847 => 208848)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2016-11-17 17:52:03 UTC (rev 208848)
@@ -664,11 +664,36 @@
         m_assembler.orr<64>(dest, dest, dataTempRegister);
     }
 
+    void rotateRight32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.ror<32>(dest, src, imm.m_value & 31);
+    }
+
+    void rotateRight32(TrustedImm32 imm, RegisterID srcDst)
+    {
+        rotateRight32(srcDst, imm, srcDst);
+    }
+
+    void rotateRight32(RegisterID src, RegisterID shiftAmmount, RegisterID dest)
+    {
+        m_assembler.ror<32>(dest, src, shiftAmmount);
+    }
+
+    void rotateRight64(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.ror<64>(dest, src, imm.m_value & 63);
+    }
+
     void rotateRight64(TrustedImm32 imm, RegisterID srcDst)
     {
-        m_assembler.ror<64>(srcDst, srcDst, imm.m_value & 63);
+        rotateRight64(srcDst, imm, srcDst);
     }
 
+    void rotateRight64(RegisterID src, RegisterID shiftAmmount, RegisterID dest)
+    {
+        m_assembler.ror<64>(dest, src, shiftAmmount);
+    }
+
     void rshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
     {
         m_assembler.asr<32>(dest, src, shiftAmount);

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (208847 => 208848)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2016-11-17 17:52:03 UTC (rev 208848)
@@ -566,7 +566,45 @@
         move32IfNeeded(src, dest);
         urshift32(imm, dest);
     }
-    
+
+    void rotateRight32(TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.rorl_i8r(imm.m_value, dest);
+    }
+
+    void rotateRight32(RegisterID src, RegisterID dest)
+    {
+        if (src == X86Registers::ecx)
+            m_assembler.rorl_CLr(dest);
+        else {
+            ASSERT(src != dest);
+
+            // Can only rotate by ecx, so we do some swapping if we see anything else.
+            swap(src, X86Registers::ecx);
+            m_assembler.rorl_CLr(dest == X86Registers::ecx ? src : dest);
+            swap(src, X86Registers::ecx);
+        }
+    }
+
+    void rotateLeft32(TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.roll_i8r(imm.m_value, dest);
+    }
+
+    void rotateLeft32(RegisterID src, RegisterID dest)
+    {
+        if (src == X86Registers::ecx)
+            m_assembler.roll_CLr(dest);
+        else {
+            ASSERT(src != dest);
+
+            // Can only rotate by ecx, so we do some swapping if we see anything else.
+            swap(src, X86Registers::ecx);
+            m_assembler.roll_CLr(dest == X86Registers::ecx ? src : dest);
+            swap(src, X86Registers::ecx);
+        }
+    }
+
     void sub32(RegisterID src, RegisterID dest)
     {
         m_assembler.subl_rr(src, dest);

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h (208847 => 208848)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h	2016-11-17 17:52:03 UTC (rev 208848)
@@ -402,10 +402,10 @@
             m_assembler.shlq_CLr(dest);
         else {
             ASSERT(src != dest);
-            
+
             // Can only shift by ecx, so we do some swapping if we see anything else.
             swap(src, X86Registers::ecx);
-            m_assembler.shlq_CLr(dest);
+            m_assembler.shlq_CLr(dest == X86Registers::ecx ? src : dest);
             swap(src, X86Registers::ecx);
         }
     }
@@ -424,7 +424,7 @@
             
             // Can only shift by ecx, so we do some swapping if we see anything else.
             swap(src, X86Registers::ecx);
-            m_assembler.sarq_CLr(dest);
+            m_assembler.sarq_CLr(dest == X86Registers::ecx ? src : dest);
             swap(src, X86Registers::ecx);
         }
     }
@@ -443,11 +443,49 @@
             
             // Can only shift by ecx, so we do some swapping if we see anything else.
             swap(src, X86Registers::ecx);
-            m_assembler.shrq_CLr(dest);
+            m_assembler.shrq_CLr(dest == X86Registers::ecx ? src : dest);
             swap(src, X86Registers::ecx);
         }
     }
 
+    void rotateRight64(TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.rorq_i8r(imm.m_value, dest);
+    }
+
+    void rotateRight64(RegisterID src, RegisterID dest)
+    {
+        if (src == X86Registers::ecx)
+            m_assembler.rorq_CLr(dest);
+        else {
+            ASSERT(src != dest);
+
+            // Can only rotate by ecx, so we do some swapping if we see anything else.
+            swap(src, X86Registers::ecx);
+            m_assembler.rorq_CLr(dest == X86Registers::ecx ? src : dest);
+            swap(src, X86Registers::ecx);
+        }
+    }
+
+    void rotateLeft64(TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.rolq_i8r(imm.m_value, dest);
+    }
+
+    void rotateLeft64(RegisterID src, RegisterID dest)
+    {
+        if (src == X86Registers::ecx)
+            m_assembler.rolq_CLr(dest);
+        else {
+            ASSERT(src != dest);
+
+            // Can only rotate by ecx, so we do some swapping if we see anything else.
+            swap(src, X86Registers::ecx);
+            m_assembler.rolq_CLr(dest == X86Registers::ecx ? src : dest);
+            swap(src, X86Registers::ecx);
+        }
+    }
+
     void mul64(RegisterID src, RegisterID dest)
     {
         m_assembler.imulq_rr(src, dest);
@@ -542,11 +580,6 @@
         move(src, dest);
         or64(imm, dest);
     }
-    
-    void rotateRight64(TrustedImm32 imm, RegisterID srcDst)
-    {
-        m_assembler.rorq_i8r(imm.m_value, srcDst);
-    }
 
     void sub64(RegisterID src, RegisterID dest)
     {

Modified: trunk/Source/_javascript_Core/assembler/X86Assembler.h (208847 => 208848)


--- trunk/Source/_javascript_Core/assembler/X86Assembler.h	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/assembler/X86Assembler.h	2016-11-17 17:52:03 UTC (rev 208848)
@@ -967,16 +967,6 @@
     {
         m_formatter.oneByteOp64(OP_XOR_EvGv, src, base, offset);
     }
-    
-    void rorq_i8r(int imm, RegisterID dst)
-    {
-        if (imm == 1)
-            m_formatter.oneByteOp64(OP_GROUP2_Ev1, GROUP2_OP_ROR, dst);
-        else {
-            m_formatter.oneByteOp64(OP_GROUP2_EvIb, GROUP2_OP_ROR, dst);
-            m_formatter.immediate8(imm);
-        }
-    }
 
 #endif
 
@@ -1028,16 +1018,24 @@
     }
 #endif
 
-    void sarl_i8r(int imm, RegisterID dst)
+private:
+    template<GroupOpcodeID op>
+    void shiftInstruction32(int imm, RegisterID dst)
     {
         if (imm == 1)
-            m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SAR, dst);
+            m_formatter.oneByteOp(OP_GROUP2_Ev1, op, dst);
         else {
-            m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SAR, dst);
+            m_formatter.oneByteOp(OP_GROUP2_EvIb, op, dst);
             m_formatter.immediate8(imm);
         }
     }
+public:
 
+    void sarl_i8r(int imm, RegisterID dst)
+    {
+        shiftInstruction32<GROUP2_OP_SAR>(imm, dst);
+    }
+
     void sarl_CLr(RegisterID dst)
     {
         m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
@@ -1045,12 +1043,7 @@
     
     void shrl_i8r(int imm, RegisterID dst)
     {
-        if (imm == 1)
-            m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SHR, dst);
-        else {
-            m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SHR, dst);
-            m_formatter.immediate8(imm);
-        }
+        shiftInstruction32<GROUP2_OP_SHR>(imm, dst);
     }
     
     void shrl_CLr(RegisterID dst)
@@ -1060,12 +1053,7 @@
 
     void shll_i8r(int imm, RegisterID dst)
     {
-        if (imm == 1)
-            m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SHL, dst);
-        else {
-            m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SHL, dst);
-            m_formatter.immediate8(imm);
-        }
+        shiftInstruction32<GROUP2_OP_SHL>(imm, dst);
     }
 
     void shll_CLr(RegisterID dst)
@@ -1073,30 +1061,52 @@
         m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHL, dst);
     }
 
-#if CPU(X86_64)
-    void sarq_CLr(RegisterID dst)
+    void rorl_i8r(int imm, RegisterID dst)
     {
-        m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
+        shiftInstruction32<GROUP2_OP_ROR>(imm, dst);
     }
 
-    void sarq_i8r(int imm, RegisterID dst)
+    void rorl_CLr(RegisterID dst)
     {
+        m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_ROR, dst);
+    }
+
+    void roll_i8r(int imm, RegisterID dst)
+    {
+        shiftInstruction32<GROUP2_OP_ROL>(imm, dst);
+    }
+
+    void roll_CLr(RegisterID dst)
+    {
+        m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_ROL, dst);
+    }
+
+#if CPU(X86_64)
+private:
+    template<GroupOpcodeID op>
+    void shiftInstruction64(int imm, RegisterID dst)
+    {
         if (imm == 1)
-            m_formatter.oneByteOp64(OP_GROUP2_Ev1, GROUP2_OP_SAR, dst);
+            m_formatter.oneByteOp64(OP_GROUP2_Ev1, op, dst);
         else {
-            m_formatter.oneByteOp64(OP_GROUP2_EvIb, GROUP2_OP_SAR, dst);
+            m_formatter.oneByteOp64(OP_GROUP2_EvIb, op, dst);
             m_formatter.immediate8(imm);
         }
     }
+public:
+    void sarq_CLr(RegisterID dst)
+    {
+        m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
+    }
 
+    void sarq_i8r(int imm, RegisterID dst)
+    {
+        shiftInstruction64<GROUP2_OP_SAR>(imm, dst);
+    }
+
     void shrq_i8r(int imm, RegisterID dst)
     {
-        if (imm == 1)
-            m_formatter.oneByteOp64(OP_GROUP2_Ev1, GROUP2_OP_SHR, dst);
-        else {
-            m_formatter.oneByteOp64(OP_GROUP2_EvIb, GROUP2_OP_SHR, dst);
-            m_formatter.immediate8(imm);
-        }
+        shiftInstruction64<GROUP2_OP_SHR>(imm, dst);
     }
 
     void shrq_CLr(RegisterID dst)
@@ -1106,12 +1116,7 @@
 
     void shlq_i8r(int imm, RegisterID dst)
     {
-        if (imm == 1)
-            m_formatter.oneByteOp64(OP_GROUP2_Ev1, GROUP2_OP_SHL, dst);
-        else {
-            m_formatter.oneByteOp64(OP_GROUP2_EvIb, GROUP2_OP_SHL, dst);
-            m_formatter.immediate8(imm);
-        }
+        shiftInstruction64<GROUP2_OP_SHL>(imm, dst);
     }
 
     void shlq_CLr(RegisterID dst)
@@ -1118,6 +1123,26 @@
     {
         m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SHL, dst);
     }
+
+    void rorq_i8r(int imm, RegisterID dst)
+    {
+        shiftInstruction64<GROUP2_OP_ROR>(imm, dst);
+    }
+
+    void rorq_CLr(RegisterID dst)
+    {
+        m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_ROR, dst);
+    }
+
+    void rolq_i8r(int imm, RegisterID dst)
+    {
+        shiftInstruction64<GROUP2_OP_ROL>(imm, dst);
+    }
+
+    void rolq_CLr(RegisterID dst)
+    {
+        m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_ROL, dst);
+    }
 #endif // CPU(X86_64)
 
     void imull_rr(RegisterID src, RegisterID dst)

Modified: trunk/Source/_javascript_Core/b3/B3Common.h (208847 => 208848)


--- trunk/Source/_javascript_Core/b3/B3Common.h	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/b3/B3Common.h	2016-11-17 17:52:03 UTC (rev 208848)
@@ -148,6 +148,28 @@
     return unsignedNumerator % unsignedDenominator;
 }
 
+template<typename IntType>
+static IntType rotateRight(IntType value, int32_t shift)
+{
+    typedef typename std::make_unsigned<IntType>::type UnsignedIntType;
+    UnsignedIntType uValue = static_cast<UnsignedIntType>(value);
+    int32_t bits = sizeof(IntType) * 8;
+    int32_t mask = bits - 1;
+    shift &= mask;
+    return (uValue >> shift) | (uValue << ((bits - shift) & mask));
+}
+
+template<typename IntType>
+static IntType rotateLeft(IntType value, int32_t shift)
+{
+    typedef typename std::make_unsigned<IntType>::type UnsignedIntType;
+    UnsignedIntType uValue = static_cast<UnsignedIntType>(value);
+    int32_t bits = sizeof(IntType) * 8;
+    int32_t mask = bits - 1;
+    shift &= mask;
+    return (uValue << shift) | (uValue >> ((bits - shift) & mask));
+}
+
 } } // namespace JSC::B3
 
 #endif // ENABLE(B3_JIT)

Modified: trunk/Source/_javascript_Core/b3/B3Const32Value.cpp (208847 => 208848)


--- trunk/Source/_javascript_Core/b3/B3Const32Value.cpp	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/b3/B3Const32Value.cpp	2016-11-17 17:52:03 UTC (rev 208848)
@@ -175,6 +175,20 @@
     return proc.add<Const32Value>(origin(), static_cast<int32_t>(static_cast<uint32_t>(m_value) >> (other->asInt32() & 31)));
 }
 
+Value* Const32Value::rotRConstant(Procedure& proc, const Value* other) const
+{
+    if (!other->hasInt32())
+        return nullptr;
+    return proc.add<Const32Value>(origin(), rotateRight(m_value, other->asInt32()));
+}
+
+Value* Const32Value::rotLConstant(Procedure& proc, const Value* other) const
+{
+    if (!other->hasInt32())
+        return nullptr;
+    return proc.add<Const32Value>(origin(), rotateLeft(m_value, other->asInt32()));
+}
+
 Value* Const32Value::bitwiseCastConstant(Procedure& proc) const
 {
     return proc.add<ConstFloatValue>(origin(), bitwise_cast<float>(m_value));

Modified: trunk/Source/_javascript_Core/b3/B3Const32Value.h (208847 => 208848)


--- trunk/Source/_javascript_Core/b3/B3Const32Value.h	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/b3/B3Const32Value.h	2016-11-17 17:52:03 UTC (rev 208848)
@@ -58,6 +58,8 @@
     Value* shlConstant(Procedure&, const Value* other) const override;
     Value* sShrConstant(Procedure&, const Value* other) const override;
     Value* zShrConstant(Procedure&, const Value* other) const override;
+    Value* rotRConstant(Procedure&, const Value* other) const override;
+    Value* rotLConstant(Procedure&, const Value* other) const override;
     Value* bitwiseCastConstant(Procedure&) const override;
     Value* iToDConstant(Procedure&) const override;
     Value* iToFConstant(Procedure&) const override;

Modified: trunk/Source/_javascript_Core/b3/B3Const64Value.cpp (208847 => 208848)


--- trunk/Source/_javascript_Core/b3/B3Const64Value.cpp	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/b3/B3Const64Value.cpp	2016-11-17 17:52:03 UTC (rev 208848)
@@ -175,6 +175,20 @@
     return proc.add<Const64Value>(origin(), static_cast<int64_t>(static_cast<uint64_t>(m_value) >> (other->asInt32() & 63)));
 }
 
+Value* Const64Value::rotRConstant(Procedure& proc, const Value* other) const
+{
+    if (!other->hasInt32())
+        return nullptr;
+    return proc.add<Const64Value>(origin(), rotateRight(m_value, other->asInt32()));
+}
+
+Value* Const64Value::rotLConstant(Procedure& proc, const Value* other) const
+{
+    if (!other->hasInt32())
+        return nullptr;
+    return proc.add<Const64Value>(origin(), rotateLeft(m_value, other->asInt32()));
+}
+
 Value* Const64Value::bitwiseCastConstant(Procedure& proc) const
 {
     return proc.add<ConstDoubleValue>(origin(), bitwise_cast<double>(m_value));

Modified: trunk/Source/_javascript_Core/b3/B3Const64Value.h (208847 => 208848)


--- trunk/Source/_javascript_Core/b3/B3Const64Value.h	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/b3/B3Const64Value.h	2016-11-17 17:52:03 UTC (rev 208848)
@@ -58,6 +58,8 @@
     Value* shlConstant(Procedure&, const Value* other) const override;
     Value* sShrConstant(Procedure&, const Value* other) const override;
     Value* zShrConstant(Procedure&, const Value* other) const override;
+    Value* rotRConstant(Procedure&, const Value* other) const override;
+    Value* rotLConstant(Procedure&, const Value* other) const override;
     Value* bitwiseCastConstant(Procedure&) const override;
     Value* iToDConstant(Procedure&) const override;
     Value* iToFConstant(Procedure&) const override;

Modified: trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp (208847 => 208848)


--- trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2016-11-17 17:52:03 UTC (rev 208848)
@@ -2191,6 +2191,16 @@
             return;
         }
 
+        case RotR: {
+            appendShift<RotateRight32, RotateRight64>(m_value->child(0), m_value->child(1));
+            return;
+        }
+
+        case RotL: {
+            appendShift<RotateLeft32, RotateLeft64>(m_value->child(0), m_value->child(1));
+            return;
+        }
+
         case Clz: {
             appendUnOp<CountLeadingZeros32, CountLeadingZeros64>(m_value->child(0));
             return;

Modified: trunk/Source/_javascript_Core/b3/B3Opcode.cpp (208847 => 208848)


--- trunk/Source/_javascript_Core/b3/B3Opcode.cpp	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/b3/B3Opcode.cpp	2016-11-17 17:52:03 UTC (rev 208848)
@@ -152,6 +152,12 @@
     case ZShr:
         out.print("ZShr");
         return;
+    case RotR:
+        out.print("RotR");
+        return;
+    case RotL:
+        out.print("RotL");
+        return;
     case Clz:
         out.print("Clz");
         return;

Modified: trunk/Source/_javascript_Core/b3/B3Opcode.h (208847 => 208848)


--- trunk/Source/_javascript_Core/b3/B3Opcode.h	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/b3/B3Opcode.h	2016-11-17 17:52:03 UTC (rev 208848)
@@ -95,6 +95,8 @@
     Shl,
     SShr, // Arithmetic Shift.
     ZShr, // Logical Shift.
+    RotR, // Rotate Right.
+    RotL, // Rotate Left.
     Clz, // Count leading zeros.
 
     // Floating point math.

Modified: trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp (208847 => 208848)


--- trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp	2016-11-17 17:52:03 UTC (rev 208848)
@@ -1069,9 +1069,7 @@
                 break;
             }
 
-            if (handleShiftAmount())
-                break;
-
+            handleShiftAmount();
             break;
 
         case SShr:
@@ -1131,9 +1129,7 @@
                     break;
             }
 
-            if (handleShiftAmount())
-                break;
-
+            handleShiftAmount();
             break;
 
         case ZShr:
@@ -1144,11 +1140,41 @@
                 break;
             }
 
-            if (handleShiftAmount())
+            handleShiftAmount();
+            break;
+
+        case RotR:
+            // Turn this: RotR(constant1, constant2)
+            // Into this: (constant1 >> constant2) | (constant1 << sizeof(constant1) * 8 - constant2)
+            if (Value* constant = m_value->child(0)->rotRConstant(m_proc, m_value->child(1))) {
+                replaceWithNewValue(constant);
                 break;
+            }
 
+            handleShiftAmount();
             break;
 
+        case RotL:
+            // Turn this: RotL(constant1, constant2)
+            // Into this: (constant1 << constant2) | (constant1 >> sizeof(constant1) * 8 - constant2)
+            if (Value* constant = m_value->child(0)->rotLConstant(m_proc, m_value->child(1))) {
+                replaceWithNewValue(constant);
+                break;
+            }
+
+            // ARM64 only has rotate right.
+            // Turn this: RotL(value, shift)
+            // Into this: RotR(value, Neg(shift))
+            if (isARM64()) {
+                Value* newShift = m_insertionSet.insert<Value>(m_index, Neg, m_value->origin(), m_value->child(1));
+                Value* rotate = m_insertionSet.insert<Value>(m_index, RotR, m_value->origin(), m_value->child(0), newShift);
+                replaceWithIdentity(rotate);
+                break;
+            }
+
+            handleShiftAmount();
+            break;
+
         case Abs:
             // Turn this: Abs(constant)
             // Into this: fabs<value->type()>(constant)
@@ -2184,12 +2210,12 @@
         m_changed = true;
     }
 
-    bool handleShiftAmount()
+    void handleShiftAmount()
     {
         // Shift anything by zero is identity.
         if (m_value->child(1)->isInt32(0)) {
             replaceWithIdentity(m_value->child(0));
-            return true;
+            return;
         }
 
         // The shift already masks its shift amount. If the shift amount is being masked by a
@@ -2202,11 +2228,7 @@
             && (m_value->child(1)->child(1)->asInt32() & mask) == mask) {
             m_value->child(1) = m_value->child(1)->child(0);
             m_changed = true;
-            // Don't need to return true, since we're still the same shift, and we can still cascade
-            // through other optimizations.
         }
-        
-        return false;
     }
 
     void replaceIfRedundant()

Modified: trunk/Source/_javascript_Core/b3/B3Validate.cpp (208847 => 208848)


--- trunk/Source/_javascript_Core/b3/B3Validate.cpp	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/b3/B3Validate.cpp	2016-11-17 17:52:03 UTC (rev 208848)
@@ -229,6 +229,8 @@
             case Shl:
             case SShr:
             case ZShr:
+            case RotR:
+                case RotL:
                 VALIDATE(!value->kind().hasExtraBits(), ("At ", *value));
                 VALIDATE(value->numChildren() == 2, ("At ", *value));
                 VALIDATE(value->type() == value->child(0)->type(), ("At ", *value));

Modified: trunk/Source/_javascript_Core/b3/B3Value.cpp (208847 => 208848)


--- trunk/Source/_javascript_Core/b3/B3Value.cpp	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/b3/B3Value.cpp	2016-11-17 17:52:03 UTC (rev 208848)
@@ -343,6 +343,16 @@
     return nullptr;
 }
 
+Value* Value::rotRConstant(Procedure&, const Value*) const
+{
+    return nullptr;
+}
+
+Value* Value::rotLConstant(Procedure&, const Value*) const
+{
+    return nullptr;
+}
+
 Value* Value::bitwiseCastConstant(Procedure&) const
 {
     return nullptr;
@@ -550,6 +560,8 @@
     case Shl:
     case SShr:
     case ZShr:
+    case RotR:
+    case RotL:
     case Clz:
     case Abs:
     case Ceil:
@@ -696,6 +708,8 @@
     case Shl:
     case SShr:
     case ZShr:
+    case RotR:
+    case RotL:
     case Equal:
     case NotEqual:
     case LessThan:
@@ -777,6 +791,8 @@
     case Shl:
     case SShr:
     case ZShr:
+    case RotR:
+    case RotL:
     case Clz:
     case Abs:
     case Ceil:

Modified: trunk/Source/_javascript_Core/b3/B3Value.h (208847 => 208848)


--- trunk/Source/_javascript_Core/b3/B3Value.h	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/b3/B3Value.h	2016-11-17 17:52:03 UTC (rev 208848)
@@ -175,6 +175,8 @@
     virtual Value* shlConstant(Procedure&, const Value* other) const;
     virtual Value* sShrConstant(Procedure&, const Value* other) const;
     virtual Value* zShrConstant(Procedure&, const Value* other) const;
+    virtual Value* rotRConstant(Procedure&, const Value* other) const;
+    virtual Value* rotLConstant(Procedure&, const Value* other) const;
     virtual Value* bitwiseCastConstant(Procedure&) const;
     virtual Value* iToDConstant(Procedure&) const;
     virtual Value* iToFConstant(Procedure&) const;
@@ -333,6 +335,8 @@
         case Shl:
         case SShr:
         case ZShr:
+        case RotR:
+        case RotL:
         case Equal:
         case NotEqual:
         case LessThan:

Modified: trunk/Source/_javascript_Core/b3/B3ValueKey.cpp (208847 => 208848)


--- trunk/Source/_javascript_Core/b3/B3ValueKey.cpp	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/b3/B3ValueKey.cpp	2016-11-17 17:52:03 UTC (rev 208848)
@@ -86,6 +86,8 @@
     case Shl:
     case SShr:
     case ZShr:
+    case RotR:
+    case RotL:
     case Equal:
     case NotEqual:
     case LessThan:

Modified: trunk/Source/_javascript_Core/b3/air/AirInstInlines.h (208847 => 208848)


--- trunk/Source/_javascript_Core/b3/air/AirInstInlines.h	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/b3/air/AirInstInlines.h	2016-11-17 17:52:03 UTC (rev 208848)
@@ -214,6 +214,26 @@
     return isShiftValid(inst);
 }
 
+inline bool isRotateRight32Valid(const Inst& inst)
+{
+    return isShiftValid(inst);
+}
+
+inline bool isRotateLeft32Valid(const Inst& inst)
+{
+    return isShiftValid(inst);
+}
+
+inline bool isRotateRight64Valid(const Inst& inst)
+{
+    return isShiftValid(inst);
+}
+
+inline bool isRotateLeft64Valid(const Inst& inst)
+{
+    return isShiftValid(inst);
+}
+
 inline bool isX86DivHelperValid(const Inst& inst)
 {
 #if CPU(X86) || CPU(X86_64)

Modified: trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes (208847 => 208848)


--- trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes	2016-11-17 17:52:03 UTC (rev 208848)
@@ -373,7 +373,7 @@
     Tmp*, Tmp
     Imm, Tmp
 
-arm64: Lshift64 U:G:64, U:G:64, ZD:G:64
+arm64: Lshift64 U:G:64, U:G:64, D:G:64
     Tmp, Tmp, Tmp
     Tmp, Imm, Tmp
 
@@ -389,7 +389,7 @@
     Tmp*, Tmp
     Imm, Tmp
 
-arm64: Rshift64 U:G:64, U:G:64, ZD:G:64
+arm64: Rshift64 U:G:64, U:G:64, D:G:64
     Tmp, Tmp, Tmp
     Tmp, Imm, Tmp
 
@@ -405,7 +405,7 @@
     Tmp*, Tmp
     Imm, Tmp
 
-arm64: Urshift64 U:G:64, U:G:64, ZD:G:64
+arm64: Urshift64 U:G:64, U:G:64, D:G:64
     Tmp, Tmp, Tmp
     Tmp, Imm, Tmp
 
@@ -413,6 +413,30 @@
     Tmp*, Tmp
     Imm, Tmp
 
+x86_64: RotateRight32 U:G:32, UZD:G:32
+    Tmp*, Tmp
+    Imm, Tmp
+
+arm64: RotateRight32 U:G:32, U:G:32, ZD:G:32
+    Tmp, Tmp, Tmp
+    Tmp, Imm, Tmp
+
+x86_64: RotateRight64 U:G:64, UD:G:64
+    Tmp*, Tmp
+    Imm, Tmp
+
+arm64: RotateRight64 U:G:64, U:G:64, D:G:64
+    Tmp, Tmp, Tmp
+    Tmp, Imm, Tmp
+
+x86_64: RotateLeft32 U:G:32, UZD:G:32
+    Tmp*, Tmp
+    Imm, Tmp
+
+x86_64: RotateLeft64 U:G:64, UD:G:64
+    Tmp*, Tmp
+    Imm, Tmp
+
 Or32 U:G:32, U:G:32, ZD:G:32
     Tmp, Tmp, Tmp
     arm64: BitImm, Tmp, Tmp

Modified: trunk/Source/_javascript_Core/b3/testb3.cpp (208847 => 208848)


--- trunk/Source/_javascript_Core/b3/testb3.cpp	2016-11-17 17:28:52 UTC (rev 208847)
+++ trunk/Source/_javascript_Core/b3/testb3.cpp	2016-11-17 17:52:03 UTC (rev 208848)
@@ -11959,6 +11959,76 @@
 }
 
 template<typename T>
+void testRotR(T valueInt, int32_t shift)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    if (sizeof(T) == 4)
+        value = root->appendNew<Value>(proc, Trunc, Origin(), value);
+
+    Value* ammount = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+    root->appendNewControlValue(proc, Return, Origin(),
+        root->appendNew<Value>(proc, RotR, Origin(), value, ammount));
+
+    CHECK_EQ(compileAndRun<T>(proc, valueInt, shift), rotateRight(valueInt, shift));
+}
+
+template<typename T>
+void testRotL(T valueInt, int32_t shift)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    if (sizeof(T) == 4)
+        value = root->appendNew<Value>(proc, Trunc, Origin(), value);
+
+    Value* ammount = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+    root->appendNewControlValue(proc, Return, Origin(),
+        root->appendNew<Value>(proc, RotL, Origin(), value, ammount));
+
+    CHECK_EQ(compileAndRun<T>(proc, valueInt, shift), rotateLeft(valueInt, shift));
+}
+
+template<typename T>
+void testRotRWithImmShift(T valueInt, int32_t shift)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    if (sizeof(T) == 4)
+        value = root->appendNew<Value>(proc, Trunc, Origin(), value);
+
+    Value* ammount = root->appendIntConstant(proc, Origin(), Int32, shift);
+    root->appendNewControlValue(proc, Return, Origin(),
+        root->appendNew<Value>(proc, RotR, Origin(), value, ammount));
+
+    CHECK_EQ(compileAndRun<T>(proc, valueInt, shift), rotateRight(valueInt, shift));
+}
+
+template<typename T>
+void testRotLWithImmShift(T valueInt, int32_t shift)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    if (sizeof(T) == 4)
+        value = root->appendNew<Value>(proc, Trunc, Origin(), value);
+
+    Value* ammount = root->appendIntConstant(proc, Origin(), Int32, shift);
+    root->appendNewControlValue(proc, Return, Origin(),
+        root->appendNew<Value>(proc, RotL, Origin(), value, ammount));
+
+    CHECK_EQ(compileAndRun<T>(proc, valueInt, shift), rotateLeft(valueInt, shift));
+}
+
+template<typename T>
 void testComputeDivisionMagic(T value, T magicMultiplier, unsigned shift)
 {
     DivisionMagic<T> magic = computeDivisionMagic(value);
@@ -15293,6 +15363,16 @@
 
     RUN(testCheckMul64SShr());
 
+    RUN_BINARY(testRotR, int32Operands(), int32Operands());
+    RUN_BINARY(testRotR, int64Operands(), int32Operands());
+    RUN_BINARY(testRotL, int32Operands(), int32Operands());
+    RUN_BINARY(testRotL, int64Operands(), int32Operands());
+
+    RUN_BINARY(testRotRWithImmShift, int32Operands(), int32Operands());
+    RUN_BINARY(testRotRWithImmShift, int64Operands(), int32Operands());
+    RUN_BINARY(testRotLWithImmShift, int32Operands(), int32Operands());
+    RUN_BINARY(testRotLWithImmShift, int64Operands(), int32Operands());
+
     RUN(testComputeDivisionMagic<int32_t>(2, -2147483647, 0));
     RUN(testTrivialInfiniteLoop());
     RUN(testFoldPathEqual());
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to