Bug 1295130 - Fold AddI opcode with constant into other AddI with constant r=nbp
authorSander Mathijs van Veen <sander@leaningtech.com>
Tue, 11 Oct 2016 07:04:00 +0200
changeset 317871 07358be0ec02a2aebfdb9fef9dfc41450a5b7e40
parent 317870 9de739c57c87fbfcb47f9c36523d750277c12c94
child 317872 44726da7a2869614b04e2193f17f6060bdbf4ceb
push id33170
push usercbook@mozilla.com
push dateFri, 14 Oct 2016 10:37:07 +0000
treeherderautoland@0d101ebfd95c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1295130
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1295130 - Fold AddI opcode with constant into other AddI with constant r=nbp
js/src/jit/FoldLinearArithConstants.cpp
js/src/jit/FoldLinearArithConstants.h
js/src/jit/Ion.cpp
js/src/jit/JitSpewer.cpp
js/src/jit/JitSpewer.h
js/src/moz.build
js/src/vm/TraceLogging.cpp
js/src/vm/TraceLoggingTypes.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit/FoldLinearArithConstants.cpp
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "jit/FoldLinearArithConstants.h"
+
+#include "jit/IonAnalysis.h"
+#include "jit/MIR.h"
+#include "jit/MIRGenerator.h"
+#include "jit/MIRGraph.h"
+
+using namespace js;
+using namespace jit;
+
+namespace js {
+namespace jit {
+
+// Mark this node and its children as RecoveredOnBailout when they are not used.
+// The marked nodes will be removed during DCE. Marking as RecoveredOnBailout is
+// necessary because the Sink pass is ran before this pass.
+static void
+markNodesAsRecoveredOnBailout(MDefinition* def)
+{
+    if (def->hasLiveDefUses() || !DeadIfUnused(def) || !def->canRecoverOnBailout())
+        return;
+
+    JitSpew(JitSpew_FLAC, "mark as recovered on bailout: %s%u", def->opName(), def->id());
+    def->setRecoveredOnBailoutUnchecked();
+
+    // Recursively mark nodes that do not have multiple uses. This loop is
+    // necessary because a node could be an unused right shift zero or an
+    // unused add, and both need to be marked as RecoveredOnBailout.
+    for (size_t i = 0; i < def->numOperands(); i++)
+        markNodesAsRecoveredOnBailout(def->getOperand(i));
+}
+
+// Fold AddIs with one variable and two or more constants into one AddI.
+static void
+AnalyzeAdd(TempAllocator& alloc, MAdd* add)
+{
+    if (add->specialization() != MIRType::Int32 || add->isRecoveredOnBailout())
+        return;
+
+    if (!add->hasUses())
+        return;
+
+    JitSpew(JitSpew_FLAC, "analyze add: %s%u", add->opName(), add->id());
+
+    SimpleLinearSum sum = ExtractLinearSum(add);
+    if (sum.constant == 0 || !sum.term)
+        return;
+
+    // Do not replace an add where the outcome is the same add instruction.
+    int idx = add->getOperand(0)->isConstant() ? 0 : 1 ;
+    MOZ_ASSERT(add->getOperand(idx)->toConstant()->type() == MIRType::Int32);
+    if (sum.term == add->getOperand(1 - idx) ||
+        sum.constant == add->getOperand(idx)->toConstant()->toInt32())
+    {
+        return;
+    }
+
+    MInstruction* rhs = MConstant::New(alloc, Int32Value(sum.constant));
+    add->block()->insertBefore(add, rhs);
+
+    MAdd* addNew = MAdd::NewAsmJS(alloc, sum.term, rhs, MIRType::Int32);
+
+    add->replaceAllLiveUsesWith(addNew);
+    add->block()->insertBefore(add, addNew);
+    JitSpew(JitSpew_FLAC, "replaced with: %s%u", addNew->opName(), addNew->id());
+    JitSpew(JitSpew_FLAC, "and constant: %s%u (%d)", rhs->opName(), rhs->id(), sum.constant);
+
+    // Mark the stale nodes as RecoveredOnBailout since the Sink pass has
+    // been run before this pass. DCE will then remove the unused nodes.
+    markNodesAsRecoveredOnBailout(add);
+}
+
+bool
+FoldLinearArithConstants(MIRGenerator* mir, MIRGraph& graph)
+{
+    for (PostorderIterator block(graph.poBegin()); block != graph.poEnd(); block++) {
+        if (mir->shouldCancel("Fold Linear Arithmetic Constants (main loop)"))
+            return false;
+
+        for (MInstructionIterator i = block->begin(); i != block->end(); i++) {
+            if (!graph.alloc().ensureBallast())
+                return false;
+
+            if (mir->shouldCancel("Fold Linear Arithmetic Constants (inner loop)"))
+                return false;
+
+            if (i->isAdd())
+                AnalyzeAdd(graph.alloc(), i->toAdd());
+        }
+    }
+    return true;
+}
+
+} /* namespace jit */
+} /* namespace js */
new file mode 100644
--- /dev/null
+++ b/js/src/jit/FoldLinearArithConstants.h
@@ -0,0 +1,22 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef jit_FoldLinearArithConstants_h
+#define jit_FoldLinearArithConstants_h
+
+#include "jit/MIR.h"
+#include "jit/MIRGraph.h"
+
+namespace js {
+namespace jit {
+
+MOZ_MUST_USE bool
+FoldLinearArithConstants(MIRGenerator* mir, MIRGraph& graph);
+
+} /* namespace jit */
+} /* namespace js */
+
+#endif /* jit_FoldLinearArithConstants_h */
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -21,16 +21,17 @@
 #include "jit/BaselineFrame.h"
 #include "jit/BaselineInspector.h"
 #include "jit/BaselineJIT.h"
 #include "jit/CodeGenerator.h"
 #include "jit/EagerSimdUnbox.h"
 #include "jit/EdgeCaseAnalysis.h"
 #include "jit/EffectiveAddressAnalysis.h"
 #include "jit/FlowAliasAnalysis.h"
+#include "jit/FoldLinearArithConstants.h"
 #include "jit/InstructionReordering.h"
 #include "jit/IonAnalysis.h"
 #include "jit/IonBuilder.h"
 #include "jit/IonOptimizationLevels.h"
 #include "jit/JitcodeMap.h"
 #include "jit/JitCommon.h"
 #include "jit/JitCompartment.h"
 #include "jit/JitSpewer.h"
@@ -1786,16 +1787,27 @@ OptimizeMIR(MIRGenerator* mir)
             return false;
         gs.spewPass("Remove Unnecessary Bitops");
         AssertExtendedGraphCoherency(graph);
 
         if (mir->shouldCancel("Remove Unnecessary Bitops"))
             return false;
     }
 
+    {
+        AutoTraceLog log(logger, TraceLogger_FoldLinearArithConstants);
+        if (!FoldLinearArithConstants(mir, graph))
+            return false;
+        gs.spewPass("Fold Linear Arithmetic Constants");
+        AssertBasicGraphCoherency(graph);
+
+        if (mir->shouldCancel("Fold Linear Arithmetic Constants"))
+            return false;
+    }
+
     if (mir->optimizationInfo().eaaEnabled()) {
         AutoTraceLog log(logger, TraceLogger_EffectiveAddressAnalysis);
         EffectiveAddressAnalysis eaa(mir, graph);
         if (!eaa.analyze())
             return false;
         gs.spewPass("Effective Address Analysis");
         AssertExtendedGraphCoherency(graph);
 
--- a/js/src/jit/JitSpewer.cpp
+++ b/js/src/jit/JitSpewer.cpp
@@ -410,16 +410,17 @@ jit::CheckLogging()
             "  scripts    Compiled scripts\n"
             "  mir        MIR information\n"
             "  prune      Prune unused branches\n"
             "  escape     Escape analysis\n"
             "  alias      Alias analysis\n"
             "  alias-sum  Alias analysis: shows summaries for every block\n"
             "  gvn        Global Value Numbering\n"
             "  licm       Loop invariant code motion\n"
+            "  flac       Fold linear arithmetic constants\n"
             "  sincos     Replace sin/cos by sincos\n"
             "  sink       Sink transformation\n"
             "  regalloc   Register allocation\n"
             "  inline     Inlining\n"
             "  snapshots  Snapshot information\n"
             "  codegen    Native code generation\n"
             "  bailouts   Bailouts\n"
             "  caches     Inline caches\n"
@@ -466,16 +467,18 @@ jit::CheckLogging()
     if (ContainsFlag(env, "gvn"))
         EnableChannel(JitSpew_GVN);
     if (ContainsFlag(env, "range"))
         EnableChannel(JitSpew_Range);
     if (ContainsFlag(env, "unroll"))
         EnableChannel(JitSpew_Unrolling);
     if (ContainsFlag(env, "licm"))
         EnableChannel(JitSpew_LICM);
+    if (ContainsFlag(env, "flac"))
+        EnableChannel(JitSpew_FLAC);
     if (ContainsFlag(env, "sincos"))
         EnableChannel(JitSpew_Sincos);
     if (ContainsFlag(env, "sink"))
         EnableChannel(JitSpew_Sink);
     if (ContainsFlag(env, "regalloc"))
         EnableChannel(JitSpew_RegAlloc);
     if (ContainsFlag(env, "inline"))
         EnableChannel(JitSpew_Inlining);
--- a/js/src/jit/JitSpewer.h
+++ b/js/src/jit/JitSpewer.h
@@ -39,16 +39,18 @@ namespace jit {
     /* Information during sinking */        \
     _(Sink)                                 \
     /* Information during Range analysis */ \
     _(Range)                                \
     /* Information during loop unrolling */ \
     _(Unrolling)                            \
     /* Information during LICM */           \
     _(LICM)                                 \
+    /* Info about fold linear constants */  \
+    _(FLAC)                                 \
     /* Information during regalloc */       \
     _(RegAlloc)                             \
     /* Information during inlining */       \
     _(Inlining)                             \
     /* Information during codegen */        \
     _(Codegen)                              \
     /* Debug info about safepoints */       \
     _(Safepoints)                           \
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -242,16 +242,17 @@ UNIFIED_SOURCES += [
     'jit/CodeGenerator.cpp',
     'jit/CompileWrappers.cpp',
     'jit/Disassembler.cpp',
     'jit/EagerSimdUnbox.cpp',
     'jit/EdgeCaseAnalysis.cpp',
     'jit/EffectiveAddressAnalysis.cpp',
     'jit/ExecutableAllocator.cpp',
     'jit/FlowAliasAnalysis.cpp',
+    'jit/FoldLinearArithConstants.cpp',
     'jit/InstructionReordering.cpp',
     'jit/Ion.cpp',
     'jit/IonAnalysis.cpp',
     'jit/IonBuilder.cpp',
     'jit/IonCaches.cpp',
     'jit/IonOptimizationLevels.cpp',
     'jit/JitcodeMap.cpp',
     'jit/JitFrames.cpp',
--- a/js/src/vm/TraceLogging.cpp
+++ b/js/src/vm/TraceLogging.cpp
@@ -696,20 +696,21 @@ TraceLoggerThreadState::init()
             "                 ParserCompileScript, ParserCompileLazy, ParserCompileModule,\n"
             "                 IrregexpCompile, IrregexpExecute, Scripts, Engine, WasmCompilation\n"
             "\n"
             "  IonCompiler    Output all information about compilation. It includes:\n"
             "                 IonCompilation, IonLinking, PruneUnusedBranches, FoldTests,\n"
             "                 SplitCriticalEdges, RenumberBlocks, ScalarReplacement, \n"
             "                 DominatorTree, PhiAnalysis, MakeLoopsContiguous, ApplyTypes, \n"
             "                 EagerSimdUnbox, AliasAnalysis, GVN, LICM, Sincos, RangeAnalysis, \n"
-            "                 LoopUnrolling, EffectiveAddressAnalysis, AlignmentMaskAnalysis, \n"
-            "                 EliminateDeadCode, ReorderInstructions, EdgeCaseAnalysis, \n"
-            "                 EliminateRedundantChecks, AddKeepAliveInstructions, GenerateLIR, \n"
-            "                 RegisterAllocation, GenerateCode, Scripts, IonBuilderRestartLoop\n"
+            "                 LoopUnrolling, FoldLinearArithConstants, EffectiveAddressAnalysis, \n"
+            "                 AlignmentMaskAnalysis, EliminateDeadCode, ReorderInstructions, \n"
+            "                 EdgeCaseAnalysis, EliminateRedundantChecks, \n"
+            "                 AddKeepAliveInstructions, GenerateLIR, RegisterAllocation, \n"
+            "                 GenerateCode, Scripts, IonBuilderRestartLoop\n"
             "\n"
             "  VMSpecific     Output the specific name of the VM call"
             "\n"
             "Specific log items:\n"
         );
         for (uint32_t i = 1; i < TraceLogger_Last; i++) {
             TraceLoggerTextId id = TraceLoggerTextId(i);
             if (!TLTextIdIsTogglable(id))
@@ -768,16 +769,17 @@ TraceLoggerThreadState::init()
         enabledTextIds[TraceLogger_ApplyTypes] = true;
         enabledTextIds[TraceLogger_EagerSimdUnbox] = true;
         enabledTextIds[TraceLogger_AliasAnalysis] = true;
         enabledTextIds[TraceLogger_GVN] = true;
         enabledTextIds[TraceLogger_LICM] = true;
         enabledTextIds[TraceLogger_Sincos] = true;
         enabledTextIds[TraceLogger_RangeAnalysis] = true;
         enabledTextIds[TraceLogger_LoopUnrolling] = true;
+        enabledTextIds[TraceLogger_FoldLinearArithConstants] = true;
         enabledTextIds[TraceLogger_EffectiveAddressAnalysis] = true;
         enabledTextIds[TraceLogger_AlignmentMaskAnalysis] = true;
         enabledTextIds[TraceLogger_EliminateDeadCode] = true;
         enabledTextIds[TraceLogger_ReorderInstructions] = true;
         enabledTextIds[TraceLogger_EdgeCaseAnalysis] = true;
         enabledTextIds[TraceLogger_EliminateRedundantChecks] = true;
         enabledTextIds[TraceLogger_AddKeepAliveInstructions] = true;
         enabledTextIds[TraceLogger_GenerateLIR] = true;
--- a/js/src/vm/TraceLoggingTypes.h
+++ b/js/src/vm/TraceLoggingTypes.h
@@ -53,16 +53,17 @@
     _(AliasAnalysis)                                  \
     _(GVN)                                            \
     _(LICM)                                           \
     _(Sincos)                                         \
     _(RangeAnalysis)                                  \
     _(LoopUnrolling)                                  \
     _(Sink)                                           \
     _(RemoveUnnecessaryBitops)                        \
+    _(FoldLinearArithConstants)                       \
     _(EffectiveAddressAnalysis)                       \
     _(AlignmentMaskAnalysis)                          \
     _(EliminateDeadCode)                              \
     _(ReorderInstructions)                            \
     _(EdgeCaseAnalysis)                               \
     _(EliminateRedundantChecks)                       \
     _(AddKeepAliveInstructions)                       \
     _(GenerateLIR)                                    \