Add a ValueRepReduction phase
authorsbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 2 Apr 2019 15:58:34 +0000 (15:58 +0000)
committersbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 2 Apr 2019 15:58:34 +0000 (15:58 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196234

Reviewed by Filip Pizlo.

This patch adds a ValueRepReduction phase. The main idea here is
to try to reduce DoubleRep(RealNumberUse:ValueRep(DoubleRepUse:@x))
to just be @x. This patch handles such above strengh reduction rules
as long as we prove that all users of the ValueRep can be converted
to using the incoming double value. That way we prevent introducing
a parallel live range for the double value.

This patch tracks the uses of the ValueRep through Phi variables,
so we can convert entire Phi variables to being Double instead
of JSValue if the Phi also has only double uses.

This is implemented through a simple escape analysis. DoubleRep(RealNumberUse:)
and OSR exit hints are not counted as escapes. All other uses are counted
as escapes. Connected Phi graphs are converted to being Double only if the
entire graph is ok with the result being Double.

Some ways we could extend this phase in the future:
- There are a lot of DoubleRep(NumberUse:@ValueRep(@x)) uses. This ensures
  that the result of the DoubleRep of @x is not impure NaN. We could
  handle this case if we introduced a PurifyNaN node and replace the DoubleRep
  with PurifyNaN(@x). Alternatively, we could see if certain users of this
  DoubleRep are okay with impure NaN flowing into them and we'd need to ensure
  their output type is always treated as if the input is impure NaN.
- We could do sinking of ValueRep where we think it's profitable. So instead
  of an escape making it so we never represent the variable as a Double, we
  could make the escape reconstruct the JSValueRep where profitable.
- We can extend this phase to handle Int52Rep if it's profitable.
- We can opt other nodes into accepting incoming Doubles so we no longer
  treat them as escapes.

This patch is somewhere between neutral and a 1% progression on JetStream 2.

* JavaScriptCore.xcodeproj/project.pbxproj:
* Sources.txt:
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
* dfg/DFGValueRepReductionPhase.cpp: Added.
(JSC::DFG::ValueRepReductionPhase::ValueRepReductionPhase):
(JSC::DFG::ValueRepReductionPhase::run):
(JSC::DFG::ValueRepReductionPhase::convertValueRepsToDouble):
(JSC::DFG::performValueRepReduction):
* dfg/DFGValueRepReductionPhase.h: Added.
* runtime/Options.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@243744 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Sources.txt
Source/JavaScriptCore/dfg/DFGPlan.cpp
Source/JavaScriptCore/dfg/DFGValueRepReductionPhase.cpp [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGValueRepReductionPhase.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/Options.h

index 6cf9444..41b7eb6 100644 (file)
@@ -1,3 +1,54 @@
+2019-04-02  Saam barati  <sbarati@apple.com>
+
+        Add a ValueRepReduction phase
+        https://bugs.webkit.org/show_bug.cgi?id=196234
+
+        Reviewed by Filip Pizlo.
+
+        This patch adds a ValueRepReduction phase. The main idea here is
+        to try to reduce DoubleRep(RealNumberUse:ValueRep(DoubleRepUse:@x))
+        to just be @x. This patch handles such above strengh reduction rules
+        as long as we prove that all users of the ValueRep can be converted
+        to using the incoming double value. That way we prevent introducing
+        a parallel live range for the double value.
+        
+        This patch tracks the uses of the ValueRep through Phi variables,
+        so we can convert entire Phi variables to being Double instead
+        of JSValue if the Phi also has only double uses.
+        
+        This is implemented through a simple escape analysis. DoubleRep(RealNumberUse:)
+        and OSR exit hints are not counted as escapes. All other uses are counted
+        as escapes. Connected Phi graphs are converted to being Double only if the
+        entire graph is ok with the result being Double.
+        
+        Some ways we could extend this phase in the future:
+        - There are a lot of DoubleRep(NumberUse:@ValueRep(@x)) uses. This ensures
+          that the result of the DoubleRep of @x is not impure NaN. We could
+          handle this case if we introduced a PurifyNaN node and replace the DoubleRep
+          with PurifyNaN(@x). Alternatively, we could see if certain users of this
+          DoubleRep are okay with impure NaN flowing into them and we'd need to ensure
+          their output type is always treated as if the input is impure NaN.
+        - We could do sinking of ValueRep where we think it's profitable. So instead
+          of an escape making it so we never represent the variable as a Double, we
+          could make the escape reconstruct the JSValueRep where profitable.
+        - We can extend this phase to handle Int52Rep if it's profitable.
+        - We can opt other nodes into accepting incoming Doubles so we no longer
+          treat them as escapes.
+        
+        This patch is somewhere between neutral and a 1% progression on JetStream 2.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::compileInThreadImpl):
+        * dfg/DFGValueRepReductionPhase.cpp: Added.
+        (JSC::DFG::ValueRepReductionPhase::ValueRepReductionPhase):
+        (JSC::DFG::ValueRepReductionPhase::run):
+        (JSC::DFG::ValueRepReductionPhase::convertValueRepsToDouble):
+        (JSC::DFG::performValueRepReduction):
+        * dfg/DFGValueRepReductionPhase.h: Added.
+        * runtime/Options.h:
+
 2019-04-01  Yusuke Suzuki  <ysuzuki@apple.com>
 
         [JSC] JSRunLoopTimer::Manager should be small
index 7574587..ea5ab40 100644 (file)
                52B310FB1974AE610080857C /* FunctionHasExecutedCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B310FA1974AE610080857C /* FunctionHasExecutedCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
                52B311011975B4670080857C /* TypeLocationCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B311001975B4670080857C /* TypeLocationCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
                52C0611F1AA51E1C00B4ADBA /* RuntimeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 52C0611D1AA51E1B00B4ADBA /* RuntimeType.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               52C55566224C2AEA0099F5CC /* DFGValueRepReductionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 52C55565224C2AE70099F5CC /* DFGValueRepReductionPhase.h */; };
                52C952B719A289850069B386 /* TypeProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 52C952B619A289850069B386 /* TypeProfiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
                52CD0F5D2242F569004A18A5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51F0EB6105C86C6B00E6DF1B /* Foundation.framework */; };
                52CD0F5E2242F569004A18A5 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932F5BD90822A1C700736975 /* JavaScriptCore.framework */; };
                52B311001975B4670080857C /* TypeLocationCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TypeLocationCache.h; sourceTree = "<group>"; };
                52B717B41A0597E1007AF4F3 /* ControlFlowProfiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ControlFlowProfiler.cpp; sourceTree = "<group>"; };
                52C0611D1AA51E1B00B4ADBA /* RuntimeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RuntimeType.h; sourceTree = "<group>"; };
+               52C55564224C2AE70099F5CC /* DFGValueRepReductionPhase.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DFGValueRepReductionPhase.cpp; path = dfg/DFGValueRepReductionPhase.cpp; sourceTree = "<group>"; };
+               52C55565224C2AE70099F5CC /* DFGValueRepReductionPhase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DFGValueRepReductionPhase.h; path = dfg/DFGValueRepReductionPhase.h; sourceTree = "<group>"; };
                52C952B619A289850069B386 /* TypeProfiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TypeProfiler.h; sourceTree = "<group>"; };
                52C952B819A28A1C0069B386 /* TypeProfiler.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TypeProfiler.cpp; sourceTree = "<group>"; };
                52CD0F642242F569004A18A5 /* testdfg */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testdfg; sourceTree = BUILT_PRODUCTS_DIR; };
                                0F34B14816D4200E001CDA5A /* DFGUseKind.h */,
                                0F3B3A2915474FF4003ED0FF /* DFGValidate.cpp */,
                                0F3B3A2A15474FF4003ED0FF /* DFGValidate.h */,
+                               52C55564224C2AE70099F5CC /* DFGValueRepReductionPhase.cpp */,
+                               52C55565224C2AE70099F5CC /* DFGValueRepReductionPhase.h */,
                                0F2BDC4E15228BE700CD8910 /* DFGValueSource.cpp */,
                                0F2BDC401522801700CD8910 /* DFGValueSource.h */,
                                0F0123301944EA1B00843A0C /* DFGValueStrength.cpp */,
                                D9722752DC54459B9125B539 /* JSModuleLoader.h in Headers */,
                                996B73201BDA08EF00331B84 /* JSModuleLoader.lut.h in Headers */,
                                E318CBC11B8AEF5100A2929D /* JSModuleNamespaceObject.h in Headers */,
+                               52C55566224C2AEA0099F5CC /* DFGValueRepReductionPhase.h in Headers */,
                                E39DA4A71B7E8B7C0084F33A /* JSModuleRecord.h in Headers */,
                                E33E8D1D1B9013C300346B52 /* JSNativeStdFunction.h in Headers */,
                                E38D999C221B78BB00D50474 /* JSNonDestructibleProxy.h in Headers */,
index 59a35b2..48e7ed9 100644 (file)
@@ -416,6 +416,7 @@ dfg/DFGTypeCheckHoistingPhase.cpp
 dfg/DFGUnificationPhase.cpp
 dfg/DFGUseKind.cpp
 dfg/DFGValidate.cpp
+dfg/DFGValueRepReductionPhase.cpp
 dfg/DFGValueSource.cpp
 dfg/DFGValueStrength.cpp
 dfg/DFGVarargsForwardingPhase.cpp
index 900a61f..76e3c1c 100644 (file)
@@ -71,6 +71,7 @@
 #include "DFGTypeCheckHoistingPhase.h"
 #include "DFGUnificationPhase.h"
 #include "DFGValidate.h"
+#include "DFGValueRepReductionPhase.h"
 #include "DFGVarargsForwardingPhase.h"
 #include "DFGVirtualRegisterAllocationPhase.h"
 #include "DFGWatchpointCollectionPhase.h"
@@ -424,6 +425,8 @@ Plan::CompilationPath Plan::compileInThreadImpl()
             RUN_PHASE(performCriticalEdgeBreaking);
             RUN_PHASE(performObjectAllocationSinking);
         }
+        if (Options::useValueRepElimination())
+            RUN_PHASE(performValueRepReduction);
         if (changed) {
             // State-at-tail and state-at-head will be invalid if we did strength reduction since
             // it might increase live ranges.
diff --git a/Source/JavaScriptCore/dfg/DFGValueRepReductionPhase.cpp b/Source/JavaScriptCore/dfg/DFGValueRepReductionPhase.cpp
new file mode 100644 (file)
index 0000000..cc47fab
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "DFGValueRepReductionPhase.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGGraph.h"
+#include "DFGInsertionSet.h"
+#include "DFGPhase.h"
+#include "DFGPhiChildren.h"
+
+namespace JSC { namespace DFG {
+
+class ValueRepReductionPhase : public Phase {
+    static constexpr bool verbose = false;
+    
+public:
+    ValueRepReductionPhase(Graph& graph)
+        : Phase(graph, "ValueRep reduction")
+        , m_insertionSet(graph)
+    {
+    }
+    
+    bool run()
+    {
+        ASSERT(m_graph.m_form == SSA);
+        return convertValueRepsToDouble();
+    }
+
+private:
+    bool convertValueRepsToDouble()
+    {
+        HashSet<Node*> candidates;
+        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
+            for (Node* node : *block) {
+                if (node->op() == ValueRep && node->child1().useKind() == DoubleRepUse)
+                    candidates.add(node);
+            }
+        }
+
+        if (!candidates.size())
+            return false;
+
+        HashMap<Node*, Vector<Node*>> usersOf;
+        auto getUsersOf = [&] (Node* candidate) {
+            auto iter = usersOf.find(candidate);
+            RELEASE_ASSERT(iter != usersOf.end());
+            return iter->value;
+        };
+
+        for (BasicBlock* block : m_graph.blocksInPreOrder()) {
+            for (Node* node : *block) {
+                if (node->op() == Phi || (node->op() == ValueRep && candidates.contains(node)))
+                    usersOf.add(node, Vector<Node*>());
+
+                Vector<Node*, 3> alreadyAdded;
+                m_graph.doToChildren(node, [&] (Edge edge) {
+                    Node* candidate = edge.node();
+                    if (alreadyAdded.contains(candidate))
+                        return;
+                    auto iter = usersOf.find(candidate);
+                    if (iter == usersOf.end())
+                        return;
+                    iter->value.append(node);
+                    alreadyAdded.append(candidate);
+                });
+            }
+        }
+
+        PhiChildren phiChildren(m_graph);
+
+        // - Any candidate that forwards into a Phi turns that Phi into a candidate.
+        // - Any Phi-1 that forwards into another Phi-2, where Phi-2 is a candidate,
+        //   makes Phi-1 a candidate too.
+        do {
+            HashSet<Node*> eligiblePhis;
+            for (Node* candidate : candidates) {
+                if (candidate->op() == Phi) {
+                    phiChildren.forAllIncomingValues(candidate, [&] (Node* incoming) {
+                        if (incoming->op() == Phi)
+                            eligiblePhis.add(incoming);
+                    });
+                }
+
+                for (Node* user : getUsersOf(candidate)) {
+                    if (user->op() == Upsilon)
+                        eligiblePhis.add(user->phi());
+                }
+            }
+
+            bool sawNewCandidate = false;
+            for (Node* phi : eligiblePhis)
+                sawNewCandidate |= candidates.add(phi).isNewEntry;
+
+            if (!sawNewCandidate)
+                break;
+        } while (true);
+
+        do {
+            HashSet<Node*> toRemove;
+
+            auto isEscaped = [&] (Node* node) {
+                return !candidates.contains(node) || toRemove.contains(node);
+            };
+
+            // Escape rules are as follows:
+            // - Any non-well-known use is an escape. Currently, we allow DoubleRep, Hints, Upsilons (described below).
+            // - Any Upsilon that forwards the candidate into an escaped phi escapes the candidate.
+            // - A Phi remains a candidate as long as all values flowing into it can be made a double.
+            //   Currently, this means these are valid things we support to forward into the Phi:
+            //    - A JSConstant(some number "x") => DoubleConstant("x")
+            //    - ValueRep(DoubleRepUse:@x) => @x
+            //    - A Phi so long as that Phi is not escaped.
+            for (Node* candidate : candidates) {
+                bool ok = true;
+
+                auto dumpEscape = [&] (const char* description, Node* node) {
+                    if (!verbose)
+                        return;
+                    dataLogLn(description);
+                    dataLog("   candidate: ");
+                    m_graph.dump(WTF::dataFile(), "", candidate);
+                    dataLog("   reason: ");
+                    m_graph.dump(WTF::dataFile(), "", node);
+                    dataLogLn();
+                };
+
+                if (candidate->op() == Phi) {
+                    phiChildren.forAllIncomingValues(candidate, [&] (Node* node) {
+                        if (node->op() == JSConstant) {
+                            if (!node->asJSValue().isNumber()) {
+                                ok = false;
+                                dumpEscape("Phi Incoming JSConstant not a number: ", node);
+                            }
+                        } else if (node->op() == ValueRep) {
+                            if (node->child1().useKind() != DoubleRepUse) {
+                                ok = false;
+                                dumpEscape("Phi Incoming ValueRep not DoubleRepUse: ", node);
+                            }
+                        } else if (node->op() == Phi) {
+                            if (isEscaped(node)) {
+                                ok = false;
+                                dumpEscape("An incoming Phi to another Phi is escaped: ", node);
+                            }
+                        } else {
+                            ok = false;
+                            dumpEscape("Unsupported incoming value to Phi: ", node);
+                        }
+                    });
+
+                    if (!ok) {
+                        toRemove.add(candidate);
+                        continue;
+                    }
+                }
+
+                for (Node* user : getUsersOf(candidate)) {
+                    switch (user->op()) {
+                    case DoubleRep:
+                        if (user->child1().useKind() != RealNumberUse) {
+                            ok = false;
+                            dumpEscape("DoubleRep escape: ", user);
+                        }
+                        break;
+
+                    case PutHint:
+                    case MovHint:
+                        break;
+
+                    case Upsilon: {
+                        Node* phi = user->phi();
+                        if (isEscaped(phi)) {
+                            dumpEscape("Upsilon of escaped phi escapes candidate: ", phi);
+                            ok = false;
+                        }
+                        break;
+                    }
+
+                    default:
+                        dumpEscape("Normal escape: ", user);
+                        ok = false;
+                        break;
+                    }
+
+                    if (!ok)
+                        break;
+                }
+
+                if (!ok)
+                    toRemove.add(candidate);
+            }
+
+            if (toRemove.isEmpty())
+                break;
+
+            for (Node* node : toRemove)
+                candidates.remove(node);
+        } while (true);
+
+        if (!candidates.size())
+            return false;
+
+        NodeOrigin originForConstant = m_graph.block(0)->at(0)->origin;
+        HashSet<Node*> doubleRepRealCheckLocations;
+
+        for (Node* candidate : candidates) {
+            if (verbose)
+                dataLogLn("Optimized: ", candidate);
+
+            Node* resultNode;
+            if (candidate->op() == Phi) {
+                resultNode = candidate;
+
+                for (Node* upsilon : phiChildren.upsilonsOf(candidate)) {
+                    Node* incomingValue = upsilon->child1().node();
+                    Node* newChild;
+                    if (incomingValue->op() == JSConstant) {
+                        double number = incomingValue->asJSValue().asNumber();
+                        newChild = m_insertionSet.insertConstant(0, originForConstant, jsDoubleNumber(number), DoubleConstant);
+                    } else if (incomingValue->op() == ValueRep) {
+                        // We don't care about the incoming value being an impure NaN because users of
+                        // this Phi are either OSR exit or DoubleRep(RealNumberUse:@phi)
+                        ASSERT(incomingValue->child1().useKind() == DoubleRepUse);
+                        newChild = incomingValue->child1().node();
+                    } else if (incomingValue->op() == Phi)
+                        newChild = incomingValue;
+                    else
+                        RELEASE_ASSERT_NOT_REACHED();
+
+                    upsilon->child1() = Edge(newChild, DoubleRepUse);
+                }
+
+                candidate->setResult(NodeResultDouble);
+            } else if (candidate->op() == ValueRep)
+                resultNode = candidate->child1().node();
+            else
+                RELEASE_ASSERT_NOT_REACHED();
+
+            for (Node* user : getUsersOf(candidate)) {
+                switch (user->op()) {
+                case DoubleRep: {
+                    ASSERT(user->child1().useKind() == RealNumberUse);
+                    user->convertToIdentityOn(resultNode);
+                    doubleRepRealCheckLocations.add(user);
+                    break;
+                }
+                    
+                case PutHint:
+                    user->child2() = Edge(resultNode, DoubleRepUse);
+                    break;
+
+                case MovHint:
+                    user->child1() = Edge(resultNode, DoubleRepUse);
+                    break;
+
+                case Upsilon: {
+                    Node* phi = user->phi();
+                    ASSERT_UNUSED(phi, candidates.contains(phi));
+                    break;
+                }
+
+                default:
+                    RELEASE_ASSERT_NOT_REACHED();
+                    break;
+                }
+            }
+        }
+
+        // Insert constants.
+        m_insertionSet.execute(m_graph.block(0));
+
+        // Insert checks that are needed when removing DoubleRep(RealNumber:@x)
+        if (doubleRepRealCheckLocations.size()) {
+            for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
+                for (unsigned i = 0; i < block->size(); ++i) {
+                    Node* node = block->at(i);
+                    if (node->op() != Identity) {
+                        ASSERT(!doubleRepRealCheckLocations.contains(node));
+                        continue;
+                    }
+                    if (!doubleRepRealCheckLocations.contains(node))
+                        continue;
+                    m_insertionSet.insertNode(
+                        i, SpecNone, Check, node->origin,
+                        Edge(node->child1().node(), DoubleRepRealUse));
+                }
+
+                m_insertionSet.execute(block);
+            }
+        }
+
+        return true;
+    }
+
+    InsertionSet m_insertionSet;
+};
+    
+bool performValueRepReduction(Graph& graph)
+{
+    return runPhase<ValueRepReductionPhase>(graph);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
diff --git a/Source/JavaScriptCore/dfg/DFGValueRepReductionPhase.h b/Source/JavaScriptCore/dfg/DFGValueRepReductionPhase.h
new file mode 100644 (file)
index 0000000..26fc76e
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#pragma once
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+class Graph;
+
+// Tries to eliminate DoubleRep(ValueRep) roundtrips.
+
+bool performValueRepReduction(Graph&);
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
index d91becc..1a1cf05 100644 (file)
@@ -283,6 +283,7 @@ constexpr bool enableWebAssemblyStreamingApi = false;
     v(bool, useMovHintRemoval, true, Normal, nullptr) \
     v(bool, usePutStackSinking, true, Normal, nullptr) \
     v(bool, useObjectAllocationSinking, true, Normal, nullptr) \
+    v(bool, useValueRepElimination, true, Normal, nullptr) \
     v(bool, useArityFixupInlining, true, Normal, nullptr) \
     v(bool, logExecutableAllocation, false, Normal, nullptr) \
     \