|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: set ts=8 sts=4 et sw=4 tw=99: |
|
3 * This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifndef jit_ValueNumbering_h |
|
8 #define jit_ValueNumbering_h |
|
9 |
|
10 #include "jit/MIR.h" |
|
11 |
|
12 namespace js { |
|
13 namespace jit { |
|
14 |
|
15 class ValueNumberer |
|
16 { |
|
17 protected: |
|
18 struct ValueHasher |
|
19 { |
|
20 typedef MDefinition * Lookup; |
|
21 typedef MDefinition * Key; |
|
22 static HashNumber hash(const Lookup &ins) { |
|
23 return ins->valueHash(); |
|
24 } |
|
25 |
|
26 static bool match(const Key &k, const Lookup &l) { |
|
27 // If one of the instructions depends on a store, and the |
|
28 // other instruction does not depend on the same store, |
|
29 // the instructions are not congruent. |
|
30 if (k->dependency() != l->dependency()) |
|
31 return false; |
|
32 return k->congruentTo(l); |
|
33 } |
|
34 }; |
|
35 |
|
36 typedef HashMap<MDefinition *, |
|
37 uint32_t, |
|
38 ValueHasher, |
|
39 IonAllocPolicy> ValueMap; |
|
40 |
|
41 struct DominatingValue |
|
42 { |
|
43 MDefinition *def; |
|
44 uint32_t validUntil; |
|
45 }; |
|
46 |
|
47 typedef HashMap<uint32_t, |
|
48 DominatingValue, |
|
49 DefaultHasher<uint32_t>, |
|
50 IonAllocPolicy> InstructionMap; |
|
51 |
|
52 protected: |
|
53 TempAllocator &alloc() const; |
|
54 uint32_t lookupValue(MDefinition *ins); |
|
55 MDefinition *findDominatingDef(InstructionMap &defs, MDefinition *ins, size_t index); |
|
56 |
|
57 MDefinition *simplify(MDefinition *def, bool useValueNumbers); |
|
58 MControlInstruction *simplifyControlInstruction(MControlInstruction *def); |
|
59 bool eliminateRedundancies(); |
|
60 |
|
61 bool computeValueNumbers(); |
|
62 |
|
63 inline bool isMarked(MDefinition *def) { |
|
64 return pessimisticPass_ || def->isInWorklist(); |
|
65 } |
|
66 |
|
67 void markDefinition(MDefinition *def); |
|
68 void unmarkDefinition(MDefinition *def); |
|
69 |
|
70 void markConsumers(MDefinition *def); |
|
71 void markBlock(MBasicBlock *block); |
|
72 void setClass(MDefinition *toSet, MDefinition *representative); |
|
73 |
|
74 public: |
|
75 static MDefinition *findSplit(MDefinition *); |
|
76 void breakClass(MDefinition*); |
|
77 |
|
78 protected: |
|
79 MIRGenerator *mir; |
|
80 MIRGraph &graph_; |
|
81 ValueMap values; |
|
82 bool pessimisticPass_; |
|
83 size_t count_; |
|
84 |
|
85 public: |
|
86 ValueNumberer(MIRGenerator *mir, MIRGraph &graph, bool optimistic); |
|
87 bool analyze(); |
|
88 bool clear(); |
|
89 }; |
|
90 |
|
91 class ValueNumberData : public TempObject { |
|
92 |
|
93 friend void ValueNumberer::breakClass(MDefinition*); |
|
94 friend MDefinition *ValueNumberer::findSplit(MDefinition*); |
|
95 uint32_t number; |
|
96 MDefinition *classNext; |
|
97 MDefinition *classPrev; |
|
98 |
|
99 public: |
|
100 ValueNumberData() : number(0), classNext(nullptr), classPrev(nullptr) {} |
|
101 |
|
102 void setValueNumber(uint32_t number_) { |
|
103 number = number_; |
|
104 } |
|
105 |
|
106 uint32_t valueNumber() { |
|
107 return number; |
|
108 } |
|
109 // Set the class of this to the given representative value. |
|
110 void setClass(MDefinition *thisDef, MDefinition *rep) { |
|
111 JS_ASSERT(thisDef->valueNumberData() == this); |
|
112 // If we are attempting to insert ourself, then nothing needs to be done. |
|
113 // However, if the definition to be inserted already has the correct value number, |
|
114 // it still needs to be inserted, since the value number needs to be updated lazily. |
|
115 // this updating tactic can leave the world in a state where thisDef is not in the |
|
116 // equivalence class of rep, but it has the same value number. Defs in this state |
|
117 // need to be re-processed. |
|
118 if (this == rep->valueNumberData()) |
|
119 return; |
|
120 |
|
121 if (classNext) |
|
122 classNext->valueNumberData()->classPrev = classPrev; |
|
123 if (classPrev) |
|
124 classPrev->valueNumberData()->classNext = classNext; |
|
125 |
|
126 |
|
127 classPrev = rep; |
|
128 classNext = rep->valueNumberData()->classNext; |
|
129 |
|
130 if (rep->valueNumberData()->classNext) |
|
131 rep->valueNumberData()->classNext->valueNumberData()->classPrev = thisDef; |
|
132 rep->valueNumberData()->classNext = thisDef; |
|
133 } |
|
134 }; |
|
135 } // namespace jit |
|
136 } // namespace js |
|
137 |
|
138 #endif /* jit_ValueNumbering_h */ |