Changeset 220625 in webkit for trunk/Source/JavaScriptCore/b3


Ignore:
Timestamp:
Aug 12, 2017, 11:44:48 AM (8 years ago)
Author:
[email protected]
Message:

Caging shouldn't have to use a patchpoint for adding
https://bugs.webkit.org/show_bug.cgi?id=175483

Reviewed by Mark Lam.
Source/JavaScriptCore:

Caging involves doing a Add(ptr, largeConstant). All of B3's heuristics for how to deal with
constants and associative operations dictate that you always want to sink constants. For example,
Add(Add(a, constant), b) always becomes Add(Add(a, b), constant). This is profitable because in
typical code, it reveals downstream optimizations. But it's terrible in the case of caging, because
we want the large constant (which is shared by all caging operations) to be hoisted. Reassociating to
sink constants obscures the constant in this case. Currently, moveConstants is not smart enough to
reassociate, so instead of sinking largeConstant, it tries (and often fails) to sink some other
constants instead. Without some hacks, this is a 5% Kraken regression and a 1.6% Octane regression.
It's not clear that moveConstants could ever be smart enough to rematerialize that constant and then
hoist it - that would require quite a bit of algebraic reasoning. But the only case we know of where
our current constant reassociation heuristics are wrong is caging. So, we can get away with some
hacks for just stopping B3's reassociation only in this specific case.

Previously, we achieved this by concealing the Add(ptr, largeConstant) inside a patchpoint. That's
OK, but patchpoints are expensive. They require a SharedTask instance. They require callbacks from
the backend, including during register allocation. And they cannot be CSE'd. We do want B3 to know
that if we cage the same pointer in two places, both places will compute the same value.

This patch improves the situation by introducing the Opaque opcode. This is handled by LowerToAir as
if it was Identity, but all prior phases treat it as an unknown pure unary idempotent operation. I.e.
they know that Opaque(x) == Opaque(x) and that Opaque(Opaque(x)) == Opaque(x). But they don't know
that Opaque(x) == x until LowerToAir. So, you can use Opaque exactly when you know that B3 will mess
up your code but Air won't. (Currently we know of no cases where Air messes things up on a large
enough scale to warrant new opcodes.)

This change is perf-neutral, but may start to help as I add more uses of caged() in the FTL. It also
makes the code a bit less ugly.

  • b3/B3LowerToAir.cpp:

(JSC::B3::Air::LowerToAir::shouldCopyPropagate):
(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::effects const):
(JSC::B3::Value::key const):
(JSC::B3::Value::isFree const):
(JSC::B3::Value::typeFor):

  • b3/B3Value.h:
  • b3/B3ValueKey.cpp:

(JSC::B3::ValueKey::materialize const):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::caged):

  • ftl/FTLOutput.cpp:

(JSC::FTL::Output::opaque):

  • ftl/FTLOutput.h:

Websites/webkit.org:


Write documentation for the new Opaque opcode.

  • docs/b3/intermediate-representation.html:
Location:
trunk/Source/JavaScriptCore/b3
Files:
8 edited

Legend:

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

    r220579 r220625  
    190190        case Trunc:
    191191        case Identity:
     192        case Opaque:
    192193            return true;
    193194        default:
     
    33373338        }
    33383339           
    3339         case Identity: {
     3340        case Identity:
     3341        case Opaque: {
    33403342            ASSERT(tmp(m_value->child(0)) == tmp(m_value));
    33413343            return;
  • trunk/Source/JavaScriptCore/b3/B3Opcode.cpp

    r214942 r220625  
    107107        out.print("Identity");
    108108        return;
     109    case Opaque:
     110        out.print("Opaque");
     111        return;
    109112    case Const32:
    110113        out.print("Const32");
  • trunk/Source/JavaScriptCore/b3/B3Opcode.h

    r214592 r220625  
    4444    // Polymorphic identity, usable with any value type.
    4545    Identity,
     46       
     47    // This is an identity, but we prohibit the compiler from realizing this until the bitter end. This can
     48    // be used to block reassociation and other compiler reasoning, if we find that it's wrong or
     49    // unprofitable and we need an escape hatch.
     50    Opaque,
    4651
    4752    // Constants. Use the ConstValue* classes. Constants exist in the control flow, so that we can
     
    259264    // because it unlocks reordering of users of @result and @phantom.
    260265    //
    261     // On X86, this is lowered to a load-load fence and @result uses @phantom directly.
     266    // On X86, this is lowered to a load-load fence and @result folds to zero.
    262267    //
    263268    // On ARM, this is lowered as if like:
  • trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp

    r219702 r220625  
    486486    {
    487487        switch (m_value->opcode()) {
     488        case Opaque:
     489            // Turn this: Opaque(Opaque(value))
     490            // Into this: Opaque(value)
     491            if (m_value->child(0)->opcode() == Opaque) {
     492                replaceWithIdentity(m_value->child(0));
     493                break;
     494            }
     495            break;
     496           
    488497        case Add:
    489498            handleCommutativity();
  • trunk/Source/JavaScriptCore/b3/B3Validate.cpp

    r215533 r220625  
    140140                break;
    141141            case Identity:
     142            case Opaque:
    142143                VALIDATE(!value->kind().hasExtraBits(), ("At ", *value));
    143144                VALIDATE(value->numChildren() == 1, ("At ", *value));
  • trunk/Source/JavaScriptCore/b3/B3Value.cpp

    r215533 r220625  
    547547    case Nop:
    548548    case Identity:
     549    case Opaque:
    549550    case Const32:
    550551    case Const64:
     
    701702ValueKey Value::key() const
    702703{
     704    // NOTE: Except for exotic things like CheckAdd and friends, we want every case here to have a
     705    // corresponding case in ValueKey::materialize().
    703706    switch (opcode()) {
    704707    case FramePointer:
    705708        return ValueKey(kind(), type());
    706709    case Identity:
     710    case Opaque:
    707711    case Abs:
    708712    case Ceil:
     
    795799    case ConstFloat:
    796800    case Identity:
     801    case Opaque:
    797802    case Nop:
    798803        return true;
     
    810815    switch (kind.opcode()) {
    811816    case Identity:
     817    case Opaque:
    812818    case Add:
    813819    case Sub:
  • trunk/Source/JavaScriptCore/b3/B3Value.h

    r215407 r220625  
    329329            break;
    330330        case Identity:
     331        case Opaque:
    331332        case Neg:
    332333        case Clz:
  • trunk/Source/JavaScriptCore/b3/B3ValueKey.cpp

    r208848 r220625  
    11/*
    2  * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    5757Value* ValueKey::materialize(Procedure& proc, Origin origin) const
    5858{
     59    // NOTE: We sometimes cannot return a Value* for some key, like for Check and friends. That's because
     60    // though those nodes have side exit effects. It would be weird to materialize anything that has a side
     61    // exit. We can't possibly know enough about a side exit to know where it would be safe to emit one.
    5962    switch (opcode()) {
    6063    case FramePointer:
    6164        return proc.add<Value>(kind(), type(), origin);
    6265    case Identity:
     66    case Opaque:
     67    case Abs:
     68    case Floor:
     69    case Ceil:
    6370    case Sqrt:
     71    case Neg:
     72    case Depend:
    6473    case SExt8:
    6574    case SExt16:
     
    7281    case FloatToDouble:
    7382    case DoubleToFloat:
    74     case Check:
    7583        return proc.add<Value>(kind(), type(), origin, child(proc, 0));
    7684    case Add:
     
    97105    case AboveEqual:
    98106    case BelowEqual:
     107    case EqualOrUnordered:
    99108        return proc.add<Value>(kind(), type(), origin, child(proc, 0), child(proc, 1));
    100109    case Select:
Note: See TracChangeset for help on using the changeset viewer.