diff -r 000000000000 -r 6474c204b198 js/src/jit/ValueNumbering.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/js/src/jit/ValueNumbering.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,138 @@ +/* -*- 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_ValueNumbering_h +#define jit_ValueNumbering_h + +#include "jit/MIR.h" + +namespace js { +namespace jit { + +class ValueNumberer +{ + protected: + struct ValueHasher + { + typedef MDefinition * Lookup; + typedef MDefinition * Key; + static HashNumber hash(const Lookup &ins) { + return ins->valueHash(); + } + + static bool match(const Key &k, const Lookup &l) { + // If one of the instructions depends on a store, and the + // other instruction does not depend on the same store, + // the instructions are not congruent. + if (k->dependency() != l->dependency()) + return false; + return k->congruentTo(l); + } + }; + + typedef HashMap ValueMap; + + struct DominatingValue + { + MDefinition *def; + uint32_t validUntil; + }; + + typedef HashMap, + IonAllocPolicy> InstructionMap; + + protected: + TempAllocator &alloc() const; + uint32_t lookupValue(MDefinition *ins); + MDefinition *findDominatingDef(InstructionMap &defs, MDefinition *ins, size_t index); + + MDefinition *simplify(MDefinition *def, bool useValueNumbers); + MControlInstruction *simplifyControlInstruction(MControlInstruction *def); + bool eliminateRedundancies(); + + bool computeValueNumbers(); + + inline bool isMarked(MDefinition *def) { + return pessimisticPass_ || def->isInWorklist(); + } + + void markDefinition(MDefinition *def); + void unmarkDefinition(MDefinition *def); + + void markConsumers(MDefinition *def); + void markBlock(MBasicBlock *block); + void setClass(MDefinition *toSet, MDefinition *representative); + + public: + static MDefinition *findSplit(MDefinition *); + void breakClass(MDefinition*); + + protected: + MIRGenerator *mir; + MIRGraph &graph_; + ValueMap values; + bool pessimisticPass_; + size_t count_; + + public: + ValueNumberer(MIRGenerator *mir, MIRGraph &graph, bool optimistic); + bool analyze(); + bool clear(); +}; + +class ValueNumberData : public TempObject { + + friend void ValueNumberer::breakClass(MDefinition*); + friend MDefinition *ValueNumberer::findSplit(MDefinition*); + uint32_t number; + MDefinition *classNext; + MDefinition *classPrev; + + public: + ValueNumberData() : number(0), classNext(nullptr), classPrev(nullptr) {} + + void setValueNumber(uint32_t number_) { + number = number_; + } + + uint32_t valueNumber() { + return number; + } + // Set the class of this to the given representative value. + void setClass(MDefinition *thisDef, MDefinition *rep) { + JS_ASSERT(thisDef->valueNumberData() == this); + // If we are attempting to insert ourself, then nothing needs to be done. + // However, if the definition to be inserted already has the correct value number, + // it still needs to be inserted, since the value number needs to be updated lazily. + // this updating tactic can leave the world in a state where thisDef is not in the + // equivalence class of rep, but it has the same value number. Defs in this state + // need to be re-processed. + if (this == rep->valueNumberData()) + return; + + if (classNext) + classNext->valueNumberData()->classPrev = classPrev; + if (classPrev) + classPrev->valueNumberData()->classNext = classNext; + + + classPrev = rep; + classNext = rep->valueNumberData()->classNext; + + if (rep->valueNumberData()->classNext) + rep->valueNumberData()->classNext->valueNumberData()->classPrev = thisDef; + rep->valueNumberData()->classNext = thisDef; + } +}; +} // namespace jit +} // namespace js + +#endif /* jit_ValueNumbering_h */