| 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 |