js/src/jit/IonAnalysis.h
author Tooru Fujisawa <arai_a@mac.com>
Sat, 01 Dec 2018 04:52:05 +0900
changeset 505471 66eb1f485c1a3ea81372758bc92292c9428b17cd
parent 505464 e4712449ba4303cef134ba0b3f1bea13fbd50c4a
child 541980 fd21aed8462aa60060c20059286044a846b2bbe1
permissions -rw-r--r--
Bug 1511393 - Use c-basic-offset: 2 in Emacs mode line for C/C++ code. r=nbp

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: set ts=8 sts=2 et sw=2 tw=80:
 * 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_IonAnalysis_h
#define jit_IonAnalysis_h

// This file declares various analysis passes that operate on MIR.

#include "jit/JitAllocPolicy.h"

namespace js {
namespace jit {

class MBasicBlock;
class MCompare;
class MDefinition;
class MIRGenerator;
class MIRGraph;
class MTest;

MOZ_MUST_USE bool PruneUnusedBranches(MIRGenerator* mir, MIRGraph& graph);

MOZ_MUST_USE bool FoldTests(MIRGraph& graph);

MOZ_MUST_USE bool FoldEmptyBlocks(MIRGraph& graph);

MOZ_MUST_USE bool SplitCriticalEdges(MIRGraph& graph);

bool IsUint32Type(const MDefinition* def);

enum Observability { ConservativeObservability, AggressiveObservability };

MOZ_MUST_USE bool EliminatePhis(MIRGenerator* mir, MIRGraph& graph,
                                Observability observe);

size_t MarkLoopBlocks(MIRGraph& graph, MBasicBlock* header, bool* canOsr);

void UnmarkLoopBlocks(MIRGraph& graph, MBasicBlock* header);

MOZ_MUST_USE bool MakeLoopsContiguous(MIRGraph& graph);

MOZ_MUST_USE bool EliminateDeadResumePointOperands(MIRGenerator* mir,
                                                   MIRGraph& graph);

MOZ_MUST_USE bool EliminateDeadCode(MIRGenerator* mir, MIRGraph& graph);

MOZ_MUST_USE bool ApplyTypeInformation(MIRGenerator* mir, MIRGraph& graph);

MOZ_MUST_USE bool MakeMRegExpHoistable(MIRGenerator* mir, MIRGraph& graph);

void RenumberBlocks(MIRGraph& graph);

MOZ_MUST_USE bool AccountForCFGChanges(MIRGenerator* mir, MIRGraph& graph,
                                       bool updateAliasAnalysis,
                                       bool underValueNumberer = false);

MOZ_MUST_USE bool RemoveUnmarkedBlocks(MIRGenerator* mir, MIRGraph& graph,
                                       uint32_t numMarkedBlocks);

MOZ_MUST_USE bool CreateMIRRootList(IonBuilder& builder);

void ClearDominatorTree(MIRGraph& graph);

MOZ_MUST_USE bool BuildDominatorTree(MIRGraph& graph);

MOZ_MUST_USE bool BuildPhiReverseMapping(MIRGraph& graph);

void AssertBasicGraphCoherency(MIRGraph& graph, bool force = false);

void AssertGraphCoherency(MIRGraph& graph, bool force = false);

void AssertExtendedGraphCoherency(MIRGraph& graph,
                                  bool underValueNumberer = false,
                                  bool force = false);

MOZ_MUST_USE bool EliminateRedundantChecks(MIRGraph& graph);

MOZ_MUST_USE bool AddKeepAliveInstructions(MIRGraph& graph);

// Simple linear sum of the form 'n' or 'x + n'.
struct SimpleLinearSum {
  MDefinition* term;
  int32_t constant;

  SimpleLinearSum(MDefinition* term, int32_t constant)
      : term(term), constant(constant) {}
};

// Math done in a Linear sum can either be in a modulo space, in which case
// overflow are wrapped around, or they can be computed in the integer-space in
// which case we have to check that no overflow can happen when summing
// constants.
//
// When the caller ignores which space it is, the definition would be used to
// deduce it.
enum class MathSpace { Modulo, Infinite, Unknown };

SimpleLinearSum ExtractLinearSum(MDefinition* ins,
                                 MathSpace space = MathSpace::Unknown);

MOZ_MUST_USE bool ExtractLinearInequality(MTest* test,
                                          BranchDirection direction,
                                          SimpleLinearSum* plhs,
                                          MDefinition** prhs, bool* plessEqual);

struct LinearTerm {
  MDefinition* term;
  int32_t scale;

  LinearTerm(MDefinition* term, int32_t scale) : term(term), scale(scale) {}
};

// General linear sum of the form 'x1*n1 + x2*n2 + ... + n'
class LinearSum {
 public:
  explicit LinearSum(TempAllocator& alloc) : terms_(alloc), constant_(0) {}

  LinearSum(const LinearSum& other)
      : terms_(other.terms_.allocPolicy()), constant_(other.constant_) {
    AutoEnterOOMUnsafeRegion oomUnsafe;
    if (!terms_.appendAll(other.terms_)) {
      oomUnsafe.crash("LinearSum::LinearSum");
    }
  }

  // These return false on an integer overflow, and afterwards the sum must
  // not be used.
  MOZ_MUST_USE bool multiply(int32_t scale);
  MOZ_MUST_USE bool add(const LinearSum& other, int32_t scale = 1);
  MOZ_MUST_USE bool add(SimpleLinearSum other, int32_t scale = 1);
  MOZ_MUST_USE bool add(MDefinition* term, int32_t scale);
  MOZ_MUST_USE bool add(int32_t constant);

  // Unlike the above function, on failure this leaves the sum unchanged and
  // it can still be used.
  MOZ_MUST_USE bool divide(uint32_t scale);

  int32_t constant() const { return constant_; }
  size_t numTerms() const { return terms_.length(); }
  LinearTerm term(size_t i) const { return terms_[i]; }
  void replaceTerm(size_t i, MDefinition* def) { terms_[i].term = def; }

  void dump(GenericPrinter& out) const;
  void dump() const;

 private:
  Vector<LinearTerm, 2, JitAllocPolicy> terms_;
  int32_t constant_;
};

// Convert all components of a linear sum (except, optionally, the constant)
// and add any new instructions to the end of block.
MDefinition* ConvertLinearSum(TempAllocator& alloc, MBasicBlock* block,
                              const LinearSum& sum,
                              bool convertConstant = false);

// Convert the test 'sum >= 0' to a comparison, adding any necessary
// instructions to the end of block.
MCompare* ConvertLinearInequality(TempAllocator& alloc, MBasicBlock* block,
                                  const LinearSum& sum);

MOZ_MUST_USE bool AnalyzeNewScriptDefiniteProperties(
    JSContext* cx, HandleFunction fun, ObjectGroup* group,
    HandlePlainObject baseobj,
    Vector<TypeNewScriptInitializer>* initializerList);

MOZ_MUST_USE bool AnalyzeArgumentsUsage(JSContext* cx, JSScript* script);

bool DeadIfUnused(const MDefinition* def);

bool IsDiscardable(const MDefinition* def);

void DumpMIRExpressions(MIRGraph& graph);

}  // namespace jit
}  // namespace js

#endif /* jit_IonAnalysis_h */