Bug 1295130 - Merge AddI into LoadUnboxedScalar r=nbp
authorSander Mathijs van Veen <sander@leaningtech.com>
Tue, 11 Oct 2016 07:06:00 +0200
changeset 317872 44726da7a2869614b04e2193f17f6060bdbf4ceb
parent 317871 07358be0ec02a2aebfdb9fef9dfc41450a5b7e40
child 317873 9f289545ab7d9f3a3b5b18452818df1e3e44f382
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 - Merge AddI into LoadUnboxedScalar r=nbp
js/src/jit/EffectiveAddressAnalysis.cpp
js/src/jit/JitSpewer.cpp
js/src/jit/JitSpewer.h
js/src/jit/MIR.h
--- a/js/src/jit/EffectiveAddressAnalysis.cpp
+++ b/js/src/jit/EffectiveAddressAnalysis.cpp
@@ -1,15 +1,16 @@
 /* -*- 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/EffectiveAddressAnalysis.h"
+#include "jit/IonAnalysis.h"
 #include "jit/MIR.h"
 #include "jit/MIRGraph.h"
 
 using namespace js;
 using namespace jit;
 
 static void
 AnalyzeLsh(TempAllocator& alloc, MLsh* lsh)
@@ -95,16 +96,86 @@ AnalyzeLsh(TempAllocator& alloc, MLsh* l
     if (base->isRecoveredOnBailout())
         return;
 
     MEffectiveAddress* eaddr = MEffectiveAddress::New(alloc, base, index, scale, displacement);
     last->replaceAllUsesWith(eaddr);
     last->block()->insertAfter(last, eaddr);
 }
 
+// Transform:
+//
+//   [AddI]
+//   addl       $9, %esi
+//   [LoadUnboxedScalar]
+//   movsd      0x0(%rbx,%rsi,8), %xmm4
+//
+// into:
+//
+//   [LoadUnboxedScalar]
+//   movsd      0x48(%rbx,%rsi,8), %xmm4
+//
+// This is possible when the AddI is only used by the LoadUnboxedScalar opcode.
+static void
+AnalyzeLoadUnboxedScalar(TempAllocator& alloc, MLoadUnboxedScalar* load)
+{
+    if (load->isRecoveredOnBailout())
+        return;
+
+    if (!load->getOperand(1)->isAdd())
+        return;
+
+    JitSpew(JitSpew_EAA, "analyze: %s%u", load->opName(), load->id());
+
+    MAdd* add = load->getOperand(1)->toAdd();
+
+    if (add->specialization() != MIRType::Int32 || !add->hasUses() ||
+        add->truncateKind() != MDefinition::TruncateKind::Truncate)
+    {
+        return;
+    }
+
+    MDefinition* lhs = add->lhs();
+    MDefinition* rhs = add->rhs();
+    MDefinition* constant = nullptr;
+    MDefinition* node = nullptr;
+
+    if (lhs->isConstant()) {
+        constant = lhs;
+        node = rhs;
+    } else if (rhs->isConstant()) {
+        constant = rhs;
+        node = lhs;
+    } else
+        return;
+
+    MOZ_ASSERT(constant->type() == MIRType::Int32);
+
+    size_t storageSize = Scalar::byteSize(load->storageType());
+    int32_t c1 = load->offsetAdjustment();
+    int32_t c2 = 0;
+    if (!SafeMul(constant->maybeConstantValue()->toInt32(), storageSize, &c2))
+        return;
+
+    int32_t offset = 0;
+    if (!SafeAdd(c1, c2, &offset))
+        return;
+
+    JitSpew(JitSpew_EAA, "set offset: %d + %d = %d on: %s%u", c1, c2, offset,
+            load->opName(), load->id());
+    load->setOffsetAdjustment(offset);
+    load->replaceOperand(1, node);
+
+    if (!add->hasLiveDefUses() && DeadIfUnused(add) && add->canRecoverOnBailout()) {
+        JitSpew(JitSpew_EAA, "mark as recovered on bailout: %s%u",
+                add->opName(), add->id());
+        add->setRecoveredOnBailoutUnchecked();
+    }
+}
+
 template<typename AsmJSMemoryAccess>
 bool
 EffectiveAddressAnalysis::tryAddDisplacement(AsmJSMemoryAccess* ins, int32_t o)
 {
 #ifdef WASM_HUGE_MEMORY
     // Compute the new offset. Check for overflow.
     uint32_t oldOffset = ins->offset();
     uint32_t newOffset = oldOffset + o;
@@ -189,16 +260,18 @@ EffectiveAddressAnalysis::analyze()
                 return false;
 
             // Note that we don't check for MAsmJSCompareExchangeHeap
             // or MAsmJSAtomicBinopHeap, because the backend and the OOB
             // mechanism don't support non-zero offsets for them yet
             // (TODO bug 1254935).
             if (i->isLsh())
                 AnalyzeLsh(graph_.alloc(), i->toLsh());
+            else if (i->isLoadUnboxedScalar())
+                AnalyzeLoadUnboxedScalar(graph_.alloc(), i->toLoadUnboxedScalar());
             else if (i->isAsmJSLoadHeap())
                 analyzeAsmJSHeapAccess(i->toAsmJSLoadHeap());
             else if (i->isAsmJSStoreHeap())
                 analyzeAsmJSHeapAccess(i->toAsmJSStoreHeap());
         }
     }
     return true;
 }
--- a/js/src/jit/JitSpewer.cpp
+++ b/js/src/jit/JitSpewer.cpp
@@ -411,16 +411,17 @@ jit::CheckLogging()
             "  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"
+            "  eaa        Effective address analysis\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"
@@ -469,16 +470,18 @@ jit::CheckLogging()
     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, "eaa"))
+        EnableChannel(JitSpew_EAA);
     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
@@ -41,16 +41,18 @@ namespace jit {
     /* Information during Range analysis */ \
     _(Range)                                \
     /* Information during loop unrolling */ \
     _(Unrolling)                            \
     /* Information during LICM */           \
     _(LICM)                                 \
     /* Info about fold linear constants */  \
     _(FLAC)                                 \
+    /* Effective address analysis info */   \
+    _(EAA)                                  \
     /* Information during regalloc */       \
     _(RegAlloc)                             \
     /* Information during inlining */       \
     _(Inlining)                             \
     /* Information during codegen */        \
     _(Codegen)                              \
     /* Debug info about safepoints */       \
     _(Safepoints)                           \
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -9961,16 +9961,19 @@ class MLoadUnboxedScalar
         return requiresBarrier_;
     }
     bool canonicalizeDoubles() const {
         return canonicalizeDoubles_;
     }
     int32_t offsetAdjustment() const {
         return offsetAdjustment_;
     }
+    void setOffsetAdjustment(int32_t offsetAdjustment) {
+        offsetAdjustment_ = offsetAdjustment;
+    }
     AliasSet getAliasSet() const override {
         // When a barrier is needed make the instruction effectful by
         // giving it a "store" effect.
         if (requiresBarrier_)
             return AliasSet::Store(AliasSet::UnboxedElement);
         return AliasSet::Load(AliasSet::UnboxedElement);
     }