Ignore:
Timestamp:
Mar 10, 2018, 11:16:15 PM (7 years ago)
Author:
Yusuke Suzuki
Message:

B3::reduceStrength should canonicalize integer comparisons
https://bugs.webkit.org/show_bug.cgi?id=150958

Reviewed by Filip Pizlo.

This patch sorts operands of comparisons by flipping opcode. For example, Above(0, @2) is
converted to Below(@2, 0). This sorting is the same to handleCommutativity rule. Since we
canonicalize comparisons to have constant value at least on the right hand side, we can
remove pattern matchings checking leftImm in B3LowerToAir.

Since this flipping changes the opcode of the value, to achieve safely, we just create a
new value which has flipped opcode and swapped operands. If we can fold it to a constant,
we replace m_value with this constant. If we fail to fold it to constant, we replace
m_value with the flipped one.

These comparisons are already handled in testb3.

  • b3/B3LowerToAir.cpp:
  • b3/B3ReduceStrength.cpp:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp

    r221954 r229513  
    16671667
    16681668        case LessThan:
    1669             // FIXME: We could do a better job of canonicalizing integer comparisons.
    1670             // https://bugs.webkit.org/show_bug.cgi?id=150958
    1671 
    1672             replaceWithNewValue(
    1673                 m_proc.addBoolConstant(
    1674                     m_value->origin(),
    1675                     m_value->child(0)->lessThanConstant(m_value->child(1))));
    1676             break;
    1677 
    16781669        case GreaterThan:
    1679             replaceWithNewValue(
    1680                 m_proc.addBoolConstant(
    1681                     m_value->origin(),
    1682                     m_value->child(0)->greaterThanConstant(m_value->child(1))));
    1683             break;
    1684 
    16851670        case LessEqual:
    1686             replaceWithNewValue(
    1687                 m_proc.addBoolConstant(
    1688                     m_value->origin(),
    1689                     m_value->child(0)->lessEqualConstant(m_value->child(1))));
    1690             break;
    1691 
    16921671        case GreaterEqual:
    1693             replaceWithNewValue(
    1694                 m_proc.addBoolConstant(
    1695                     m_value->origin(),
    1696                     m_value->child(0)->greaterEqualConstant(m_value->child(1))));
    1697             break;
    1698 
    16991672        case Above:
    1700             replaceWithNewValue(
    1701                 m_proc.addBoolConstant(
    1702                     m_value->origin(),
    1703                     m_value->child(0)->aboveConstant(m_value->child(1))));
    1704             break;
    1705 
    17061673        case Below:
    1707             replaceWithNewValue(
    1708                 m_proc.addBoolConstant(
    1709                     m_value->origin(),
    1710                     m_value->child(0)->belowConstant(m_value->child(1))));
    1711             break;
    1712 
    17131674        case AboveEqual:
    1714             replaceWithNewValue(
    1715                 m_proc.addBoolConstant(
    1716                     m_value->origin(),
    1717                     m_value->child(0)->aboveEqualConstant(m_value->child(1))));
    1718             break;
    1719 
    1720         case BelowEqual:
    1721             replaceWithNewValue(
    1722                 m_proc.addBoolConstant(
    1723                     m_value->origin(),
    1724                     m_value->child(0)->belowEqualConstant(m_value->child(1))));
    1725             break;
     1675        case BelowEqual: {
     1676            auto* value = newComparisonVaueIfNecessary();
     1677            TriState result = MixedTriState;
     1678            switch (value->opcode()) {
     1679            case LessThan:
     1680                result = value->child(1)->greaterThanConstant(value->child(0));
     1681                break;
     1682            case GreaterThan:
     1683                result = value->child(1)->lessThanConstant(value->child(0));
     1684                break;
     1685            case LessEqual:
     1686                result = value->child(1)->greaterEqualConstant(value->child(0));
     1687                break;
     1688            case GreaterEqual:
     1689                result = value->child(1)->lessEqualConstant(value->child(0));
     1690                break;
     1691            case Above:
     1692                result = value->child(1)->belowConstant(value->child(0));
     1693                break;
     1694            case Below:
     1695                result = value->child(1)->aboveConstant(value->child(0));
     1696                break;
     1697            case AboveEqual:
     1698                result = value->child(1)->belowEqualConstant(value->child(0));
     1699                break;
     1700            case BelowEqual:
     1701                result = value->child(1)->aboveEqualConstant(value->child(0));
     1702                break;
     1703            default:
     1704                RELEASE_ASSERT_NOT_REACHED();
     1705                break;
     1706            }
     1707
     1708            if (auto* constant = m_proc.addBoolConstant(value->origin(), result)) {
     1709                replaceWithNewValue(constant);
     1710                break;
     1711            }
     1712
     1713            // Replace with newly created "value". Its opcode is flipped and operands are swapped from m_value.
     1714            if (m_value != value)
     1715                replaceWithNewValue(value);
     1716            break;
     1717        }
    17261718
    17271719        case EqualOrUnordered:
     
    21352127    }
    21362128
     2129    static bool shouldSwapBinaryOperands(Value* value)
     2130    {
     2131        // Note that we have commutative operations that take more than two children. Those operations may
     2132        // commute their first two children while leaving the rest unaffected.
     2133        ASSERT(value->numChildren() >= 2);
     2134
     2135        // Leave it alone if the right child is a constant.
     2136        if (value->child(1)->isConstant()
     2137            || value->child(0)->opcode() == AtomicStrongCAS)
     2138            return false;
     2139
     2140        if (value->child(0)->isConstant())
     2141            return true;
     2142
     2143        if (value->child(1)->opcode() == AtomicStrongCAS)
     2144            return true;
     2145
     2146        // Sort the operands. This is an important canonicalization. We use the index instead of
     2147        // the address to make this at least slightly deterministic.
     2148        if (value->child(0)->index() > value->child(1)->index())
     2149            return true;
     2150
     2151        return false;
     2152    }
     2153
    21372154    // Turn this: Add(constant, value)
    21382155    // Into this: Add(value, constant)
     
    21442161    void handleCommutativity()
    21452162    {
    2146         // Note that we have commutative operations that take more than two children. Those operations may
    2147         // commute their first two children while leaving the rest unaffected.
    2148         ASSERT(m_value->numChildren() >= 2);
    2149        
    2150         // Leave it alone if the right child is a constant.
    2151         if (m_value->child(1)->isConstant()
    2152             || m_value->child(0)->opcode() == AtomicStrongCAS)
    2153             return;
    2154        
    2155         auto swap = [&] () {
     2163        if (shouldSwapBinaryOperands(m_value)) {
    21562164            std::swap(m_value->child(0), m_value->child(1));
    21572165            m_changed = true;
     2166        }
     2167    }
     2168
     2169    Value* newComparisonVaueIfNecessary()
     2170    {
     2171        auto flip = [] (Opcode opcode) {
     2172            switch (opcode) {
     2173            case LessThan:
     2174                return GreaterThan;
     2175            case GreaterThan:
     2176                return LessThan;
     2177            case LessEqual:
     2178                return GreaterEqual;
     2179            case GreaterEqual:
     2180                return LessEqual;
     2181            case Above:
     2182                return Below;
     2183            case Below:
     2184                return Above;
     2185            case AboveEqual:
     2186                return BelowEqual;
     2187            case BelowEqual:
     2188                return AboveEqual;
     2189            default:
     2190                return opcode;
     2191            }
    21582192        };
    2159        
    2160         if (m_value->child(0)->isConstant())
    2161             return swap();
    2162        
    2163         if (m_value->child(1)->opcode() == AtomicStrongCAS)
    2164             return swap();
    2165        
    2166         // Sort the operands. This is an important canonicalization. We use the index instead of
    2167         // the address to make this at least slightly deterministic.
    2168         if (m_value->child(0)->index() > m_value->child(1)->index())
    2169             return swap();
     2193        if (shouldSwapBinaryOperands(m_value)) {
     2194            m_changed = true;
     2195            return m_proc.add<Value>(flip(m_value->opcode()), m_value->origin(), m_value->child(1), m_value->child(0));
     2196        }
     2197        return m_value;
    21702198    }
    21712199
Note: See TracChangeset for help on using the changeset viewer.