OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/gap-resolver.h" | 5 #include "src/compiler/gap-resolver.h" |
6 | 6 |
7 #include "src/base/utils/random-number-generator.h" | 7 #include "src/base/utils/random-number-generator.h" |
8 #include "test/cctest/cctest.h" | 8 #include "test/cctest/cctest.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 15 matching lines...) Expand all Loading... |
26 return values_ == other.values_; | 26 return values_ == other.values_; |
27 } | 27 } |
28 | 28 |
29 bool operator!=(const InterpreterState& other) const { | 29 bool operator!=(const InterpreterState& other) const { |
30 return values_ != other.values_; | 30 return values_ != other.values_; |
31 } | 31 } |
32 | 32 |
33 private: | 33 private: |
34 struct Key { | 34 struct Key { |
35 bool is_constant; | 35 bool is_constant; |
36 bool is_float; | 36 MachineRepresentation rep; |
37 LocationOperand::LocationKind kind; | 37 LocationOperand::LocationKind kind; |
38 int index; | 38 int index; |
39 | 39 |
40 bool operator<(const Key& other) const { | 40 bool operator<(const Key& other) const { |
41 if (this->is_constant != other.is_constant) { | 41 if (this->is_constant != other.is_constant) { |
42 return this->is_constant; | 42 return this->is_constant; |
43 } | 43 } |
44 if (this->is_float != other.is_float) { | 44 if (this->rep != other.rep) { |
45 return this->is_float; | 45 return static_cast<int>(this->rep) < static_cast<int>(other.rep); |
46 } | 46 } |
47 if (this->kind != other.kind) { | 47 if (this->kind != other.kind) { |
48 return this->kind < other.kind; | 48 return this->kind < other.kind; |
49 } | 49 } |
50 return this->index < other.index; | 50 return this->index < other.index; |
51 } | 51 } |
52 | 52 |
53 bool operator==(const Key& other) const { | 53 bool operator==(const Key& other) const { |
54 return this->is_constant == other.is_constant && | 54 return this->is_constant == other.is_constant && this->rep == other.rep && |
55 this->kind == other.kind && this->index == other.index; | 55 this->kind == other.kind && this->index == other.index; |
56 } | 56 } |
57 }; | 57 }; |
58 | 58 |
59 // Internally, the state is a normalized permutation of (kind,index) pairs. | 59 // Internally, the state is a normalized permutation of (kind,index) pairs. |
60 typedef Key Value; | 60 typedef Key Value; |
61 typedef std::map<Key, Value> OperandMap; | 61 typedef std::map<Key, Value> OperandMap; |
62 | 62 |
63 Value read(const InstructionOperand& op) const { | 63 Value read(const InstructionOperand& op) const { |
64 OperandMap::const_iterator it = values_.find(KeyFor(op)); | 64 OperandMap::const_iterator it = values_.find(KeyFor(op)); |
65 return (it == values_.end()) ? ValueFor(op) : it->second; | 65 return (it == values_.end()) ? ValueFor(op) : it->second; |
66 } | 66 } |
67 | 67 |
68 void write(const InstructionOperand& op, Value v) { | 68 void write(const InstructionOperand& op, Value v) { |
69 if (v == ValueFor(op)) { | 69 if (v == ValueFor(op)) { |
70 values_.erase(KeyFor(op)); | 70 values_.erase(KeyFor(op)); |
71 } else { | 71 } else { |
72 values_[KeyFor(op)] = v; | 72 values_[KeyFor(op)] = v; |
73 } | 73 } |
74 } | 74 } |
75 | 75 |
76 static Key KeyFor(const InstructionOperand& op) { | 76 static Key KeyFor(const InstructionOperand& op) { |
77 bool is_constant = op.IsConstant(); | 77 bool is_constant = op.IsConstant(); |
78 bool is_float = false; | 78 MachineRepresentation rep = |
| 79 v8::internal::compiler::InstructionSequence::DefaultRepresentation(); |
79 LocationOperand::LocationKind kind; | 80 LocationOperand::LocationKind kind; |
80 int index; | 81 int index; |
81 if (!is_constant) { | 82 if (!is_constant) { |
82 if (op.IsRegister()) { | 83 const LocationOperand& loc_op = LocationOperand::cast(op); |
83 index = LocationOperand::cast(op).GetRegister().code(); | 84 if (loc_op.IsAnyRegister()) { |
84 } else if (op.IsFPRegister()) { | 85 if (loc_op.IsFPRegister()) { |
85 index = LocationOperand::cast(op).GetDoubleRegister().code(); | 86 rep = kSimpleFPAliasing ? MachineRepresentation::kFloat64 |
| 87 : loc_op.representation(); |
| 88 } |
| 89 index = loc_op.register_code(); |
86 } else { | 90 } else { |
87 index = LocationOperand::cast(op).index(); | 91 index = loc_op.index(); |
88 } | 92 } |
89 is_float = IsFloatingPoint(LocationOperand::cast(op).representation()); | 93 kind = loc_op.location_kind(); |
90 kind = LocationOperand::cast(op).location_kind(); | |
91 } else { | 94 } else { |
92 index = ConstantOperand::cast(op).virtual_register(); | 95 index = ConstantOperand::cast(op).virtual_register(); |
93 kind = LocationOperand::REGISTER; | 96 kind = LocationOperand::REGISTER; |
94 } | 97 } |
95 Key key = {is_constant, is_float, kind, index}; | 98 Key key = {is_constant, rep, kind, index}; |
96 return key; | 99 return key; |
97 } | 100 } |
98 | 101 |
99 static Value ValueFor(const InstructionOperand& op) { return KeyFor(op); } | 102 static Value ValueFor(const InstructionOperand& op) { return KeyFor(op); } |
100 | 103 |
101 static InstructionOperand FromKey(Key key) { | 104 static InstructionOperand FromKey(Key key) { |
102 if (key.is_constant) { | 105 if (key.is_constant) { |
103 return ConstantOperand(key.index); | 106 return ConstantOperand(key.index); |
104 } | 107 } |
105 return AllocatedOperand( | 108 return AllocatedOperand(key.kind, key.rep, key.index); |
106 key.kind, | |
107 v8::internal::compiler::InstructionSequence::DefaultRepresentation(), | |
108 key.index); | |
109 } | 109 } |
110 | 110 |
111 friend std::ostream& operator<<(std::ostream& os, | 111 friend std::ostream& operator<<(std::ostream& os, |
112 const InterpreterState& is) { | 112 const InterpreterState& is) { |
113 for (OperandMap::const_iterator it = is.values_.begin(); | 113 for (OperandMap::const_iterator it = is.values_.begin(); |
114 it != is.values_.end(); ++it) { | 114 it != is.values_.end(); ++it) { |
115 if (it != is.values_.begin()) os << " "; | 115 if (it != is.values_.begin()) os << " "; |
116 InstructionOperand source = FromKey(it->first); | 116 InstructionOperand source = FromKey(it->second); |
117 InstructionOperand destination = FromKey(it->second); | 117 InstructionOperand destination = FromKey(it->first); |
118 MoveOperands mo(source, destination); | 118 MoveOperands mo(source, destination); |
119 PrintableMoveOperands pmo = {RegisterConfiguration::Turbofan(), &mo}; | 119 PrintableMoveOperands pmo = {RegisterConfiguration::Turbofan(), &mo}; |
120 os << pmo; | 120 os << pmo; |
121 } | 121 } |
122 return os; | 122 return os; |
123 } | 123 } |
124 | 124 |
125 OperandMap values_; | 125 OperandMap values_; |
126 }; | 126 }; |
127 | 127 |
(...skipping 30 matching lines...) Expand all Loading... |
158 }; | 158 }; |
159 | 159 |
160 | 160 |
161 class ParallelMoveCreator : public HandleAndZoneScope { | 161 class ParallelMoveCreator : public HandleAndZoneScope { |
162 public: | 162 public: |
163 ParallelMoveCreator() : rng_(CcTest::random_number_generator()) {} | 163 ParallelMoveCreator() : rng_(CcTest::random_number_generator()) {} |
164 | 164 |
165 ParallelMove* Create(int size) { | 165 ParallelMove* Create(int size) { |
166 ParallelMove* parallel_move = new (main_zone()) ParallelMove(main_zone()); | 166 ParallelMove* parallel_move = new (main_zone()) ParallelMove(main_zone()); |
167 std::set<InstructionOperand, CompareOperandModuloType> seen; | 167 std::set<InstructionOperand, CompareOperandModuloType> seen; |
168 MachineRepresentation rep = RandomRepresentation(); | |
169 for (int i = 0; i < size; ++i) { | 168 for (int i = 0; i < size; ++i) { |
| 169 MachineRepresentation rep = RandomRepresentation(); |
170 MoveOperands mo(CreateRandomOperand(true, rep), | 170 MoveOperands mo(CreateRandomOperand(true, rep), |
171 CreateRandomOperand(false, rep)); | 171 CreateRandomOperand(false, rep)); |
172 if (!mo.IsRedundant() && seen.find(mo.destination()) == seen.end()) { | 172 if (!mo.IsRedundant() && seen.find(mo.destination()) == seen.end()) { |
173 parallel_move->AddMove(mo.source(), mo.destination()); | 173 parallel_move->AddMove(mo.source(), mo.destination()); |
174 seen.insert(mo.destination()); | 174 seen.insert(mo.destination()); |
175 } | 175 } |
176 } | 176 } |
177 return parallel_move; | 177 return parallel_move; |
178 } | 178 } |
179 | 179 |
180 private: | 180 private: |
181 MachineRepresentation RandomRepresentation() { | 181 MachineRepresentation RandomRepresentation() { |
182 int index = rng_->NextInt(5); | 182 int index = rng_->NextInt(5); |
183 switch (index) { | 183 switch (index) { |
184 case 0: | 184 case 0: |
185 return MachineRepresentation::kWord32; | 185 return MachineRepresentation::kWord32; |
186 case 1: | 186 case 1: |
187 return MachineRepresentation::kWord64; | 187 return MachineRepresentation::kWord64; |
188 case 2: | 188 case 2: |
189 return MachineRepresentation::kFloat32; | 189 // TODO(bbudge) Re-enable float operands when GapResolver correctly |
| 190 // handles FP aliasing. |
| 191 return kSimpleFPAliasing ? MachineRepresentation::kFloat32 |
| 192 : MachineRepresentation::kFloat64; |
190 case 3: | 193 case 3: |
191 return MachineRepresentation::kFloat64; | 194 return MachineRepresentation::kFloat64; |
192 case 4: | 195 case 4: |
193 return MachineRepresentation::kTagged; | 196 return MachineRepresentation::kTagged; |
194 } | 197 } |
195 UNREACHABLE(); | 198 UNREACHABLE(); |
196 return MachineRepresentation::kNone; | 199 return MachineRepresentation::kNone; |
197 } | 200 } |
198 | 201 |
199 InstructionOperand CreateRandomOperand(bool is_source, | 202 InstructionOperand CreateRandomOperand(bool is_source, |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 ParallelMove* pm = pmc.Create(size); | 248 ParallelMove* pm = pmc.Create(size); |
246 | 249 |
247 // Note: The gap resolver modifies the ParallelMove, so interpret first. | 250 // Note: The gap resolver modifies the ParallelMove, so interpret first. |
248 MoveInterpreter mi1(pmc.main_zone()); | 251 MoveInterpreter mi1(pmc.main_zone()); |
249 mi1.AssembleParallelMove(pm); | 252 mi1.AssembleParallelMove(pm); |
250 | 253 |
251 MoveInterpreter mi2(pmc.main_zone()); | 254 MoveInterpreter mi2(pmc.main_zone()); |
252 GapResolver resolver(&mi2); | 255 GapResolver resolver(&mi2); |
253 resolver.Resolve(pm); | 256 resolver.Resolve(pm); |
254 | 257 |
255 CHECK(mi1.state() == mi2.state()); | 258 CHECK_EQ(mi1.state(), mi2.state()); |
256 } | 259 } |
257 } | 260 } |
258 } | 261 } |
259 | 262 |
260 } // namespace compiler | 263 } // namespace compiler |
261 } // namespace internal | 264 } // namespace internal |
262 } // namespace v8 | 265 } // namespace v8 |
OLD | NEW |