DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (b6d82b1a6b02)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
/* -*- 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_ValueNumbering_h
#define jit_ValueNumbering_h

#include "jit/JitAllocPolicy.h"
#include "js/HashTable.h"

namespace js {
namespace jit {

class MDefinition;
class MBasicBlock;
class MIRGraph;
class MPhi;
class MIRGenerator;
class MResumePoint;

class ValueNumberer {
  // Value numbering data.
  class VisibleValues {
    // Hash policy for ValueSet.
    struct ValueHasher {
      typedef const MDefinition* Lookup;
      typedef MDefinition* Key;
      static HashNumber hash(Lookup ins);
      static bool match(Key k, Lookup l);
      static void rekey(Key& k, Key newKey);
    };

    typedef HashSet<MDefinition*, ValueHasher, JitAllocPolicy> ValueSet;

    ValueSet set_;  // Set of visible values

   public:
    explicit VisibleValues(TempAllocator& alloc);

    typedef ValueSet::Ptr Ptr;
    typedef ValueSet::AddPtr AddPtr;

    Ptr findLeader(const MDefinition* def) const;
    AddPtr findLeaderForAdd(MDefinition* def);
    MOZ_MUST_USE bool add(AddPtr p, MDefinition* def);
    void overwrite(AddPtr p, MDefinition* def);
    void forget(const MDefinition* def);
    void clear();
#ifdef DEBUG
    bool has(const MDefinition* def) const;
#endif
  };

  typedef Vector<MBasicBlock*, 4, JitAllocPolicy> BlockWorklist;
  typedef Vector<MDefinition*, 4, JitAllocPolicy> DefWorklist;

  MIRGenerator* const mir_;
  MIRGraph& graph_;
  VisibleValues values_;           // Numbered values
  DefWorklist deadDefs_;           // Worklist for deleting values
  BlockWorklist remainingBlocks_;  // Blocks remaining with fewer preds
  MDefinition* nextDef_;           // The next definition; don't discard
  size_t totalNumVisited_;         // The number of blocks visited
  bool rerun_;                     // Should we run another GVN iteration?
  bool blocksRemoved_;             // Have any blocks been removed?
  bool updateAliasAnalysis_;       // Do we care about AliasAnalysis?
  bool dependenciesBroken_;        // Have we broken AliasAnalysis?
  bool hasOSRFixups_;              // Have we created any OSR fixup blocks?

  enum UseRemovedOption { DontSetUseRemoved, SetUseRemoved };

  MOZ_MUST_USE bool handleUseReleased(MDefinition* def,
                                      UseRemovedOption useRemovedOption);
  MOZ_MUST_USE bool discardDefsRecursively(MDefinition* def);
  MOZ_MUST_USE bool releaseResumePointOperands(MResumePoint* resume);
  MOZ_MUST_USE bool releaseAndRemovePhiOperands(MPhi* phi);
  MOZ_MUST_USE bool releaseOperands(MDefinition* def);
  MOZ_MUST_USE bool discardDef(MDefinition* def);
  MOZ_MUST_USE bool processDeadDefs();

  MOZ_MUST_USE bool fixupOSROnlyLoop(MBasicBlock* block, MBasicBlock* backedge);
  MOZ_MUST_USE bool removePredecessorAndDoDCE(MBasicBlock* block,
                                              MBasicBlock* pred,
                                              size_t predIndex);
  MOZ_MUST_USE bool removePredecessorAndCleanUp(MBasicBlock* block,
                                                MBasicBlock* pred);

  MDefinition* simplified(MDefinition* def) const;
  MDefinition* leader(MDefinition* def);
  bool hasLeader(const MPhi* phi, const MBasicBlock* phiBlock) const;
  bool loopHasOptimizablePhi(MBasicBlock* header) const;

  MOZ_MUST_USE bool visitDefinition(MDefinition* def);
  MOZ_MUST_USE bool visitControlInstruction(MBasicBlock* block);
  MOZ_MUST_USE bool visitUnreachableBlock(MBasicBlock* block);
  MOZ_MUST_USE bool visitBlock(MBasicBlock* block);
  MOZ_MUST_USE bool visitDominatorTree(MBasicBlock* root);
  MOZ_MUST_USE bool visitGraph();

  MOZ_MUST_USE bool insertOSRFixups();
  MOZ_MUST_USE bool cleanupOSRFixups();

 public:
  ValueNumberer(MIRGenerator* mir, MIRGraph& graph);

  enum UpdateAliasAnalysisFlag { DontUpdateAliasAnalysis, UpdateAliasAnalysis };

  // Optimize the graph, performing expression simplification and
  // canonicalization, eliminating statically fully-redundant expressions,
  // deleting dead instructions, and removing unreachable blocks.
  MOZ_MUST_USE bool run(UpdateAliasAnalysisFlag updateAliasAnalysis);
};

}  // namespace jit
}  // namespace js

#endif /* jit_ValueNumbering_h */