Title: [279593] trunk/Source/_javascript_Core
Revision
279593
Author
commit-qu...@webkit.org
Date
2021-07-06 10:29:30 -0700 (Tue, 06 Jul 2021)

Log Message

Fix instruction check failure of UBFX and SBFIZ in testb3 due to the speculative fix in bug 227554
https://bugs.webkit.org/show_bug.cgi?id=227563

Patch by Yijia Huang <yijia_hu...@apple.com> on 2021-07-06
Reviewed by Filip Pizlo.

This patch includes two modifications to resolve rdar://79978150:
    1. Fix the bug caused by the patch introducing BFI.
    2. Discard the corresponding speculative fix in https://bugs.webkit.org/show_bug.cgi?id=227554.

The previous patch, added bit field insert (BFI) to AIR opcode, causes the Gmail page
hanging issue on Safari. The root cause is the incorrect definition of register role in
BFI's AIR opcode. Since BFI inserts a bit field at the low end of the destination register
while keeping the high bit unchanged, the destination register should have both roles of
use and define simultaneously, which is not (missing use) in the previous patch.

This will result in the loss of preserving the value of the destination register,
which does happen when browsing the Gmail page on Safari.

    // B3 IR snippets from Gmail
    Int32 b@23  = Add(b@104, b@111, D@100)
    ...
    Int32 b@55  = Const32(65535, D@50)
    Int32 b@137 = BitAnd(b@118, $65535(b@55), D@160)
    Int32 b@168 = Const32(16, D@40)
    Int32 b@141 = Shl(b@137, $16(b@168), D@163)
    Int32 b@143 = BitAnd(b@23, $65535(b@55), D@166)
    Int32 b@144 = BitOr(b@141, b@143, D@169)

The pattern of BFI is d = ((n & mask1) << lsb) | (d & mask2). So, it is obvious that
BFI can be utilized in b@144 where the d is b@23.

    // Incorrect AIR opcode of BFI
    arm64: InsertBitField32 U:G:32, U:G:32, U:G:32, ZD:G:32
        Tmp, Imm, Imm, Tmp

    // Air w/o use role
    Add32            %x3, %x7, %x7,      b@23
    ...
    InsertBitField32 %x3, $16, $16, %x4, b@144

    // Generated code w/o use role
    add      w7, w3,  w7
    ...
    bfi      w4, w3, #16, #16

In Air, the added value is stored in the w7. But the value is not preserved after
lowering with BFI. To fix this, the use role should be enabled for the destination
register.

    // Correnct AIR opcode of BFI
    arm64: InsertBitField32 U:G:32, U:G:32, U:G:32, UZD:G:32
        Tmp, Imm, Imm, Tmp

    // Air w/ use role
    Add32            %x3, %x7, %x7,      b@23
    ...
    Move32           %x7, %x4,           b@144
    InsertBitField32 %x3, $16, $16, %x4, b@144

    // Generated code w/ use role
    add      w7, w3, w7
    ...
    ubfx     x4, x7,  #0, #32
    bfi      w4, w3, #16, #16

In addition, BFXIL, which has pattern d = ((n >> lsb) & mask1) | (d & mask2), also needs
the similar update.

* b3/B3LowerToAir.cpp:
* b3/air/AirOpcode.opcodes:
* b3/testb3_2.cpp:
(testInsertBitField32):
(testInsertBitField64):
(testExtractInsertBitfieldAtLowEnd32):
(testExtractInsertBitfieldAtLowEnd64):
* runtime/OptionsList.h:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (279592 => 279593)


--- trunk/Source/_javascript_Core/ChangeLog	2021-07-06 17:26:48 UTC (rev 279592)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-07-06 17:29:30 UTC (rev 279593)
@@ -1,3 +1,82 @@
+2021-07-06  Yijia Huang  <yijia_hu...@apple.com>
+
+        Fix instruction check failure of UBFX and SBFIZ in testb3 due to the speculative fix in bug 227554
+        https://bugs.webkit.org/show_bug.cgi?id=227563
+
+        Reviewed by Filip Pizlo.
+
+        This patch includes two modifications to resolve rdar://79978150:
+            1. Fix the bug caused by the patch introducing BFI.
+            2. Discard the corresponding speculative fix in https://bugs.webkit.org/show_bug.cgi?id=227554.
+
+        The previous patch, added bit field insert (BFI) to AIR opcode, causes the Gmail page 
+        hanging issue on Safari. The root cause is the incorrect definition of register role in 
+        BFI's AIR opcode. Since BFI inserts a bit field at the low end of the destination register 
+        while keeping the high bit unchanged, the destination register should have both roles of 
+        use and define simultaneously, which is not (missing use) in the previous patch. 
+
+        This will result in the loss of preserving the value of the destination register, 
+        which does happen when browsing the Gmail page on Safari.
+
+            // B3 IR snippets from Gmail
+            Int32 b@23  = Add(b@104, b@111, D@100)
+            ...
+            Int32 b@55  = Const32(65535, D@50)
+            Int32 b@137 = BitAnd(b@118, $65535(b@55), D@160)
+            Int32 b@168 = Const32(16, D@40)
+            Int32 b@141 = Shl(b@137, $16(b@168), D@163)
+            Int32 b@143 = BitAnd(b@23, $65535(b@55), D@166)
+            Int32 b@144 = BitOr(b@141, b@143, D@169)
+
+        The pattern of BFI is d = ((n & mask1) << lsb) | (d & mask2). So, it is obvious that 
+        BFI can be utilized in b@144 where the d is b@23.
+
+            // Incorrect AIR opcode of BFI
+            arm64: InsertBitField32 U:G:32, U:G:32, U:G:32, ZD:G:32
+                Tmp, Imm, Imm, Tmp
+
+            // Air w/o use role
+            Add32            %x3, %x7, %x7,      b@23
+            ...
+            InsertBitField32 %x3, $16, $16, %x4, b@144
+
+            // Generated code w/o use role
+            add      w7, w3,  w7
+            ...
+            bfi      w4, w3, #16, #16
+
+        In Air, the added value is stored in the w7. But the value is not preserved after 
+        lowering with BFI. To fix this, the use role should be enabled for the destination 
+        register.
+
+            // Correnct AIR opcode of BFI
+            arm64: InsertBitField32 U:G:32, U:G:32, U:G:32, UZD:G:32
+                Tmp, Imm, Imm, Tmp
+
+            // Air w/ use role
+            Add32            %x3, %x7, %x7,      b@23
+            ...
+            Move32           %x7, %x4,           b@144
+            InsertBitField32 %x3, $16, $16, %x4, b@144
+
+            // Generated code w/ use role
+            add      w7, w3, w7
+            ...
+            ubfx     x4, x7,  #0, #32
+            bfi      w4, w3, #16, #16
+
+        In addition, BFXIL, which has pattern d = ((n >> lsb) & mask1) | (d & mask2), also needs 
+        the similar update.
+
+        * b3/B3LowerToAir.cpp:
+        * b3/air/AirOpcode.opcodes:
+        * b3/testb3_2.cpp:
+        (testInsertBitField32):
+        (testInsertBitField64):
+        (testExtractInsertBitfieldAtLowEnd32):
+        (testExtractInsertBitfieldAtLowEnd64):
+        * runtime/OptionsList.h:
+
 2021-07-04  Robin Morisset  <rmoris...@apple.com>
 
         ActiveScratchBufferScope should take the buffer as argument

Modified: trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp (279592 => 279593)


--- trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2021-07-06 17:26:48 UTC (rev 279592)
+++ trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2021-07-06 17:29:30 UTC (rev 279593)
@@ -2764,8 +2764,6 @@
             // UBFX Pattern: dest = (src >> lsb) & mask 
             // Where: mask = (1 << width) - 1
             auto tryAppendUBFX = [&] () -> bool {
-                if (!Options::useBFI())
-                    return false;
                 Air::Opcode opcode = opcodeForType(ExtractUnsignedBitfield32, ExtractUnsignedBitfield64, m_value->type());
                 if (!isValidForm(opcode, Arg::Tmp, Arg::Imm, Arg::Imm, Arg::Tmp)) 
                     return false;
@@ -2865,8 +2863,6 @@
             // Where: mask1 = ((1 << width) - 1)
             //        mask2 = ~(mask1 << lsb)
             auto tryAppendBFI = [&] (Value* left, Value* right) -> bool {
-                if (!Options::useBFI())
-                    return false;
                 Air::Opcode opcode = opcodeForType(InsertBitField32, InsertBitField64, m_value->type());
                 if (!isValidForm(opcode, Arg::Tmp, Arg::Imm, Arg::Imm, Arg::Tmp)) 
                     return false;
@@ -3055,8 +3051,6 @@
             // SBFIZ Pattern: d = ((src << amount) >> amount) << lsb
             // where: amount = datasize - width
             auto tryAppendSBFIZ = [&] () -> bool {
-                if (!Options::useBFI())
-                    return false;
                 Air::Opcode opcode = opcodeForType(InsertSignedBitfieldInZero32, InsertSignedBitfieldInZero64, m_value->type());
                 if (!isValidForm(opcode, Arg::Tmp, Arg::Imm, Arg::Imm, Arg::Tmp))
                     return false;

Modified: trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes (279592 => 279593)


--- trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes	2021-07-06 17:26:48 UTC (rev 279592)
+++ trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes	2021-07-06 17:29:30 UTC (rev 279593)
@@ -824,10 +824,10 @@
 arm64: InsertUnsignedBitfieldInZero64 U:G:64, U:G:32, U:G:32, D:G:64
     Tmp, Imm, Imm, Tmp
 
-arm64: InsertBitField32 U:G:32, U:G:32, U:G:32, ZD:G:32
+arm64: InsertBitField32 U:G:32, U:G:32, U:G:32, UZD:G:32
     Tmp, Imm, Imm, Tmp
 
-arm64: InsertBitField64 U:G:64, U:G:32, U:G:32, D:G:64
+arm64: InsertBitField64 U:G:64, U:G:32, U:G:32, UD:G:64
     Tmp, Imm, Imm, Tmp
 
 arm64: ClearBitField32 U:G:32, U:G:32, ZD:G:32
@@ -848,10 +848,10 @@
 arm64: OrNot64 U:G:64, U:G:64, D:G:64
     Tmp, Tmp, Tmp
 
-arm64: ExtractInsertBitfieldAtLowEnd32 U:G:32, U:G:32, U:G:32, ZD:G:32
+arm64: ExtractInsertBitfieldAtLowEnd32 U:G:32, U:G:32, U:G:32, UZD:G:32
     Tmp, Imm, Imm, Tmp
 
-arm64: ExtractInsertBitfieldAtLowEnd64 U:G:64, U:G:32, U:G:32, D:G:64
+arm64: ExtractInsertBitfieldAtLowEnd64 U:G:64, U:G:32, U:G:32, UD:G:64
     Tmp, Imm, Imm, Tmp
 
 arm64: InsertSignedBitfieldInZero32 U:G:32, U:G:32, U:G:32, ZD:G:32

Modified: trunk/Source/_javascript_Core/b3/testb3_2.cpp (279592 => 279593)


--- trunk/Source/_javascript_Core/b3/testb3_2.cpp	2021-07-06 17:26:48 UTC (rev 279592)
+++ trunk/Source/_javascript_Core/b3/testb3_2.cpp	2021-07-06 17:29:30 UTC (rev 279593)
@@ -3160,8 +3160,6 @@
 
 void testInsertBitField32()
 {
-    if (!JSC::Options::useBFI())
-        return;
     if (JSC::Options::defaultB3OptLevel() < 2)
         return;
     uint32_t d = 0xf0f0f0f0;
@@ -3199,6 +3197,13 @@
         return invoke<uint32_t>(*code, d, n);
     };
 
+    for (size_t i = 0; i < lsbs.size(); ++i) {
+        uint32_t lsb = lsbs.at(i);
+        uint32_t mask1 = (1U << widths.at(i)) - 1U;
+        uint32_t mask2 = ~(mask1 << lsb);
+        CHECK(test1(lsb, mask1, mask2) == (((n & mask1) << lsb) | (d & mask2)));
+    }
+
     // Test Pattern: d = (d & mask2) | ((n & mask1) << lsb) 
     // Where: mask1 = ((1 << width) - 1)
     //        mask2 = ~(mask1 << lsb)
@@ -3233,15 +3238,70 @@
         uint32_t lsb = lsbs.at(i);
         uint32_t mask1 = (1U << widths.at(i)) - 1U;
         uint32_t mask2 = ~(mask1 << lsb);
-        CHECK(test1(lsb, mask1, mask2) == (((n & mask1) << lsb) | (d & mask2)));
         CHECK(test2(lsb, mask1, mask2) == ((d & mask2) | ((n & mask1) << lsb)));
     }
+
+    // Test use role on destination register of BFI
+    uint32_t dA = 0x0000f0f0;
+    uint32_t dB = 0xf0f00000;
+
+    auto test3 = [&] (uint32_t lsb, uint32_t mask1, uint32_t mask2) -> uint32_t {
+        Procedure proc;
+        BasicBlock* root = proc.addBlock();
+
+        Value* dAValue = root->appendNew<Value>(
+            proc, Trunc, Origin(), 
+            root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+        Value* dBValue = root->appendNew<Value>(
+            proc, Trunc, Origin(), 
+            root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+        Value* nValue = root->appendNew<Value>(
+            proc, Trunc, Origin(), 
+            root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
+        Value* lsbValue = root->appendNew<Const32Value>(proc, Origin(), lsb);
+        Value* maskValue1 = root->appendNew<Const32Value>(proc, Origin(), mask1);
+        Value* maskValue2 = root->appendNew<Const32Value>(proc, Origin(), mask2);
+
+        // d = dA + dB
+        Value* dValue = root->appendNew<Value>(proc, Add, Origin(), dAValue, dBValue);
+
+        // d = (d & mask2) | ((n & mask1) << lsb) 
+        Value* leftAndValue = root->appendNew<Value>(proc, BitAnd, Origin(), nValue, maskValue1);
+        Value* shiftValue = root->appendNew<Value>(proc, Shl, Origin(), leftAndValue, lsbValue);
+        Value* rightAndValue = root->appendNew<Value>(proc, BitAnd, Origin(), dValue, maskValue2);
+        Value* orValue = root->appendNew<Value>(proc, BitOr, Origin(), shiftValue, rightAndValue);
+
+        // v3 = ((mask1 + mask2) + dB) + dA
+        Value* value1 = root->appendNew<Value>(proc, Add, Origin(), maskValue1, maskValue2);
+        Value* value2 = root->appendNew<Value>(proc, Add, Origin(), value1, dBValue);
+        Value* value3 = root->appendNew<Value>(proc, Add, Origin(), value2, dAValue);
+
+        root->appendNewControlValue(
+            proc, Return, Origin(), 
+            root->appendNew<Value>(proc, Add, Origin(), value3, orValue));
+
+        auto code = compileProc(proc);
+        if (isARM64())
+            checkUsesInstruction(*code, "bfi");
+        return invoke<uint32_t>(*code, dA, dB, n);
+    };
+
+    for (size_t i = 0; i < lsbs.size(); ++i) {
+        uint32_t lsb = lsbs.at(i);
+        uint32_t mask1 = (1U << widths.at(i)) - 1U;
+        uint32_t mask2 = ~(mask1 << lsb);
+
+        uint32_t lhs3 = test3(lsb, mask1, mask2);
+        uint32_t dv = dA + dB;
+        dv = (dv & mask2) | ((n & mask1) << lsb);
+        uint32_t v3 = ((mask1 + mask2) + dB) + dA;
+        uint32_t rhs3 = v3 + dv;
+        CHECK(lhs3 == rhs3);
+    }
 }
 
 void testInsertBitField64()
 {
-    if (!JSC::Options::useBFI())
-        return;
     if (JSC::Options::defaultB3OptLevel() < 2)
         return;
     uint64_t d = 0xf0f0f0f0f0f0f0f0;
@@ -3308,6 +3368,58 @@
         CHECK(test1(lsb, mask1, mask2) == (((n & mask1) << lsb) | (d & mask2)));
         CHECK(test2(lsb, mask1, mask2) == ((d & mask2) | ((n & mask1) << lsb)));
     }
+
+    // Test use role on destination register of BFI
+    uint64_t dA = 0x00000000f0f0f0f0;
+    uint64_t dB = 0xf0f0f0f000000000;
+
+    auto test3 = [&] (uint64_t lsb, uint64_t mask1, uint64_t mask2) -> uint64_t {
+        Procedure proc;
+        BasicBlock* root = proc.addBlock();
+
+        Value* dAValue = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+        Value* dBValue = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
+        Value* nValue = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
+        Value* lsbValue = root->appendNew<Const32Value>(proc, Origin(), lsb);
+        Value* maskValue1 = root->appendNew<Const64Value>(proc, Origin(), mask1);
+        Value* maskValue2 = root->appendNew<Const64Value>(proc, Origin(), mask2);
+
+        // d = dA + dB
+        Value* dValue = root->appendNew<Value>(proc, Add, Origin(), dAValue, dBValue);
+
+        // d = (d & mask2) | ((n & mask1) << lsb) 
+        Value* leftAndValue = root->appendNew<Value>(proc, BitAnd, Origin(), nValue, maskValue1);
+        Value* shiftValue = root->appendNew<Value>(proc, Shl, Origin(), leftAndValue, lsbValue);
+        Value* rightAndValue = root->appendNew<Value>(proc, BitAnd, Origin(), dValue, maskValue2);
+        Value* orValue = root->appendNew<Value>(proc, BitOr, Origin(), shiftValue, rightAndValue);
+
+        // v3 = ((mask1 + mask2) + dB) + dA
+        Value* value1 = root->appendNew<Value>(proc, Add, Origin(), maskValue1, maskValue2);
+        Value* value2 = root->appendNew<Value>(proc, Add, Origin(), value1, dBValue);
+        Value* value3 = root->appendNew<Value>(proc, Add, Origin(), value2, dAValue);
+
+        root->appendNewControlValue(
+            proc, Return, Origin(), 
+            root->appendNew<Value>(proc, Add, Origin(), value3, orValue));
+
+        auto code = compileProc(proc);
+        if (isARM64())
+            checkUsesInstruction(*code, "bfi");
+        return invoke<uint64_t>(*code, dA, dB, n);
+    };
+
+    for (size_t i = 0; i < lsbs.size(); ++i) {
+        uint64_t lsb = lsbs.at(i);
+        uint64_t mask1 = (1ULL << widths.at(i)) - 1ULL;
+        uint64_t mask2 = ~(mask1 << lsb);
+
+        uint64_t lhs3 = test3(lsb, mask1, mask2);
+        uint64_t dv = dA + dB;
+        dv = (dv & mask2) | ((n & mask1) << lsb);
+        uint64_t v3 = ((mask1 + mask2) + dB) + dA;
+        uint64_t rhs3 = v3 + dv;
+        CHECK(lhs3 == rhs3);
+    }
 }
 
 void testExtractInsertBitfieldAtLowEnd32()
@@ -3392,6 +3504,64 @@
         uint32_t mask2 = ~(mask1 >> lsb);
         CHECK(test2(lsb, mask1, mask2) == (((n & mask1) >> lsb) | (d & mask2)));
     }
+
+    // Test use role on destination register of BFXIL
+    uint32_t dA = 0x0000f0f0;
+    uint32_t dB = 0xf0f00000;
+
+    auto test3 = [&] (uint32_t lsb, uint32_t mask1, uint32_t mask2) -> uint32_t {
+        Procedure proc;
+        BasicBlock* root = proc.addBlock();
+
+        Value* dAValue = root->appendNew<Value>(
+            proc, Trunc, Origin(), 
+            root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+        Value* dBValue = root->appendNew<Value>(
+            proc, Trunc, Origin(), 
+            root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+        Value* nValue = root->appendNew<Value>(
+            proc, Trunc, Origin(), 
+            root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
+        Value* lsbValue = root->appendNew<Const32Value>(proc, Origin(), lsb);
+        Value* maskValue1 = root->appendNew<Const32Value>(proc, Origin(), mask1);
+        Value* maskValue2 = root->appendNew<Const32Value>(proc, Origin(), mask2);
+
+        // d = dA + dB
+        Value* dValue = root->appendNew<Value>(proc, Add, Origin(), dAValue, dBValue);
+
+        // d = d = ((n >> lsb) & mask1) | (d & mask2)
+        Value* shiftValue = root->appendNew<Value>(proc, ZShr, Origin(), nValue, lsbValue);
+        Value* leftAndValue = root->appendNew<Value>(proc, BitAnd, Origin(), shiftValue, maskValue1);
+        Value* rightAndValue = root->appendNew<Value>(proc, BitAnd, Origin(), dValue, maskValue2);
+        Value* orValue = root->appendNew<Value>(proc, BitOr, Origin(), leftAndValue, rightAndValue);
+
+        // v3 = ((mask1 + mask2) + dB) + dA
+        Value* value1 = root->appendNew<Value>(proc, Add, Origin(), maskValue1, maskValue2);
+        Value* value2 = root->appendNew<Value>(proc, Add, Origin(), value1, dBValue);
+        Value* value3 = root->appendNew<Value>(proc, Add, Origin(), value2, dAValue);
+
+        root->appendNewControlValue(
+            proc, Return, Origin(), 
+            root->appendNew<Value>(proc, Add, Origin(), value3, orValue));
+
+        auto code = compileProc(proc);
+        if (isARM64())
+            checkUsesInstruction(*code, "bfxil");
+        return invoke<uint32_t>(*code, dA, dB, n);
+    };
+
+    for (size_t i = 0; i < lsbs.size(); ++i) {
+        uint32_t lsb = lsbs.at(i);
+        uint32_t mask1 = (1U << widths.at(i)) - 1U;
+        uint32_t mask2 = ~mask1;
+
+        uint32_t lhs3 = test3(lsb, mask1, mask2);
+        uint32_t dv = dA + dB;
+        dv = ((n >> lsb) & mask1) | (dv & mask2);
+        uint32_t v3 = ((mask1 + mask2) + dB) + dA;
+        uint32_t rhs3 = v3 + dv;
+        CHECK(lhs3 == rhs3);
+    }
 }
 
 void testExtractInsertBitfieldAtLowEnd64()
@@ -3468,6 +3638,58 @@
         uint64_t mask2 = ~(mask1 >> lsb);
         CHECK(test2(lsb, mask1, mask2) == (((n & mask1) >> lsb) | (d & mask2)));
     }
+
+    // Test use role on destination register of BFXIL
+    uint64_t dA = 0x00000000f0f0f0f0;
+    uint64_t dB = 0xf0f0f0f000000000;
+
+    auto test3 = [&] (uint64_t lsb, uint64_t mask1, uint64_t mask2) -> uint64_t {
+        Procedure proc;
+        BasicBlock* root = proc.addBlock();
+
+        Value* dAValue = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+        Value* dBValue = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
+        Value* nValue = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
+        Value* lsbValue = root->appendNew<Const32Value>(proc, Origin(), lsb);
+        Value* maskValue1 = root->appendNew<Const64Value>(proc, Origin(), mask1);
+        Value* maskValue2 = root->appendNew<Const64Value>(proc, Origin(), mask2);
+
+        // d = dA + dB
+        Value* dValue = root->appendNew<Value>(proc, Add, Origin(), dAValue, dBValue);
+
+        // d = d = ((n >> lsb) & mask1) | (d & mask2)
+        Value* shiftValue = root->appendNew<Value>(proc, ZShr, Origin(), nValue, lsbValue);
+        Value* leftAndValue = root->appendNew<Value>(proc, BitAnd, Origin(), shiftValue, maskValue1);
+        Value* rightAndValue = root->appendNew<Value>(proc, BitAnd, Origin(), dValue, maskValue2);
+        Value* orValue = root->appendNew<Value>(proc, BitOr, Origin(), leftAndValue, rightAndValue);
+
+        // v3 = ((mask1 + mask2) + dB) + dA
+        Value* value1 = root->appendNew<Value>(proc, Add, Origin(), maskValue1, maskValue2);
+        Value* value2 = root->appendNew<Value>(proc, Add, Origin(), value1, dBValue);
+        Value* value3 = root->appendNew<Value>(proc, Add, Origin(), value2, dAValue);
+
+        root->appendNewControlValue(
+            proc, Return, Origin(), 
+            root->appendNew<Value>(proc, Add, Origin(), value3, orValue));
+
+        auto code = compileProc(proc);
+        if (isARM64())
+            checkUsesInstruction(*code, "bfxil");
+        return invoke<uint64_t>(*code, dA, dB, n);
+    };
+
+    for (size_t i = 0; i < lsbs.size(); ++i) {
+        uint64_t lsb = lsbs.at(i);
+        uint64_t mask1 = (1ULL << widths.at(i)) - 1ULL;
+        uint64_t mask2 = ~mask1;
+
+        uint64_t lhs3 = test3(lsb, mask1, mask2);
+        uint64_t dv = dA + dB;
+        dv = ((n >> lsb) & mask1) | (dv & mask2);
+        uint64_t v3 = ((mask1 + mask2) + dB) + dA;
+        uint64_t rhs3 = v3 + dv;
+        CHECK(lhs3 == rhs3);
+    }
 }
 
 void testBIC32()

Modified: trunk/Source/_javascript_Core/runtime/OptionsList.h (279592 => 279593)


--- trunk/Source/_javascript_Core/runtime/OptionsList.h	2021-07-06 17:26:48 UTC (rev 279592)
+++ trunk/Source/_javascript_Core/runtime/OptionsList.h	2021-07-06 17:29:30 UTC (rev 279593)
@@ -549,7 +549,6 @@
     v(Bool, useDataIC, false, Normal, nullptr) \
     v(Bool, useDataICInOptimizingJIT, false, Normal, nullptr) \
     v(Bool, useDataICSharing, false, Normal, nullptr) \
-    v(Bool, useBFI, false, Normal, "Allow ARM64 instruction selection of BFI") \
 
 
 enum OptionEquivalence {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to