Title: [192696] trunk/Source/_javascript_Core
Revision
192696
Author
benja...@webkit.org
Date
2015-11-20 14:07:05 -0800 (Fri, 20 Nov 2015)

Log Message

[JSC] Add Air lowering to BitNot() for Xor(value, -1)
https://bugs.webkit.org/show_bug.cgi?id=151474

Patch by Benjamin Poulain <bpoul...@apple.com> on 2015-11-20
Reviewed by Filip Pizlo.

* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::not32):
* assembler/MacroAssemblerX86_64.h:
(JSC::MacroAssemblerX86_64::not64):
* assembler/X86Assembler.h:
(JSC::X86Assembler::notq_r):
(JSC::X86Assembler::notq_m):
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::createGenericCompare):
(JSC::B3::Air::LowerToAir::lower):
* b3/B3ReduceStrength.cpp:
* b3/air/AirOpcode.opcodes:
* b3/testb3.cpp:
(JSC::B3::testNegValueSubOne):
(JSC::B3::testNegValueSubOne32):
(JSC::B3::testBitNotArg):
(JSC::B3::testBitNotImm):
(JSC::B3::testBitNotMem):
(JSC::B3::testBitNotArg32):
(JSC::B3::testBitNotImm32):
(JSC::B3::testBitNotMem32):
(JSC::B3::testBitNotOnBooleanAndBranch32):
(JSC::B3::int64Operands):
(JSC::B3::int32Operands):
(JSC::B3::run):
* ftl/FTLB3Output.h:
(JSC::FTL::Output::bitNot):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (192695 => 192696)


--- trunk/Source/_javascript_Core/ChangeLog	2015-11-20 21:19:57 UTC (rev 192695)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-11-20 22:07:05 UTC (rev 192696)
@@ -1,3 +1,38 @@
+2015-11-20  Benjamin Poulain  <bpoul...@apple.com>
+
+        [JSC] Add Air lowering to BitNot() for Xor(value, -1)
+        https://bugs.webkit.org/show_bug.cgi?id=151474
+
+        Reviewed by Filip Pizlo.
+
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::not32):
+        * assembler/MacroAssemblerX86_64.h:
+        (JSC::MacroAssemblerX86_64::not64):
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::notq_r):
+        (JSC::X86Assembler::notq_m):
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::createGenericCompare):
+        (JSC::B3::Air::LowerToAir::lower):
+        * b3/B3ReduceStrength.cpp:
+        * b3/air/AirOpcode.opcodes:
+        * b3/testb3.cpp:
+        (JSC::B3::testNegValueSubOne):
+        (JSC::B3::testNegValueSubOne32):
+        (JSC::B3::testBitNotArg):
+        (JSC::B3::testBitNotImm):
+        (JSC::B3::testBitNotMem):
+        (JSC::B3::testBitNotArg32):
+        (JSC::B3::testBitNotImm32):
+        (JSC::B3::testBitNotMem32):
+        (JSC::B3::testBitNotOnBooleanAndBranch32):
+        (JSC::B3::int64Operands):
+        (JSC::B3::int32Operands):
+        (JSC::B3::run):
+        * ftl/FTLB3Output.h:
+        (JSC::FTL::Output::bitNot):
+
 2015-11-20  Yusuke Suzuki  <utatane....@gmail.com>
 
         Super use should be recorded in per-function scope

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (192695 => 192696)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2015-11-20 21:19:57 UTC (rev 192695)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2015-11-20 22:07:05 UTC (rev 192696)
@@ -481,6 +481,16 @@
         xor32(imm, dest);
     }
 
+    void not32(RegisterID srcDest)
+    {
+        m_assembler.notl_r(srcDest);
+    }
+
+    void not32(Address dest)
+    {
+        m_assembler.notl_m(dest.offset, dest.base);
+    }
+
     void sqrtDouble(FPRegisterID src, FPRegisterID dst)
     {
         m_assembler.sqrtsd_rr(src, dst);

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h (192695 => 192696)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h	2015-11-20 21:19:57 UTC (rev 192695)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h	2015-11-20 22:07:05 UTC (rev 192696)
@@ -502,6 +502,16 @@
         m_assembler.xorq_ir(imm.m_value, srcDest);
     }
 
+    void not64(RegisterID srcDest)
+    {
+        m_assembler.notq_r(srcDest);
+    }
+
+    void not64(Address dest)
+    {
+        m_assembler.notq_m(dest.offset, dest.base);
+    }
+
     void load64(ImplicitAddress address, RegisterID dest)
     {
         m_assembler.movq_mr(address.offset, address.base, dest);

Modified: trunk/Source/_javascript_Core/assembler/X86Assembler.h (192695 => 192696)


--- trunk/Source/_javascript_Core/assembler/X86Assembler.h	2015-11-20 21:19:57 UTC (rev 192695)
+++ trunk/Source/_javascript_Core/assembler/X86Assembler.h	2015-11-20 22:07:05 UTC (rev 192696)
@@ -622,6 +622,18 @@
         m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NOT, base, offset);
     }
 
+#if CPU(X86_64)
+    void notq_r(RegisterID dst)
+    {
+        m_formatter.oneByteOp64(OP_GROUP3_Ev, GROUP3_OP_NOT, dst);
+    }
+
+    void notq_m(int offset, RegisterID base)
+    {
+        m_formatter.oneByteOp64(OP_GROUP3_Ev, GROUP3_OP_NOT, base, offset);
+    }
+#endif
+
     void orl_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp(OP_OR_EvGv, src, dst);

Modified: trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp (192695 => 192696)


--- trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2015-11-20 21:19:57 UTC (rev 192695)
+++ trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2015-11-20 22:07:05 UTC (rev 192696)
@@ -804,7 +804,7 @@
             if (!canBeInternal(value) && value != m_value)
                 break;
             bool shouldInvert =
-                (value->opcode() == BitXor && value->child(1)->isInt(1) && value->child(0)->returnsBool())
+                (value->opcode() == BitXor && value->child(1)->hasInt() && (value->child(1)->asInt() & 1) && value->child(0)->returnsBool())
                 || (value->opcode() == Equal && value->child(1)->isInt(0));
             if (!shouldInvert)
                 break;
@@ -1315,6 +1315,10 @@
         }
 
         case BitXor: {
+            if (m_value->child(1)->isInt(-1)) {
+                appendUnOp<Not32, Not64, Air::Oops>(m_value->child(0));
+                return;
+            }
             appendBinOp<Xor32, Xor64, Air::Oops, Commutative>(
                 m_value->child(0), m_value->child(1));
             return;
@@ -1370,6 +1374,14 @@
                     matched = tryAppendStoreBinOp<And32, And64, Commutative>(
                         valueToStore->child(0), valueToStore->child(1));
                     break;
+                case BitXor:
+                    if (valueToStore->child(1)->isInt(-1)) {
+                        matched = tryAppendStoreUnOp<Not32, Not64>(valueToStore->child(0));
+                        break;
+                    }
+                    matched = tryAppendStoreBinOp<Xor32, Xor64, Commutative>(
+                        valueToStore->child(0), valueToStore->child(1));
+                    break;
                 default:
                     break;
                 }

Modified: trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp (192695 => 192696)


--- trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp	2015-11-20 21:19:57 UTC (rev 192695)
+++ trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp	2015-11-20 22:07:05 UTC (rev 192696)
@@ -180,6 +180,17 @@
                 m_changed = true;
                 break;
             }
+
+            // Turn this: Integer Add(Sub(0, value), -1)
+            // Into this: BitXor(value, -1)
+            if (m_value->isInteger()
+                && m_value->child(0)->opcode() == Sub
+                && m_value->child(1)->isInt(-1)
+                && m_value->child(0)->child(0)->isInt(0)) {
+                replaceWithNewValue(m_proc.add<Value>(BitXor, m_value->origin(), m_value->child(0)->child(1), m_value->child(1)));
+                break;
+            }
+
             break;
 
         case Sub:

Modified: trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes (192695 => 192696)


--- trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes	2015-11-20 21:19:57 UTC (rev 192695)
+++ trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes	2015-11-20 22:07:05 UTC (rev 192696)
@@ -195,6 +195,14 @@
     Tmp, Addr
     Imm, Tmp
 
+Not32 UD:G
+    Tmp
+    Addr
+
+Not64 UD:G
+    Tmp
+    Addr
+
 ConvertInt32ToDouble U:G, D:F
     Tmp, Tmp
     Addr, Tmp

Modified: trunk/Source/_javascript_Core/b3/testb3.cpp (192695 => 192696)


--- trunk/Source/_javascript_Core/b3/testb3.cpp	2015-11-20 21:19:57 UTC (rev 192695)
+++ trunk/Source/_javascript_Core/b3/testb3.cpp	2015-11-20 22:07:05 UTC (rev 192696)
@@ -600,6 +600,21 @@
     CHECK(compileAndRun<int64_t>(proc, a) == a - b);
 }
 
+void testNegValueSubOne(int a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    Value* negArgument = root->appendNew<Value>(proc, Sub, Origin(),
+        root->appendNew<Const64Value>(proc, Origin(), 0),
+        argument);
+    Value* negArgumentMinusOne = root->appendNew<Value>(proc, Sub, Origin(),
+        negArgument,
+        root->appendNew<Const64Value>(proc, Origin(), 1));
+    root->appendNew<ControlValue>(proc, Return, Origin(), negArgumentMinusOne);
+    CHECK(compileAndRun<int>(proc, a) == -a - 1);
+}
+
 void testSubImmArg(int a, int b)
 {
     Procedure proc;
@@ -664,6 +679,22 @@
     CHECK(compileAndRun<int>(proc, b) == a - b);
 }
 
+void testNegValueSubOne32(int a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* negArgument = root->appendNew<Value>(proc, Sub, Origin(),
+        root->appendNew<Const32Value>(proc, Origin(), 0),
+        argument);
+    Value* negArgumentMinusOne = root->appendNew<Value>(proc, Sub, Origin(),
+        negArgument,
+        root->appendNew<Const32Value>(proc, Origin(), 1));
+    root->appendNew<ControlValue>(proc, Return, Origin(), negArgumentMinusOne);
+    CHECK(compileAndRun<int>(proc, a) == -a - 1);
+}
+
 void testSubArgDouble(double a)
 {
     Procedure proc;
@@ -1411,6 +1442,129 @@
     CHECK(compileAndRun<int>(proc, b) == (a ^ (b ^ c)));
 }
 
+void testBitNotArg(int64_t a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    root->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        root->appendNew<Value>(
+            proc, BitXor, Origin(),
+            root->appendNew<Const64Value>(proc, Origin(), -1),
+            root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
+
+    CHECK(isIdentical(compileAndRun<int64_t>(proc, a), static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
+}
+
+void testBitNotImm(int64_t a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    root->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        root->appendNew<Value>(
+            proc, BitXor, Origin(),
+            root->appendNew<Const64Value>(proc, Origin(), -1),
+            root->appendNew<Const64Value>(proc, Origin(), a)));
+
+    CHECK(isIdentical(compileAndRun<int64_t>(proc, a), static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
+}
+
+void testBitNotMem(int64_t a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
+    Value* notLoad = root->appendNew<Value>(proc, BitXor, Origin(),
+        root->appendNew<Const64Value>(proc, Origin(), -1),
+        load);
+    root->appendNew<MemoryValue>(proc, Store, Origin(), notLoad, address);
+    root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
+
+    int64_t input = a;
+    compileAndRun<int32_t>(proc, &input);
+    CHECK(isIdentical(input, static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
+}
+
+void testBitNotArg32(int32_t a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    root->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        root->appendNew<Value>(proc, BitXor, Origin(),
+            root->appendNew<Const32Value>(proc, Origin(), -1),
+            argument));
+    CHECK(isIdentical(compileAndRun<int32_t>(proc, a), static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
+}
+
+void testBitNotImm32(int32_t a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    root->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        root->appendNew<Value>(
+            proc, BitXor, Origin(),
+            root->appendNew<Const32Value>(proc, Origin(), -1),
+            root->appendNew<Const32Value>(proc, Origin(), a)));
+
+    CHECK(isIdentical(compileAndRun<int32_t>(proc, a), static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
+}
+
+void testBitNotMem32(int32_t a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
+    Value* notLoad = root->appendNew<Value>(proc, BitXor, Origin(),
+        root->appendNew<Const32Value>(proc, Origin(), -1),
+        load);
+    root->appendNew<MemoryValue>(proc, Store, Origin(), notLoad, address);
+    root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
+
+    int32_t input = a;
+    compileAndRun<int32_t>(proc, &input);
+    CHECK(isIdentical(input, static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
+}
+
+void testBitNotOnBooleanAndBranch32(int64_t a, int64_t b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    BasicBlock* thenCase = proc.addBlock();
+    BasicBlock* elseCase = proc.addBlock();
+
+    Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* argsAreEqual = root->appendNew<Value>(proc, Equal, Origin(), arg1, arg2);
+    Value* argsAreNotEqual = root->appendNew<Value>(proc, BitXor, Origin(),
+        root->appendNew<Const32Value>(proc, Origin(), -1),
+        argsAreEqual);
+
+    root->appendNew<ControlValue>(
+        proc, Branch, Origin(),
+        argsAreNotEqual,
+        FrequentedBlock(thenCase), FrequentedBlock(elseCase));
+
+    thenCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        thenCase->appendNew<Const32Value>(proc, Origin(), 42));
+
+    elseCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        elseCase->appendNew<Const32Value>(proc, Origin(), -42));
+
+    int32_t expectedValue = (a != b) ? 42 : -42;
+    CHECK(compileAndRun<int32_t>(proc, a, b) == expectedValue);
+}
+
 void testShlArgs(int64_t a, int64_t b)
 {
     Procedure proc;
@@ -4762,6 +4916,7 @@
 
 typedef Operand<double> DoubleOperand;
 typedef Operand<int64_t> Int64Operand;
+typedef Operand<int32_t> Int32Operand;
 
 static const std::array<DoubleOperand, 9>& doubleOperands()
 {
@@ -4784,9 +4939,30 @@
     Vector<Int64Operand> operands;
     for (DoubleOperand doubleOperand : doubleOperands())
         operands.append({ doubleOperand.name, bitwise_cast<int64_t>(doubleOperand.value) });
+    operands.append({ "1", 1 });
+    operands.append({ "-1", -1 });
+    operands.append({ "int64-max", std::numeric_limits<int64_t>::max() });
+    operands.append({ "int64-min", std::numeric_limits<int64_t>::min() });
+    operands.append({ "int32-max", std::numeric_limits<int32_t>::max() });
+    operands.append({ "int32-min", std::numeric_limits<int32_t>::min() });
+
     return operands;
 }
 
+static Vector<Int32Operand> int32Operands()
+{
+    Vector<Int32Operand> operands({
+        { "0", 0 },
+        { "1", 1 },
+        { "-1", -1 },
+        { "42", 42 },
+        { "-42", -42 },
+        { "int32-max", std::numeric_limits<int32_t>::max() },
+        { "int32-min", std::numeric_limits<int32_t>::min() }
+    });
+    return operands;
+}
+
 #define RUN(test) do {                          \
         if (!shouldRun(#test))                  \
             break;                              \
@@ -4965,6 +5141,7 @@
     RUN(testSubImmArg(1, 2));
     RUN(testSubImmArg(13, -42));
     RUN(testSubImmArg(-13, 42));
+    RUN_UNARY(testNegValueSubOne, int32Operands());
 
     RUN(testSubArgs32(1, 1));
     RUN(testSubArgs32(1, 2));
@@ -4978,6 +5155,7 @@
     RUN(testSubImmArg32(1, 2));
     RUN(testSubImmArg32(13, -42));
     RUN(testSubImmArg32(-13, 42));
+    RUN_UNARY(testNegValueSubOne32, int64Operands());
 
     RUN_UNARY(testSubArgDouble, doubleOperands());
     RUN_BINARY(testSubArgsDouble, doubleOperands(), doubleOperands());
@@ -5091,26 +5269,11 @@
     RUN(testBitOrImmBitOrArgImm32(6, 1, 6));
     RUN(testBitOrImmBitOrArgImm32(24, 0xffff, 7));
 
-    RUN(testBitXorArgs(43, 43));
-    RUN(testBitXorArgs(43, 0));
-    RUN(testBitXorArgs(10, 3));
-    RUN(testBitXorArgs(42, 0xffffffffffffffff));
-    RUN(testBitXorSameArg(43));
-    RUN(testBitXorSameArg(0));
-    RUN(testBitXorSameArg(3));
-    RUN(testBitXorSameArg(0xffffffffffffffff));
-    RUN(testBitXorImms(43, 43));
-    RUN(testBitXorImms(43, 0));
-    RUN(testBitXorImms(10, 3));
-    RUN(testBitXorImms(42, 0xffffffffffffffff));
-    RUN(testBitXorArgImm(43, 43));
-    RUN(testBitXorArgImm(43, 0));
-    RUN(testBitXorArgImm(10, 3));
-    RUN(testBitXorArgImm(42, 0xffffffffffffffff));
-    RUN(testBitXorImmArg(43, 43));
-    RUN(testBitXorImmArg(43, 0));
-    RUN(testBitXorImmArg(10, 3));
-    RUN(testBitXorImmArg(42, 0xffffffffffffffff));
+    RUN_BINARY(testBitXorArgs, int64Operands(), int64Operands());
+    RUN_UNARY(testBitXorSameArg, int64Operands());
+    RUN_BINARY(testBitXorImms, int64Operands(), int64Operands());
+    RUN_BINARY(testBitXorArgImm, int64Operands(), int64Operands());
+    RUN_BINARY(testBitXorImmArg, int64Operands(), int64Operands());
     RUN(testBitXorBitXorArgImmImm(2, 7, 3));
     RUN(testBitXorBitXorArgImmImm(1, 6, 6));
     RUN(testBitXorBitXorArgImmImm(0xffff, 24, 7));
@@ -5144,6 +5307,14 @@
     RUN(testBitXorImmBitXorArgImm32(6, 1, 6));
     RUN(testBitXorImmBitXorArgImm32(24, 0xffff, 7));
 
+    RUN_UNARY(testBitNotArg, int64Operands());
+    RUN_UNARY(testBitNotImm, int64Operands());
+    RUN_UNARY(testBitNotMem, int64Operands());
+    RUN_UNARY(testBitNotArg32, int32Operands());
+    RUN_UNARY(testBitNotImm32, int32Operands());
+    RUN_UNARY(testBitNotMem32, int32Operands());
+    RUN_BINARY(testBitNotOnBooleanAndBranch32, int32Operands(), int32Operands());
+
     RUN(testShlArgs(1, 0));
     RUN(testShlArgs(1, 1));
     RUN(testShlArgs(1, 62));

Modified: trunk/Source/_javascript_Core/ftl/FTLB3Output.h (192695 => 192696)


--- trunk/Source/_javascript_Core/ftl/FTLB3Output.h	2015-11-20 21:19:57 UTC (rev 192695)
+++ trunk/Source/_javascript_Core/ftl/FTLB3Output.h	2015-11-20 22:07:05 UTC (rev 192696)
@@ -145,7 +145,7 @@
     LValue shl(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Shl, origin(), left, castToInt32(right)); }
     LValue aShr(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::SShr, origin(), left, castToInt32(right)); }
     LValue lShr(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::ZShr, origin(), left, castToInt32(right)); }
-    LValue bitNot(LValue value) { CRASH(); }
+    LValue bitNot(LValue);
 
     LValue insertElement(LValue vector, LValue element, LValue index) { CRASH(); }
 
@@ -475,6 +475,13 @@
     addIncomingToPhi(phi, theRest...);
 }
 
+inline LValue Output::bitNot(LValue value)
+{
+    return m_block->appendNew<B3::Value>(m_proc, B3::BitXor, origin(),
+        value,
+        m_block->appendIntConstant(m_proc, origin(), value->type(), -1));
+}
+
 inline LValue Output::bitCast(LValue value, LType type)
 {
     ASSERT_UNUSED(type, type == int64 || type == doubleType);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to