Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(155)

Side by Side Diff: test/cctest/compiler/test-gap-resolver.cc

Issue 1081373002: [turbofan] cleanup ParallelMove (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/zone-allocator.h ('k') | test/cctest/compiler/test-instruction.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 using namespace v8::internal; 10 using namespace v8::internal;
11 using namespace v8::internal::compiler; 11 using namespace v8::internal::compiler;
12 12
13 // The state of our move interpreter is the mapping of operands to values. Note 13 // The state of our move interpreter is the mapping of operands to values. Note
14 // that the actual values don't really matter, all we care about is equality. 14 // that the actual values don't really matter, all we care about is equality.
15 class InterpreterState { 15 class InterpreterState {
16 public: 16 public:
17 typedef std::vector<MoveOperands> Moves; 17 void ExecuteInParallel(const ParallelMove* moves) {
18
19 void ExecuteInParallel(Moves moves) {
20 InterpreterState copy(*this); 18 InterpreterState copy(*this);
21 for (Moves::iterator it = moves.begin(); it != moves.end(); ++it) { 19 for (const auto m : *moves) {
22 if (!it->IsRedundant()) write(it->destination(), copy.read(it->source())); 20 if (!m->IsRedundant()) write(m->destination(), copy.read(m->source()));
23 } 21 }
24 } 22 }
25 23
26 bool operator==(const InterpreterState& other) const { 24 bool operator==(const InterpreterState& other) const {
27 return values_ == other.values_; 25 return values_ == other.values_;
28 } 26 }
29 27
30 bool operator!=(const InterpreterState& other) const { 28 bool operator!=(const InterpreterState& other) const {
31 return values_ != other.values_; 29 return values_ != other.values_;
32 } 30 }
(...skipping 17 matching lines...) Expand all
50 bool operator==(const Key& other) const { 48 bool operator==(const Key& other) const {
51 return this->is_constant == other.is_constant && 49 return this->is_constant == other.is_constant &&
52 this->kind == other.kind && this->index == other.index; 50 this->kind == other.kind && this->index == other.index;
53 } 51 }
54 }; 52 };
55 53
56 // Internally, the state is a normalized permutation of (kind,index) pairs. 54 // Internally, the state is a normalized permutation of (kind,index) pairs.
57 typedef Key Value; 55 typedef Key Value;
58 typedef std::map<Key, Value> OperandMap; 56 typedef std::map<Key, Value> OperandMap;
59 57
60 Value read(const InstructionOperand* op) const { 58 Value read(const InstructionOperand& op) const {
61 OperandMap::const_iterator it = values_.find(KeyFor(op)); 59 OperandMap::const_iterator it = values_.find(KeyFor(op));
62 return (it == values_.end()) ? ValueFor(op) : it->second; 60 return (it == values_.end()) ? ValueFor(op) : it->second;
63 } 61 }
64 62
65 void write(const InstructionOperand* op, Value v) { 63 void write(const InstructionOperand& op, Value v) {
66 if (v == ValueFor(op)) { 64 if (v == ValueFor(op)) {
67 values_.erase(KeyFor(op)); 65 values_.erase(KeyFor(op));
68 } else { 66 } else {
69 values_[KeyFor(op)] = v; 67 values_[KeyFor(op)] = v;
70 } 68 }
71 } 69 }
72 70
73 static Key KeyFor(const InstructionOperand* op) { 71 static Key KeyFor(const InstructionOperand& op) {
74 bool is_constant = op->IsConstant(); 72 bool is_constant = op.IsConstant();
75 AllocatedOperand::AllocatedKind kind; 73 AllocatedOperand::AllocatedKind kind;
76 int index; 74 int index;
77 if (!is_constant) { 75 if (!is_constant) {
78 index = AllocatedOperand::cast(op)->index(); 76 index = AllocatedOperand::cast(op).index();
79 kind = AllocatedOperand::cast(op)->allocated_kind(); 77 kind = AllocatedOperand::cast(op).allocated_kind();
80 } else { 78 } else {
81 index = ConstantOperand::cast(op)->virtual_register(); 79 index = ConstantOperand::cast(op).virtual_register();
82 kind = AllocatedOperand::REGISTER; 80 kind = AllocatedOperand::REGISTER;
83 } 81 }
84 Key key = {is_constant, kind, index}; 82 Key key = {is_constant, kind, index};
85 return key; 83 return key;
86 } 84 }
87 85
88 static Value ValueFor(const InstructionOperand* op) { return KeyFor(op); } 86 static Value ValueFor(const InstructionOperand& op) { return KeyFor(op); }
89 87
90 static InstructionOperand FromKey(Key key) { 88 static InstructionOperand FromKey(Key key) {
91 if (key.is_constant) { 89 if (key.is_constant) {
92 return ConstantOperand(key.index); 90 return ConstantOperand(key.index);
93 } 91 }
94 return AllocatedOperand(key.kind, key.index); 92 return AllocatedOperand(key.kind, key.index);
95 } 93 }
96 94
97 friend std::ostream& operator<<(std::ostream& os, 95 friend std::ostream& operator<<(std::ostream& os,
98 const InterpreterState& is) { 96 const InterpreterState& is) {
99 for (OperandMap::const_iterator it = is.values_.begin(); 97 for (OperandMap::const_iterator it = is.values_.begin();
100 it != is.values_.end(); ++it) { 98 it != is.values_.end(); ++it) {
101 if (it != is.values_.begin()) os << " "; 99 if (it != is.values_.begin()) os << " ";
102 InstructionOperand source = FromKey(it->first); 100 InstructionOperand source = FromKey(it->first);
103 InstructionOperand destination = FromKey(it->second); 101 InstructionOperand destination = FromKey(it->second);
104 MoveOperands mo(&source, &destination); 102 MoveOperands mo(source, destination);
105 PrintableMoveOperands pmo = {RegisterConfiguration::ArchDefault(), &mo}; 103 PrintableMoveOperands pmo = {RegisterConfiguration::ArchDefault(), &mo};
106 os << pmo; 104 os << pmo;
107 } 105 }
108 return os; 106 return os;
109 } 107 }
110 108
111 OperandMap values_; 109 OperandMap values_;
112 }; 110 };
113 111
114 112
115 // An abstract interpreter for moves, swaps and parallel moves. 113 // An abstract interpreter for moves, swaps and parallel moves.
116 class MoveInterpreter : public GapResolver::Assembler { 114 class MoveInterpreter : public GapResolver::Assembler {
117 public: 115 public:
116 explicit MoveInterpreter(Zone* zone) : zone_(zone) {}
117
118 virtual void AssembleMove(InstructionOperand* source, 118 virtual void AssembleMove(InstructionOperand* source,
119 InstructionOperand* destination) OVERRIDE { 119 InstructionOperand* destination) OVERRIDE {
120 InterpreterState::Moves moves; 120 ParallelMove* moves = new (zone_) ParallelMove(zone_);
121 moves.push_back(MoveOperands(source, destination)); 121 moves->AddMove(*source, *destination);
122 state_.ExecuteInParallel(moves); 122 state_.ExecuteInParallel(moves);
123 } 123 }
124 124
125 virtual void AssembleSwap(InstructionOperand* source, 125 virtual void AssembleSwap(InstructionOperand* source,
126 InstructionOperand* destination) OVERRIDE { 126 InstructionOperand* destination) OVERRIDE {
127 InterpreterState::Moves moves; 127 ParallelMove* moves = new (zone_) ParallelMove(zone_);
128 moves.push_back(MoveOperands(source, destination)); 128 moves->AddMove(*source, *destination);
129 moves.push_back(MoveOperands(destination, source)); 129 moves->AddMove(*destination, *source);
130 state_.ExecuteInParallel(moves); 130 state_.ExecuteInParallel(moves);
131 } 131 }
132 132
133 void AssembleParallelMove(const ParallelMove* pm) { 133 void AssembleParallelMove(const ParallelMove* moves) {
134 InterpreterState::Moves moves(pm->move_operands()->begin(),
135 pm->move_operands()->end());
136 state_.ExecuteInParallel(moves); 134 state_.ExecuteInParallel(moves);
137 } 135 }
138 136
139 InterpreterState state() const { return state_; } 137 InterpreterState state() const { return state_; }
140 138
141 private: 139 private:
140 Zone* const zone_;
142 InterpreterState state_; 141 InterpreterState state_;
143 }; 142 };
144 143
145 144
146 class ParallelMoveCreator : public HandleAndZoneScope { 145 class ParallelMoveCreator : public HandleAndZoneScope {
147 public: 146 public:
148 ParallelMoveCreator() : rng_(CcTest::random_number_generator()) {} 147 ParallelMoveCreator() : rng_(CcTest::random_number_generator()) {}
149 148
150 ParallelMove* Create(int size) { 149 ParallelMove* Create(int size) {
151 ParallelMove* parallel_move = new (main_zone()) ParallelMove(main_zone()); 150 ParallelMove* parallel_move = new (main_zone()) ParallelMove(main_zone());
152 std::set<InstructionOperand*, InstructionOperandComparator> seen; 151 std::set<InstructionOperand> seen;
153 for (int i = 0; i < size; ++i) { 152 for (int i = 0; i < size; ++i) {
154 MoveOperands mo(CreateRandomOperand(true), CreateRandomOperand(false)); 153 MoveOperands mo(CreateRandomOperand(true), CreateRandomOperand(false));
155 if (!mo.IsRedundant() && seen.find(mo.destination()) == seen.end()) { 154 if (!mo.IsRedundant() && seen.find(mo.destination()) == seen.end()) {
156 parallel_move->AddMove(mo.source(), mo.destination(), main_zone()); 155 parallel_move->AddMove(mo.source(), mo.destination());
157 seen.insert(mo.destination()); 156 seen.insert(mo.destination());
158 } 157 }
159 } 158 }
160 return parallel_move; 159 return parallel_move;
161 } 160 }
162 161
163 private: 162 private:
164 struct InstructionOperandComparator { 163 InstructionOperand CreateRandomOperand(bool is_source) {
165 bool operator()(const InstructionOperand* x,
166 const InstructionOperand* y) const {
167 return *x < *y;
168 }
169 };
170
171 InstructionOperand* CreateRandomOperand(bool is_source) {
172 int index = rng_->NextInt(6); 164 int index = rng_->NextInt(6);
173 // destination can't be Constant. 165 // destination can't be Constant.
174 switch (rng_->NextInt(is_source ? 5 : 4)) { 166 switch (rng_->NextInt(is_source ? 5 : 4)) {
175 case 0: 167 case 0:
176 return StackSlotOperand::New(main_zone(), index); 168 return StackSlotOperand(index);
177 case 1: 169 case 1:
178 return DoubleStackSlotOperand::New(main_zone(), index); 170 return DoubleStackSlotOperand(index);
179 case 2: 171 case 2:
180 return RegisterOperand::New(main_zone(), index); 172 return RegisterOperand(index);
181 case 3: 173 case 3:
182 return DoubleRegisterOperand::New(main_zone(), index); 174 return DoubleRegisterOperand(index);
183 case 4: 175 case 4:
184 return ConstantOperand::New(main_zone(), index); 176 return ConstantOperand(index);
185 } 177 }
186 UNREACHABLE(); 178 UNREACHABLE();
187 return NULL; 179 return InstructionOperand();
188 } 180 }
189 181
190 private: 182 private:
191 v8::base::RandomNumberGenerator* rng_; 183 v8::base::RandomNumberGenerator* rng_;
192 }; 184 };
193 185
194 186
195 TEST(FuzzResolver) { 187 TEST(FuzzResolver) {
196 ParallelMoveCreator pmc; 188 ParallelMoveCreator pmc;
197 for (int size = 0; size < 20; ++size) { 189 for (int size = 0; size < 20; ++size) {
198 for (int repeat = 0; repeat < 50; ++repeat) { 190 for (int repeat = 0; repeat < 50; ++repeat) {
199 ParallelMove* pm = pmc.Create(size); 191 ParallelMove* pm = pmc.Create(size);
200 192
201 // Note: The gap resolver modifies the ParallelMove, so interpret first. 193 // Note: The gap resolver modifies the ParallelMove, so interpret first.
202 MoveInterpreter mi1; 194 MoveInterpreter mi1(pmc.main_zone());
203 mi1.AssembleParallelMove(pm); 195 mi1.AssembleParallelMove(pm);
204 196
205 MoveInterpreter mi2; 197 MoveInterpreter mi2(pmc.main_zone());
206 GapResolver resolver(&mi2); 198 GapResolver resolver(&mi2);
207 resolver.Resolve(pm); 199 resolver.Resolve(pm);
208 200
209 CHECK(mi1.state() == mi2.state()); 201 CHECK(mi1.state() == mi2.state());
210 } 202 }
211 } 203 }
212 } 204 }
OLDNEW
« no previous file with comments | « src/zone-allocator.h ('k') | test/cctest/compiler/test-instruction.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698