Bug 998485 - IonMonkey: Remove analyzeEdge* functions. r=nbp
☠☠ backed out by 43ad7f4f490e ☠ ☠
authorRémi WENG <contact@ixartz.com>
Thu, 14 Aug 2014 15:11:43 +0200
changeset 199531 04892482d288db39e4bcc13bb7dd98c36609daf9
parent 199530 c975c3d3545deca49b6d7cf341d97b5166467f49
child 199532 909de22e9deca90b3ac258c60ca2c3b7d9976d22
push id27309
push userryanvm@gmail.com
push dateThu, 14 Aug 2014 20:21:31 +0000
treeherdermozilla-central@31db71673c6e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs998485
milestone34.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 998485 - IonMonkey: Remove analyzeEdge* functions. r=nbp
js/src/jit/EdgeCaseAnalysis.cpp
js/src/jit/EdgeCaseAnalysis.h
js/src/jit/Ion.cpp
js/src/jit/MIR.cpp
js/src/jit/MIR.h
js/src/moz.build
deleted file mode 100644
--- a/js/src/jit/EdgeCaseAnalysis.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/* -*- 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/EdgeCaseAnalysis.h"
-
-#include "jit/MIR.h"
-#include "jit/MIRGraph.h"
-
-using namespace js;
-using namespace js::jit;
-
-EdgeCaseAnalysis::EdgeCaseAnalysis(MIRGenerator *mir, MIRGraph &graph)
-  : mir(mir), graph(graph)
-{
-}
-
-bool
-EdgeCaseAnalysis::analyzeLate()
-{
-    // Renumber definitions for NeedNegativeZeroCheck under analyzeEdgeCasesBackward.
-    uint32_t nextId = 0;
-
-    for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
-        if (mir->shouldCancel("Analyze Late (first loop)"))
-            return false;
-        for (MDefinitionIterator iter(*block); iter; iter++) {
-            iter->setId(nextId++);
-            iter->analyzeEdgeCasesForward();
-        }
-        block->lastIns()->setId(nextId++);
-    }
-
-    for (PostorderIterator block(graph.poBegin()); block != graph.poEnd(); block++) {
-        if (mir->shouldCancel("Analyze Late (second loop)"))
-            return false;
-        for (MInstructionReverseIterator riter(block->rbegin()); riter != block->rend(); riter++)
-            riter->analyzeEdgeCasesBackward();
-    }
-
-    return true;
-}
deleted file mode 100644
--- a/js/src/jit/EdgeCaseAnalysis.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* -*- 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_EdgeCaseAnalysis_h
-#define jit_EdgeCaseAnalysis_h
-
-#include "jit/MIRGenerator.h"
-
-namespace js {
-namespace jit {
-
-class MIRGraph;
-
-class EdgeCaseAnalysis
-{
-    MIRGenerator *mir;
-    MIRGraph &graph;
-
-  public:
-    EdgeCaseAnalysis(MIRGenerator *mir, MIRGraph &graph);
-    bool analyzeLate();
-};
-
-
-} // namespace jit
-} // namespace js
-
-#endif /* jit_EdgeCaseAnalysis_h */
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -16,17 +16,16 @@
 #include "gc/Marking.h"
 #include "jit/AliasAnalysis.h"
 #include "jit/BacktrackingAllocator.h"
 #include "jit/BaselineDebugModeOSR.h"
 #include "jit/BaselineFrame.h"
 #include "jit/BaselineInspector.h"
 #include "jit/BaselineJIT.h"
 #include "jit/CodeGenerator.h"
-#include "jit/EdgeCaseAnalysis.h"
 #include "jit/EffectiveAddressAnalysis.h"
 #include "jit/IonAnalysis.h"
 #include "jit/IonBuilder.h"
 #include "jit/IonOptimizationLevels.h"
 #include "jit/IonSpewer.h"
 #include "jit/JitcodeMap.h"
 #include "jit/JitCommon.h"
 #include "jit/JitCompartment.h"
@@ -1575,28 +1574,16 @@ OptimizeMIR(MIRGenerator *mir)
 
         if (mir->shouldCancel("Make loops contiguous"))
             return false;
     }
 
     // Passes after this point must not move instructions; these analyses
     // depend on knowing the final order in which instructions will execute.
 
-    if (mir->optimizationInfo().edgeCaseAnalysisEnabled()) {
-        AutoTraceLog log(logger, TraceLogger::EdgeCaseAnalysis);
-        EdgeCaseAnalysis edgeCaseAnalysis(mir, graph);
-        if (!edgeCaseAnalysis.analyzeLate())
-            return false;
-        IonSpewPass("Edge Case Analysis (Late)");
-        AssertGraphCoherency(graph);
-
-        if (mir->shouldCancel("Edge Case Analysis (Late)"))
-            return false;
-    }
-
     if (mir->optimizationInfo().eliminateRedundantChecksEnabled()) {
         AutoTraceLog log(logger, TraceLogger::EliminateRedundantChecks);
         // Note: check elimination has to run after all other passes that move
         // instructions. Since check uses are replaced with the actual index,
         // code motion after this pass could incorrectly move a load or store
         // before its bounds check.
         if (!EliminateRedundantChecks(graph))
             return false;
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -217,26 +217,16 @@ MDefinition::congruentIfOperandsEqual(co
 
 MDefinition *
 MDefinition::foldsTo(TempAllocator &alloc)
 {
     // In the default case, there are no constants to fold.
     return this;
 }
 
-void
-MDefinition::analyzeEdgeCasesForward()
-{
-}
-
-void
-MDefinition::analyzeEdgeCasesBackward()
-{
-}
-
 static bool
 MaybeEmulatesUndefined(MDefinition *op)
 {
     if (!op->mightBeType(MIRType_Object))
         return false;
 
     types::TemporaryTypeSet *types = op->resultTypeSet();
     if (!types)
@@ -1399,119 +1389,16 @@ MUrsh::infer(BaselineInspector *inspecto
         setResultType(MIRType_Double);
         return;
     }
 
     specialization_ = MIRType_Int32;
     setResultType(MIRType_Int32);
 }
 
-static inline bool
-NeedNegativeZeroCheck(MDefinition *def)
-{
-    // Test if all uses have the same semantics for -0 and 0
-    for (MUseIterator use = def->usesBegin(); use != def->usesEnd(); use++) {
-        if (use->consumer()->isResumePoint())
-            continue;
-
-        MDefinition *use_def = use->consumer()->toDefinition();
-        switch (use_def->op()) {
-          case MDefinition::Op_Add: {
-            // If add is truncating -0 and 0 are observed as the same.
-            if (use_def->toAdd()->isTruncated())
-                break;
-
-            // x + y gives -0, when both x and y are -0
-
-            // Figure out the order in which the addition's operands will
-            // execute. EdgeCaseAnalysis::analyzeLate has renumbered the MIR
-            // definitions for us so that this just requires comparing ids.
-            MDefinition *first = use_def->toAdd()->getOperand(0);
-            MDefinition *second = use_def->toAdd()->getOperand(1);
-            if (first->id() > second->id()) {
-                MDefinition *temp = first;
-                first = second;
-                second = temp;
-            }
-
-            if (def == first) {
-                // Negative zero checks can be removed on the first executed
-                // operand only if it is guaranteed the second executed operand
-                // will produce a value other than -0. While the second is
-                // typed as an int32, a bailout taken between execution of the
-                // operands may change that type and cause a -0 to flow to the
-                // second.
-                //
-                // There is no way to test whether there are any bailouts
-                // between execution of the operands, so remove negative
-                // zero checks from the first only if the second's type is
-                // independent from type changes that may occur after bailing.
-                switch (second->op()) {
-                  case MDefinition::Op_Constant:
-                  case MDefinition::Op_BitAnd:
-                  case MDefinition::Op_BitOr:
-                  case MDefinition::Op_BitXor:
-                  case MDefinition::Op_BitNot:
-                  case MDefinition::Op_Lsh:
-                  case MDefinition::Op_Rsh:
-                    break;
-                  default:
-                    return true;
-                }
-            }
-
-            // The negative zero check can always be removed on the second
-            // executed operand; by the time this executes the first will have
-            // been evaluated as int32 and the addition's result cannot be -0.
-            break;
-          }
-          case MDefinition::Op_Sub:
-            // If sub is truncating -0 and 0 are observed as the same
-            if (use_def->toSub()->isTruncated())
-                break;
-            /* Fall through...  */
-          case MDefinition::Op_StoreElement:
-          case MDefinition::Op_StoreElementHole:
-          case MDefinition::Op_LoadElement:
-          case MDefinition::Op_LoadElementHole:
-          case MDefinition::Op_LoadTypedArrayElement:
-          case MDefinition::Op_LoadTypedArrayElementHole:
-          case MDefinition::Op_CharCodeAt:
-          case MDefinition::Op_Mod:
-            // Only allowed to remove check when definition is the second operand
-            if (use_def->getOperand(0) == def)
-                return true;
-            for (size_t i = 2, e = use_def->numOperands(); i < e; i++) {
-                if (use_def->getOperand(i) == def)
-                    return true;
-            }
-            break;
-          case MDefinition::Op_BoundsCheck:
-            // Only allowed to remove check when definition is the first operand
-            if (use_def->toBoundsCheck()->getOperand(1) == def)
-                return true;
-            break;
-          case MDefinition::Op_ToString:
-          case MDefinition::Op_FromCharCode:
-          case MDefinition::Op_TableSwitch:
-          case MDefinition::Op_Compare:
-          case MDefinition::Op_BitAnd:
-          case MDefinition::Op_BitOr:
-          case MDefinition::Op_BitXor:
-          case MDefinition::Op_Abs:
-          case MDefinition::Op_TruncateToInt32:
-            // Always allowed to remove check. No matter which operand.
-            break;
-          default:
-            return true;
-        }
-    }
-    return false;
-}
-
 MDefinition *
 MBinaryArithInstruction::foldsTo(TempAllocator &alloc)
 {
     if (specialization_ == MIRType_None)
         return this;
 
     MDefinition *lhs = getOperand(0);
     MDefinition *rhs = getOperand(1);
@@ -1615,55 +1502,16 @@ MDiv::foldsTo(TempAllocator &alloc)
         return folded;
 
     if (MDefinition *folded = EvaluateExactReciprocal(alloc, this))
         return folded;
 
     return this;
 }
 
-void
-MDiv::analyzeEdgeCasesForward()
-{
-    // This is only meaningful when doing integer division.
-    if (specialization_ != MIRType_Int32)
-        return;
-
-    // Try removing divide by zero check
-    if (rhs()->isConstant() && !rhs()->toConstant()->value().isInt32(0))
-        canBeDivideByZero_ = false;
-
-    // If lhs is a constant int != INT32_MIN, then
-    // negative overflow check can be skipped.
-    if (lhs()->isConstant() && !lhs()->toConstant()->value().isInt32(INT32_MIN))
-        canBeNegativeOverflow_ = false;
-
-    // If rhs is a constant int != -1, likewise.
-    if (rhs()->isConstant() && !rhs()->toConstant()->value().isInt32(-1))
-        canBeNegativeOverflow_ = false;
-
-    // If lhs is != 0, then negative zero check can be skipped.
-    if (lhs()->isConstant() && !lhs()->toConstant()->value().isInt32(0))
-        setCanBeNegativeZero(false);
-
-    // If rhs is >= 0, likewise.
-    if (rhs()->isConstant()) {
-        const js::Value &val = rhs()->toConstant()->value();
-        if (val.isInt32() && val.toInt32() >= 0)
-            setCanBeNegativeZero(false);
-    }
-}
-
-void
-MDiv::analyzeEdgeCasesBackward()
-{
-    if (canBeNegativeZero() && !NeedNegativeZeroCheck(this))
-        setCanBeNegativeZero(false);
-}
-
 bool
 MDiv::fallible() const
 {
     return !isTruncated();
 }
 
 MDefinition *
 MMod::foldsTo(TempAllocator &alloc)
@@ -1672,33 +1520,16 @@ MMod::foldsTo(TempAllocator &alloc)
         return this;
 
     if (MDefinition *folded = EvaluateConstantOperands(alloc, this))
         return folded;
 
     return this;
 }
 
-void
-MMod::analyzeEdgeCasesForward()
-{
-    // These optimizations make sense only for integer division
-    if (specialization_ != MIRType_Int32)
-        return;
-
-    if (rhs()->isConstant() && !rhs()->toConstant()->value().isInt32(0))
-        canBeDivideByZero_ = false;
-
-    if (rhs()->isConstant()) {
-        int32_t n = rhs()->toConstant()->value().toInt32();
-        if (n > 0 && !IsPowerOfTwo(n))
-            canBePowerOfTwoDivisor_ = false;
-    }
-}
-
 bool
 MMod::fallible() const
 {
     return !isTruncated() &&
            (isUnsigned() || canBeDivideByZero() || canBeNegativeDividend());
 }
 
 void
@@ -1748,46 +1579,16 @@ MMul::foldsTo(TempAllocator &alloc)
         return this;
 
     if (lhs() == rhs())
         setCanBeNegativeZero(false);
 
     return this;
 }
 
-void
-MMul::analyzeEdgeCasesForward()
-{
-    // Try to remove the check for negative zero
-    // This only makes sense when using the integer multiplication
-    if (specialization() != MIRType_Int32)
-        return;
-
-    // If lhs is > 0, no need for negative zero check.
-    if (lhs()->isConstant()) {
-        const js::Value &val = lhs()->toConstant()->value();
-        if (val.isInt32() && val.toInt32() > 0)
-            setCanBeNegativeZero(false);
-    }
-
-    // If rhs is > 0, likewise.
-    if (rhs()->isConstant()) {
-        const js::Value &val = rhs()->toConstant()->value();
-        if (val.isInt32() && val.toInt32() > 0)
-            setCanBeNegativeZero(false);
-    }
-}
-
-void
-MMul::analyzeEdgeCasesBackward()
-{
-    if (canBeNegativeZero() && !NeedNegativeZeroCheck(this))
-        setCanBeNegativeZero(false);
-}
-
 bool
 MMul::updateForReplacement(MDefinition *ins_)
 {
     MMul *ins = ins_->toMul();
     bool negativeZero = canBeNegativeZero() || ins->canBeNegativeZero();
     setCanBeNegativeZero(negativeZero);
     // Remove the imul annotation when merging imul and normal multiplication.
     if (mode_ == Integer && ins->mode() != Integer)
@@ -2478,23 +2279,16 @@ MDefinition *
 MToInt32::foldsTo(TempAllocator &alloc)
 {
     MDefinition *input = getOperand(0);
     if (input->type() == MIRType_Int32)
         return input;
     return this;
 }
 
-void
-MToInt32::analyzeEdgeCasesBackward()
-{
-    if (!NeedNegativeZeroCheck(this))
-        setCanBeNegativeZero(false);
-}
-
 MDefinition *
 MTruncateToInt32::foldsTo(TempAllocator &alloc)
 {
     MDefinition *input = getOperand(0);
     if (input->type() == MIRType_Int32)
         return input;
 
     if (input->type() == MIRType_Double && input->isConstant()) {
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -477,18 +477,16 @@ class MDefinition : public MNode
     }
 
     virtual HashNumber valueHash() const;
     virtual bool congruentTo(const MDefinition *ins) const {
         return false;
     }
     bool congruentIfOperandsEqual(const MDefinition *ins) const;
     virtual MDefinition *foldsTo(TempAllocator &alloc);
-    virtual void analyzeEdgeCasesForward();
-    virtual void analyzeEdgeCasesBackward();
 
     // When a floating-point value is used by nodes which would prefer to
     // recieve integer inputs, we may be able to help by computing our result
     // into an integer directly.
     //
     // A value can be truncated in 4 differents ways:
     //   1. Ignore Infinities (x / 0 --> 0).
     //   2. Ignore overflow (INT_MIN / -1 == (INT_MAX + 1) --> INT_MIN)
@@ -3799,19 +3797,16 @@ class MToInt32
                          MacroAssembler::IntConversionInputKind conversion =
                              MacroAssembler::IntConversion_Any)
     {
         return new(alloc) MToInt32(def, conversion);
     }
 
     MDefinition *foldsTo(TempAllocator &alloc);
 
-    // this only has backwards information flow.
-    void analyzeEdgeCasesBackward();
-
     bool canBeNegativeZero() const {
         return canBeNegativeZero_;
     }
     void setCanBeNegativeZero(bool negativeZero) {
         canBeNegativeZero_ = negativeZero;
     }
 
     TypePolicy *typePolicy() {
@@ -4946,18 +4941,16 @@ class MMul : public MBinaryArithInstruct
     }
     static MMul *New(TempAllocator &alloc, MDefinition *left, MDefinition *right, MIRType type,
                      Mode mode = Normal)
     {
         return new(alloc) MMul(left, right, type, mode);
     }
 
     MDefinition *foldsTo(TempAllocator &alloc);
-    void analyzeEdgeCasesForward();
-    void analyzeEdgeCasesBackward();
     void collectRangeInfoPreTrunc();
 
     double getIdentity() {
         return 1;
     }
 
     bool congruentTo(const MDefinition *ins) const {
         if (!ins->isMul())
@@ -5043,18 +5036,16 @@ class MDiv : public MBinaryArithInstruct
         MDiv *div = new(alloc) MDiv(left, right, type);
         div->unsigned_ = unsignd;
         if (type == MIRType_Int32)
             div->setTruncateKind(Truncate);
         return div;
     }
 
     MDefinition *foldsTo(TempAllocator &alloc);
-    void analyzeEdgeCasesForward();
-    void analyzeEdgeCasesBackward();
 
     double getIdentity() {
         MOZ_ASSUME_UNREACHABLE("not used");
     }
 
     bool canBeNegativeZero() const {
         return canBeNegativeZero_;
     }
@@ -5161,18 +5152,16 @@ class MMod : public MBinaryArithInstruct
         return canBeDivideByZero_;
     }
 
     bool canBePowerOfTwoDivisor() const {
         JS_ASSERT(specialization_ == MIRType_Int32);
         return canBePowerOfTwoDivisor_;
     }
 
-    void analyzeEdgeCasesForward();
-
     bool isUnsigned() const {
         return unsigned_;
     }
 
     bool writeRecoverData(CompactBufferWriter &writer) const;
     bool canRecoverOnBailout() const {
         return specialization_ < MIRType_Object;
     }
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -151,17 +151,16 @@ UNIFIED_SOURCES += [
     'jit/BaselineIC.cpp',
     'jit/BaselineInspector.cpp',
     'jit/BaselineJIT.cpp',
     'jit/BitSet.cpp',
     'jit/BytecodeAnalysis.cpp',
     'jit/C1Spewer.cpp',
     'jit/CodeGenerator.cpp',
     'jit/CompileWrappers.cpp',
-    'jit/EdgeCaseAnalysis.cpp',
     'jit/EffectiveAddressAnalysis.cpp',
     'jit/ExecutableAllocator.cpp',
     'jit/Ion.cpp',
     'jit/IonAnalysis.cpp',
     'jit/IonBuilder.cpp',
     'jit/IonCaches.cpp',
     'jit/IonFrames.cpp',
     'jit/IonMacroAssembler.cpp',