Changeset 249747 in webkit


Ignore:
Timestamp:
Sep 10, 2019 5:46:32 PM (5 years ago)
Author:
ysuzuki@apple.com
Message:

[JSC] 32bit bitwide operation with all-one (-1) is wrong in B3
https://bugs.webkit.org/show_bug.cgi?id=201634

Reviewed by Mark Lam and Robin Morisset.

This patch includes two things. One is fixing 32bit bitwise operation with allOne constants. Another is fixing the existing bug in BitAnd strength reduction.

  1. 32bit bitwise operation with allOne constants

Accidentally, the B3::Value is ConstInt32(-1), value->isInt(std::numeric_limits<uint32_t>::max()) returns false!
For example, in BitAnd strength reduction,

1034 Turn this: BitAnd(value, all-ones)
1035
Into this: value.
1036 if ((m_value->type() == Int64 && m_value->child(1)->isInt(std::numeric_limits<uint64_t>::max()))

1037
(m_value->type() == Int32 && m_value->child(1)->isInt(std::numeric_limits<uint32_t>::max()))) {

1038 replaceWithIdentity(m_value->child(0));
1039 break;
1040 }

We use m_value->child(1)->isInt(std::numeric_limits<uint32_t>::max()). However, Value::isInt is,

262 inline bool Value::isInt(int64_t value) const
263 {
264 return hasInt() && asInt() == value;
265 }

So, UINT32_MAX is expanded to int64_t, but it is not -1 since UINT32_MAX can be representable in int64_t. And Value::asInt implementation is,

257 inline int64_t Value::asInt() const
258 {
259 return hasInt32() ? asInt32() : asInt64();
260 }

So, we perform static_cast<int64_t>(-1) == static_cast<int64_t>(UINT32_MAX). This is false, but this comparison is not what we want!
We should use isInt32 and isInt64 for bit patterns (like, operands for Bitwise opcodes).

  1. BitAnd and BitOr strength reduction bug

We also fix the following optimization.

Turn this: BitAnd(Op(value, constant1), constant2)
where !(constant1 & constant2)
and Op is BitOr or BitXor
into this: BitAnd(value, constant2)

Since we stop further optimization when we match if (m_value->child(1)->hasInt()), the following optimization is never taken.

Turn this: BitAnd(BitXor(x, allOnes), c)
Into this: BitXor(BitOr(x, ~c), allOnes)

And we also found that this not-used optimization has a bug not inserting a newly produced constant B3::Value. This patch also fixes it.

For both, this patch adds tests. And (2) fix can be ensured that the testb3 does not crash with validate-graph option.

  • b3/B3LowerToAir.cpp:
  • b3/B3ReduceStrength.cpp:
  • b3/testb3.h:
  • b3/testb3_2.cpp:

(testBitAndNotNot32):
(testBitAndNotImm):
(testBitAndNotImm32):
(testBitOrAndAndArgs32):
(testBitOrAndSameArgs32):
(testBitOrNotNot32):
(testBitOrNotImm32):
(addBitTests):

  • b3/testb3_3.cpp:

(testBitXorAndAndArgs32):
(testBitXorAndSameArgs32):

Location:
trunk/Source/JavaScriptCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r249743 r249747  
     12019-09-10  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] 32bit bitwide operation with all-one (-1) is wrong in B3
     4        https://bugs.webkit.org/show_bug.cgi?id=201634
     5
     6        Reviewed by Mark Lam and Robin Morisset.
     7
     8        This patch includes two things. One is fixing 32bit bitwise operation with allOne constants. Another is fixing the existing bug in BitAnd strength reduction.
     9
     10        1. 32bit bitwise operation with allOne constants
     11
     12            Accidentally, the B3::Value is ConstInt32(-1), `value->isInt(std::numeric_limits<uint32_t>::max())` returns `false`!
     13            For example, in BitAnd strength reduction,
     14
     15                1034             // Turn this: BitAnd(value, all-ones)
     16                1035             // Into this: value.
     17                1036             if ((m_value->type() == Int64 && m_value->child(1)->isInt(std::numeric_limits<uint64_t>::max()))
     18                1037                 || (m_value->type() == Int32 && m_value->child(1)->isInt(std::numeric_limits<uint32_t>::max()))) {
     19                1038                 replaceWithIdentity(m_value->child(0));
     20                1039                 break;
     21                1040             }
     22
     23            We use `m_value->child(1)->isInt(std::numeric_limits<uint32_t>::max())`. However, Value::isInt is,
     24
     25                262 inline bool Value::isInt(int64_t value) const
     26                263 {
     27                264     return hasInt() && asInt() == value;
     28                265 }
     29
     30            So, UINT32_MAX is expanded to int64_t, but it is not -1 since UINT32_MAX can be representable in int64_t. And Value::asInt implementation is,
     31
     32                257 inline int64_t Value::asInt() const
     33                258 {
     34                259     return hasInt32() ? asInt32() : asInt64();
     35                260 }
     36
     37            So, we perform `static_cast<int64_t>(-1) == static_cast<int64_t>(UINT32_MAX)`. This is false, but this comparison is not what we want!
     38            We should use `isInt32` and `isInt64` for bit patterns (like, operands for Bitwise opcodes).
     39
     40        2. BitAnd and BitOr strength reduction bug
     41
     42            We also fix the following optimization.
     43
     44                // Turn this: BitAnd(Op(value, constant1), constant2)
     45                //     where !(constant1 & constant2)
     46                //       and Op is BitOr or BitXor
     47                // into this: BitAnd(value, constant2)
     48
     49            Since we stop further optimization when we match `if (m_value->child(1)->hasInt())`, the following optimization is never taken.
     50
     51                // Turn this: BitAnd(BitXor(x, allOnes), c)
     52                // Into this: BitXor(BitOr(x, ~c), allOnes)
     53
     54            And we also found that this not-used optimization has a bug not inserting a newly produced constant B3::Value. This patch also fixes it.
     55
     56        For both, this patch adds tests. And (2) fix can be ensured that the testb3 does not crash with validate-graph option.
     57
     58        * b3/B3LowerToAir.cpp:
     59        * b3/B3ReduceStrength.cpp:
     60        * b3/testb3.h:
     61        * b3/testb3_2.cpp:
     62        (testBitAndNotNot32):
     63        (testBitAndNotImm):
     64        (testBitAndNotImm32):
     65        (testBitOrAndAndArgs32):
     66        (testBitOrAndSameArgs32):
     67        (testBitOrNotNot32):
     68        (testBitOrNotImm32):
     69        (addBitTests):
     70        * b3/testb3_3.cpp:
     71        (testBitXorAndAndArgs32):
     72        (testBitXorAndSameArgs32):
     73
    1742019-09-10  Commit Queue  <commit-queue@webkit.org>
    275
  • trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp

    r249743 r249747  
    27502750            }
    27512751
    2752             if (m_value->child(1)->isInt(0xffffffff)) {
     2752            if (m_value->child(1)->isInt64(0xffffffff) || m_value->child(1)->isInt32(0xffffffff)) {
    27532753                appendUnOp<Move32, Move32>(m_value->child(0));
    27542754                return;
  • trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp

    r249743 r249747  
    10341034            // Turn this: BitAnd(value, all-ones)
    10351035            // Into this: value.
    1036             if ((m_value->type() == Int64 && m_value->child(1)->isInt(std::numeric_limits<uint64_t>::max()))
    1037                 || (m_value->type() == Int32 && m_value->child(1)->isInt(std::numeric_limits<uint32_t>::max()))) {
     1036            if ((m_value->type() == Int64 && m_value->child(1)->isInt64(std::numeric_limits<uint64_t>::max()))
     1037                || (m_value->type() == Int32 && m_value->child(1)->isInt32(std::numeric_limits<uint32_t>::max()))) {
    10381038                replaceWithIdentity(m_value->child(0));
    10391039                break;
     
    10841084            // into this: BitAnd(value, constant2)
    10851085            if (m_value->child(1)->hasInt()) {
     1086                bool replaced = false;
    10861087                int64_t constant2 = m_value->child(1)->asInt();
    10871088                switch (m_value->child(0)->opcode()) {
     
    10921093                        m_value->child(0) = m_value->child(0)->child(0);
    10931094                        m_changed = true;
     1095                        replaced = true;
    10941096                        break;
    10951097                    }
     
    10981100                    break;
    10991101                }
    1100                 break;
     1102                if (replaced)
     1103                    break;
    11011104            }
    11021105
     
    11071110                && m_value->child(1)->opcode() == BitXor
    11081111                && ((m_value->type() == Int64
    1109                         && m_value->child(0)->child(1)->isInt(std::numeric_limits<uint64_t>::max())
    1110                         && m_value->child(1)->child(1)->isInt(std::numeric_limits<uint64_t>::max()))
     1112                        && m_value->child(0)->child(1)->isInt64(std::numeric_limits<uint64_t>::max())
     1113                        && m_value->child(1)->child(1)->isInt64(std::numeric_limits<uint64_t>::max()))
    11111114                    || (m_value->type() == Int32
    1112                         && m_value->child(0)->child(1)->isInt(std::numeric_limits<uint32_t>::max())
    1113                         && m_value->child(1)->child(1)->isInt(std::numeric_limits<uint32_t>::max())))) {
     1115                        && m_value->child(0)->child(1)->isInt32(std::numeric_limits<uint32_t>::max())
     1116                        && m_value->child(1)->child(1)->isInt32(std::numeric_limits<uint32_t>::max())))) {
    11141117                Value* bitOr = m_insertionSet.insert<Value>(m_index, BitOr, m_value->origin(), m_value->child(0)->child(0), m_value->child(1)->child(0));
    11151118                replaceWithNew<Value>(BitXor, m_value->origin(), bitOr, m_value->child(1)->child(1));
     
    11241127                && m_value->child(1)->hasInt()
    11251128                && ((m_value->type() == Int64
    1126                         && m_value->child(0)->child(1)->isInt(std::numeric_limits<uint64_t>::max()))
     1129                        && m_value->child(0)->child(1)->isInt64(std::numeric_limits<uint64_t>::max()))
    11271130                    || (m_value->type() == Int32
    1128                         && m_value->child(0)->child(1)->isInt(std::numeric_limits<uint32_t>::max())))) {
    1129                 Value* bitOr = m_insertionSet.insert<Value>(m_index, BitOr, m_value->origin(), m_value->child(0)->child(0), m_value->child(1)->bitXorConstant(m_proc, m_value->child(0)->child(1)));
     1131                        && m_value->child(0)->child(1)->isInt32(std::numeric_limits<uint32_t>::max())))) {
     1132                Value* newConstant = m_value->child(1)->bitXorConstant(m_proc, m_value->child(0)->child(1));
     1133                ASSERT(newConstant);
     1134                m_insertionSet.insertValue(m_index, newConstant);
     1135                Value* bitOr = m_insertionSet.insert<Value>(m_index, BitOr, m_value->origin(), m_value->child(0)->child(0), newConstant);
    11301136                replaceWithNew<Value>(BitXor, m_value->origin(), bitOr, m_value->child(0)->child(1));
    11311137                break;
     
    11721178            // Turn this: BitOr(value, all-ones)
    11731179            // Into this: all-ones.
    1174             if ((m_value->type() == Int64 && m_value->child(1)->isInt(std::numeric_limits<uint64_t>::max()))
    1175                 || (m_value->type() == Int32 && m_value->child(1)->isInt(std::numeric_limits<uint32_t>::max()))) {
     1180            if ((m_value->type() == Int64 && m_value->child(1)->isInt64(std::numeric_limits<uint64_t>::max()))
     1181                || (m_value->type() == Int32 && m_value->child(1)->isInt32(std::numeric_limits<uint32_t>::max()))) {
    11761182                replaceWithIdentity(m_value->child(1));
    11771183                break;
     
    11841190                && m_value->child(1)->opcode() == BitXor
    11851191                && ((m_value->type() == Int64
    1186                         && m_value->child(0)->child(1)->isInt(std::numeric_limits<uint64_t>::max())
    1187                         && m_value->child(1)->child(1)->isInt(std::numeric_limits<uint64_t>::max()))
     1192                        && m_value->child(0)->child(1)->isInt64(std::numeric_limits<uint64_t>::max())
     1193                        && m_value->child(1)->child(1)->isInt64(std::numeric_limits<uint64_t>::max()))
    11881194                    || (m_value->type() == Int32
    1189                         && m_value->child(0)->child(1)->isInt(std::numeric_limits<uint32_t>::max())
    1190                         && m_value->child(1)->child(1)->isInt(std::numeric_limits<uint32_t>::max())))) {
     1195                        && m_value->child(0)->child(1)->isInt32(std::numeric_limits<uint32_t>::max())
     1196                        && m_value->child(1)->child(1)->isInt32(std::numeric_limits<uint32_t>::max())))) {
    11911197                Value* bitAnd = m_insertionSet.insert<Value>(m_index, BitAnd, m_value->origin(), m_value->child(0)->child(0), m_value->child(1)->child(0));
    11921198                replaceWithNew<Value>(BitXor, m_value->origin(), bitAnd, m_value->child(1)->child(1));
     
    12011207                && m_value->child(1)->hasInt()
    12021208                && ((m_value->type() == Int64
    1203                         && m_value->child(0)->child(1)->isInt(std::numeric_limits<uint64_t>::max()))
     1209                        && m_value->child(0)->child(1)->isInt64(std::numeric_limits<uint64_t>::max()))
    12041210                    || (m_value->type() == Int32
    1205                         && m_value->child(0)->child(1)->isInt(std::numeric_limits<uint32_t>::max())))) {
    1206                 Value* bitAnd = m_insertionSet.insert<Value>(m_index, BitAnd, m_value->origin(), m_value->child(0)->child(0), m_value->child(1)->bitXorConstant(m_proc, m_value->child(0)->child(1)));
     1211                        && m_value->child(0)->child(1)->isInt32(std::numeric_limits<uint32_t>::max())))) {
     1212                Value* newConstant = m_value->child(1)->bitXorConstant(m_proc, m_value->child(0)->child(1));
     1213                ASSERT(newConstant);
     1214                m_insertionSet.insertValue(m_index, newConstant);
     1215                Value* bitAnd = m_insertionSet.insert<Value>(m_index, BitAnd, m_value->origin(), m_value->child(0)->child(0), newConstant);
    12071216                replaceWithNew<Value>(BitXor, m_value->origin(), bitAnd, m_value->child(0)->child(1));
    12081217                break;
  • trunk/Source/JavaScriptCore/b3/testb3.h

    r249743 r249747  
    460460void testBitXorSameArg(int64_t);
    461461void testBitXorAndAndArgs(int64_t, int64_t, int64_t c);
     462void testBitXorAndAndArgs32(int32_t, int32_t, int32_t c);
    462463void testBitXorAndSameArgs(int64_t, int64_t);
     464void testBitXorAndSameArgs32(int32_t, int32_t);
    463465void testBitXorImms(int64_t, int64_t);
    464466void testBitXorArgImm(int64_t, int64_t);
  • trunk/Source/JavaScriptCore/b3/testb3_2.cpp

    r249743 r249747  
    25662566}
    25672567
     2568static void testBitAndNotNot32(int32_t a, int32_t b)
     2569{
     2570    Procedure proc;
     2571    BasicBlock* root = proc.addBlock();
     2572    Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     2573    Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
     2574    Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const32Value>(proc, Origin(), -1));
     2575    Value* notB = root->appendNew<Value>(proc, BitXor, Origin(), argB, root->appendNew<Const32Value>(proc, Origin(), -1));
     2576    root->appendNewControlValue(
     2577        proc, Return, Origin(),
     2578        root->appendNew<Value>(
     2579            proc, BitAnd, Origin(),
     2580            notA,
     2581            notB));
     2582
     2583    CHECK_EQ(compileAndRun<int32_t>(proc, a, b), (~a & ~b));
     2584}
     2585
    25682586static void testBitAndNotImm(int64_t a, int64_t b)
    25692587{
     
    25802598            cstB));
    25812599
    2582     CHECK_EQ(compileAndRun<int64_t>(proc, a, b), (~a & b));
     2600    CHECK_EQ(compileAndRun<int64_t>(proc, a), (~a & b));
     2601}
     2602
     2603static void testBitAndNotImm32(int32_t a, int32_t b)
     2604{
     2605    Procedure proc;
     2606    BasicBlock* root = proc.addBlock();
     2607    Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     2608    Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const32Value>(proc, Origin(), -1));
     2609    Value* cstB = root->appendNew<Const32Value>(proc, Origin(), b);
     2610    root->appendNewControlValue(
     2611        proc, Return, Origin(),
     2612        root->appendNew<Value>(
     2613            proc, BitAnd, Origin(),
     2614            notA,
     2615            cstB));
     2616
     2617    CHECK_EQ(compileAndRun<int32_t>(proc, a), (~a & b));
    25832618}
    25842619
     
    29953030}
    29963031
     3032static void testBitOrAndAndArgs32(int32_t a, int32_t b, int32_t c)
     3033{
     3034    // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
     3035    // ((a & b) | (a & c))
     3036    // ((a & b) | (c & a))
     3037    // ((b & a) | (a & c))
     3038    // ((b & a) | (c & a))
     3039    for (int i = 0; i < 4; ++i) {
     3040        Procedure proc;
     3041        BasicBlock* root = proc.addBlock();
     3042        Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     3043        Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
     3044        Value* argC = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
     3045        Value* andAB = i & 2 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
     3046            : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
     3047        Value* andAC = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argC)
     3048            : root->appendNew<Value>(proc, BitAnd, Origin(), argC, argA);
     3049        root->appendNewControlValue(
     3050            proc, Return, Origin(),
     3051            root->appendNew<Value>(
     3052                proc, BitOr, Origin(),
     3053                andAB,
     3054                andAC));
     3055
     3056        CHECK_EQ(compileAndRun<int32_t>(proc, a, b, c), ((a & b) | (a & c)));
     3057    }
     3058}
     3059
    29973060static void testBitOrAndSameArgs(int64_t a, int64_t b)
    29983061{
     
    30173080}
    30183081
     3082static void testBitOrAndSameArgs32(int32_t a, int32_t b)
     3083{
     3084    // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
     3085    // ((a & b) | a)
     3086    // ((b & a) | a)
     3087    // (a | (a & b))
     3088    // (a | (b & a))
     3089    for (int i = 0; i < 4; ++i) {
     3090        Procedure proc;
     3091        BasicBlock* root = proc.addBlock();
     3092        Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     3093        Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
     3094        Value* andAB = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
     3095            : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
     3096        Value* result = i & 2 ? root->appendNew<Value>(proc, BitOr, Origin(), andAB, argA)
     3097            : root->appendNew<Value>(proc, BitOr, Origin(), argA, andAB);
     3098        root->appendNewControlValue(proc, Return, Origin(), result);
     3099
     3100        CHECK_EQ(compileAndRun<int32_t>(proc, a, b), ((a & b) | a));
     3101    }
     3102}
     3103
    30193104static void testBitOrNotNot(int64_t a, int64_t b)
    30203105{
     
    30353120}
    30363121
     3122static void testBitOrNotNot32(int32_t a, int32_t b)
     3123{
     3124    Procedure proc;
     3125    BasicBlock* root = proc.addBlock();
     3126    Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     3127    Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
     3128    Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const32Value>(proc, Origin(), -1));
     3129    Value* notB = root->appendNew<Value>(proc, BitXor, Origin(), argB, root->appendNew<Const32Value>(proc, Origin(), -1));
     3130    root->appendNewControlValue(
     3131        proc, Return, Origin(),
     3132        root->appendNew<Value>(
     3133            proc, BitOr, Origin(),
     3134            notA,
     3135            notB));
     3136
     3137    CHECK_EQ(compileAndRun<int32_t>(proc, a, b), (~a | ~b));
     3138}
     3139
    30373140static void testBitOrNotImm(int64_t a, int64_t b)
    30383141{
     
    30503153
    30513154    CHECK_EQ(compileAndRun<int64_t>(proc, a, b), (~a | b));
     3155}
     3156
     3157static void testBitOrNotImm32(int32_t a, int32_t b)
     3158{
     3159    Procedure proc;
     3160    BasicBlock* root = proc.addBlock();
     3161    Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     3162    Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const32Value>(proc, Origin(), -1));
     3163    Value* cstB = root->appendNew<Const32Value>(proc, Origin(), b);
     3164    root->appendNewControlValue(
     3165        proc, Return, Origin(),
     3166        root->appendNew<Value>(
     3167            proc, BitOr, Origin(),
     3168            notA,
     3169            cstB));
     3170
     3171    CHECK_EQ(compileAndRun<int32_t>(proc, a), (~a | b));
    30523172}
    30533173
     
    32883408    RUN_BINARY(testBitAndArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
    32893409    RUN_BINARY(testBitAndNotNot, int64Operands(), int64Operands());
     3410    RUN_BINARY(testBitAndNotNot32, int32Operands(), int32Operands());
    32903411    RUN_BINARY(testBitAndNotImm, int64Operands(), int64Operands());
     3412    RUN_BINARY(testBitAndNotImm32, int32Operands(), int32Operands());
    32913413   
    32923414    RUN(testBitOrArgs(43, 43));
     
    33523474    RUN_BINARY(testBitOrArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
    33533475    RUN_TERNARY(testBitOrAndAndArgs, int64Operands(), int64Operands(), int64Operands());
     3476    RUN_TERNARY(testBitOrAndAndArgs32, int32Operands(), int32Operands(), int32Operands());
    33543477    RUN_BINARY(testBitOrAndSameArgs, int64Operands(), int64Operands());
     3478    RUN_BINARY(testBitOrAndSameArgs32, int32Operands(), int32Operands());
    33553479    RUN_BINARY(testBitOrNotNot, int64Operands(), int64Operands());
     3480    RUN_BINARY(testBitOrNotNot32, int32Operands(), int32Operands());
    33563481    RUN_BINARY(testBitOrNotImm, int64Operands(), int64Operands());
     3482    RUN_BINARY(testBitOrNotImm32, int32Operands(), int32Operands());
    33573483   
    33583484    RUN_BINARY(testBitXorArgs, int64Operands(), int64Operands());
     
    33943520    RUN(testBitXorImmBitXorArgImm32(24, 0xffff, 7));
    33953521    RUN_TERNARY(testBitXorAndAndArgs, int64Operands(), int64Operands(), int64Operands());
     3522    RUN_TERNARY(testBitXorAndAndArgs32, int32Operands(), int32Operands(), int32Operands());
    33963523    RUN_BINARY(testBitXorAndSameArgs, int64Operands(), int64Operands());
     3524    RUN_BINARY(testBitXorAndSameArgs32, int32Operands(), int32Operands());
    33973525   
    33983526    RUN_UNARY(testBitNotArg, int64Operands());
  • trunk/Source/JavaScriptCore/b3/testb3_3.cpp

    r249743 r249747  
    260260}
    261261
     262void testBitXorAndAndArgs32(int32_t a, int32_t b, int32_t c)
     263{
     264    // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
     265    // ((a & b) ^ (a & c))
     266    // ((a & b) ^ (c & a))
     267    // ((b & a) ^ (a & c))
     268    // ((b & a) ^ (c & a))
     269    for (int i = 0; i < 4; ++i) {
     270        Procedure proc;
     271        BasicBlock* root = proc.addBlock();
     272        Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     273        Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
     274        Value* argC = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
     275        Value* andAB = i & 2 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
     276            : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
     277        Value* andAC = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argC)
     278            : root->appendNew<Value>(proc, BitAnd, Origin(), argC, argA);
     279        root->appendNewControlValue(
     280            proc, Return, Origin(),
     281            root->appendNew<Value>(
     282                proc, BitXor, Origin(),
     283                andAB,
     284                andAC));
     285
     286        CHECK_EQ(compileAndRun<int32_t>(proc, a, b, c), ((a & b) ^ (a & c)));
     287    }
     288}
     289
    262290void testBitXorAndSameArgs(int64_t a, int64_t b)
    263291{
     
    279307   
    280308        CHECK_EQ(compileAndRun<int64_t>(proc, a, b), ((a & b) ^ a));
     309    }
     310}
     311
     312void testBitXorAndSameArgs32(int32_t a, int32_t b)
     313{
     314    // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
     315    // ((a & b) ^ a)
     316    // ((b & a) ^ a)
     317    // (a ^ (a & b))
     318    // (a ^ (b & a))
     319    for (int i = 0; i < 4; ++i) {
     320        Procedure proc;
     321        BasicBlock* root = proc.addBlock();
     322        Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     323        Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
     324        Value* andAB = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
     325            : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
     326        Value* result = i & 2 ? root->appendNew<Value>(proc, BitXor, Origin(), andAB, argA)
     327            : root->appendNew<Value>(proc, BitXor, Origin(), argA, andAB);
     328        root->appendNewControlValue(proc, Return, Origin(), result);
     329
     330        CHECK_EQ(compileAndRun<int32_t>(proc, a, b), ((a & b) ^ a));
    281331    }
    282332}
Note: See TracChangeset for help on using the changeset viewer.