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

Side by Side Diff: src/compiler/move-optimizer.cc

Issue 755323011: [turbofan] optimize moves into merges (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix Created 5 years, 10 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/compiler/move-optimizer.h ('k') | src/compiler/register-allocator-verifier.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/move-optimizer.h" 5 #include "src/compiler/move-optimizer.h"
6 6
7 namespace v8 { 7 namespace v8 {
8 namespace internal { 8 namespace internal {
9 namespace compiler { 9 namespace compiler {
10 10
11 namespace { 11 namespace {
12 12
13 typedef std::pair<InstructionOperand, InstructionOperand> MoveKey;
14 typedef ZoneMap<MoveKey, unsigned> MoveMap;
15 typedef ZoneSet<InstructionOperand> OperandSet;
16
17
13 bool GapsCanMoveOver(Instruction* instr) { 18 bool GapsCanMoveOver(Instruction* instr) {
14 DCHECK(!instr->IsGapMoves()); 19 DCHECK(!instr->IsGapMoves());
15 return instr->IsSourcePosition() || instr->IsNop(); 20 return instr->IsSourcePosition() || instr->IsNop();
16 } 21 }
17 22
18 23
19 int FindFirstNonEmptySlot(GapInstruction* gap) { 24 int FindFirstNonEmptySlot(GapInstruction* gap) {
20 int i = GapInstruction::FIRST_INNER_POSITION; 25 int i = GapInstruction::FIRST_INNER_POSITION;
21 for (; i <= GapInstruction::LAST_INNER_POSITION; i++) { 26 for (; i <= GapInstruction::LAST_INNER_POSITION; i++) {
22 auto move = gap->parallel_moves()[i]; 27 auto move = gap->parallel_moves()[i];
(...skipping 18 matching lines...) Expand all
41 code_(code), 46 code_(code),
42 to_finalize_(local_zone), 47 to_finalize_(local_zone),
43 temp_vector_0_(local_zone), 48 temp_vector_0_(local_zone),
44 temp_vector_1_(local_zone) {} 49 temp_vector_1_(local_zone) {}
45 50
46 51
47 void MoveOptimizer::Run() { 52 void MoveOptimizer::Run() {
48 for (auto* block : code()->instruction_blocks()) { 53 for (auto* block : code()->instruction_blocks()) {
49 CompressBlock(block); 54 CompressBlock(block);
50 } 55 }
56 for (auto block : code()->instruction_blocks()) {
57 if (block->PredecessorCount() <= 1) continue;
58 OptimizeMerge(block);
59 }
51 for (auto gap : to_finalize_) { 60 for (auto gap : to_finalize_) {
52 FinalizeMoves(gap); 61 FinalizeMoves(gap);
53 } 62 }
54 } 63 }
55 64
56 65
57 void MoveOptimizer::CompressMoves(MoveOpVector* eliminated, ParallelMove* left, 66 void MoveOptimizer::CompressMoves(MoveOpVector* eliminated, ParallelMove* left,
58 ParallelMove* right) { 67 ParallelMove* right) {
59 DCHECK(eliminated->empty()); 68 DCHECK(eliminated->empty());
60 auto move_ops = right->move_operands(); 69 auto move_ops = right->move_operands();
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 CompressMoves(&temp_vector, pred_moves, left); 132 CompressMoves(&temp_vector, pred_moves, left);
124 // Slide prev_gap down so we always know where to look for it. 133 // Slide prev_gap down so we always know where to look for it.
125 std::swap(prev_gap->parallel_moves()[0], gap->parallel_moves()[0]); 134 std::swap(prev_gap->parallel_moves()[0], gap->parallel_moves()[0]);
126 } 135 }
127 prev_gap = gap; 136 prev_gap = gap;
128 } 137 }
129 if (prev_gap != nullptr) to_finalize_.push_back(prev_gap); 138 if (prev_gap != nullptr) to_finalize_.push_back(prev_gap);
130 } 139 }
131 140
132 141
142 GapInstruction* MoveOptimizer::LastGap(InstructionBlock* block) {
143 int gap_index = block->last_instruction_index() - 1;
144 auto instr = code()->instructions()[gap_index];
145 return GapInstruction::cast(instr);
146 }
147
148
149 void MoveOptimizer::OptimizeMerge(InstructionBlock* block) {
150 DCHECK(block->PredecessorCount() > 1);
151 // Ensure that the last instruction in all incoming blocks don't contain
152 // things that would prevent moving gap moves across them.
153 for (auto pred_index : block->predecessors()) {
154 auto pred = code()->InstructionBlockAt(pred_index);
155 auto last_instr = code()->instructions()[pred->last_instruction_index()];
156 DCHECK(!last_instr->IsGapMoves());
157 if (last_instr->IsSourcePosition()) continue;
158 if (last_instr->IsCall()) return;
159 if (last_instr->TempCount() != 0) return;
160 if (last_instr->OutputCount() != 0) return;
161 for (size_t i = 0; i < last_instr->InputCount(); ++i) {
162 auto op = last_instr->InputAt(i);
163 if (!op->IsConstant() && !op->IsImmediate()) return;
164 }
165 }
166 // TODO(dcarney): pass a ZonePool down for this?
167 MoveMap move_map(local_zone());
168 size_t correct_counts = 0;
169 // Accumulate set of shared moves.
170 for (auto pred_index : block->predecessors()) {
171 auto pred = code()->InstructionBlockAt(pred_index);
172 auto gap = LastGap(pred);
173 if (gap->parallel_moves()[0] == nullptr ||
174 gap->parallel_moves()[0]->move_operands()->is_empty()) {
175 return;
176 }
177 auto move_ops = gap->parallel_moves()[0]->move_operands();
178 for (auto op = move_ops->begin(); op != move_ops->end(); ++op) {
179 if (op->IsRedundant()) continue;
180 auto src = *op->source();
181 auto dst = *op->destination();
182 MoveKey key = {src, dst};
183 auto res = move_map.insert(std::make_pair(key, 1));
184 if (!res.second) {
185 res.first->second++;
186 if (res.first->second == block->PredecessorCount()) {
187 correct_counts++;
188 }
189 }
190 }
191 }
192 if (move_map.empty() || correct_counts != move_map.size()) return;
193 // Find insertion point.
194 GapInstruction* gap = nullptr;
195 for (int i = block->first_instruction_index();
196 i <= block->last_instruction_index(); ++i) {
197 auto instr = code()->instructions()[i];
198 if (instr->IsGapMoves()) {
199 gap = GapInstruction::cast(instr);
200 continue;
201 }
202 if (!GapsCanMoveOver(instr)) break;
203 }
204 DCHECK(gap != nullptr);
205 bool gap_initialized = true;
206 if (gap->parallel_moves()[0] == nullptr ||
207 gap->parallel_moves()[0]->move_operands()->is_empty()) {
208 to_finalize_.push_back(gap);
209 } else {
210 // Will compress after insertion.
211 gap_initialized = false;
212 std::swap(gap->parallel_moves()[0], gap->parallel_moves()[1]);
213 }
214 auto move = gap->GetOrCreateParallelMove(
215 static_cast<GapInstruction::InnerPosition>(0), code_zone());
216 // Delete relevant entries in predecessors and move everything to block.
217 bool first_iteration = true;
218 for (auto pred_index : block->predecessors()) {
219 auto pred = code()->InstructionBlockAt(pred_index);
220 auto gap = LastGap(pred);
brucedawson 2015/04/06 18:05:31 This line of code is worrisome because it shadows
221 auto move_ops = gap->parallel_moves()[0]->move_operands();
222 for (auto op = move_ops->begin(); op != move_ops->end(); ++op) {
223 if (op->IsRedundant()) continue;
224 MoveKey key = {*op->source(), *op->destination()};
225 auto it = move_map.find(key);
226 USE(it);
227 DCHECK(it != move_map.end());
228 if (first_iteration) {
229 move->AddMove(op->source(), op->destination(), code_zone());
230 }
231 op->Eliminate();
232 }
233 first_iteration = false;
234 }
235 // Compress.
236 if (!gap_initialized) {
237 CompressMoves(&temp_vector_0(), gap->parallel_moves()[0],
238 gap->parallel_moves()[1]);
239 }
240 }
241
242
133 // Split multiple loads of the same constant or stack slot off into the second 243 // Split multiple loads of the same constant or stack slot off into the second
134 // slot and keep remaining moves in the first slot. 244 // slot and keep remaining moves in the first slot.
135 void MoveOptimizer::FinalizeMoves(GapInstruction* gap) { 245 void MoveOptimizer::FinalizeMoves(GapInstruction* gap) {
136 auto loads = temp_vector_0(); 246 auto loads = temp_vector_0();
137 DCHECK(loads.empty()); 247 DCHECK(loads.empty());
138 auto new_moves = temp_vector_1(); 248 auto new_moves = temp_vector_1();
139 DCHECK(new_moves.empty()); 249 DCHECK(new_moves.empty());
140 auto move_ops = gap->parallel_moves()[0]->move_operands(); 250 auto move_ops = gap->parallel_moves()[0]->move_operands();
141 for (auto move = move_ops->begin(); move != move_ops->end(); ++move) { 251 for (auto move = move_ops->begin(); move != move_ops->end(); ++move) {
142 if (move->IsRedundant()) { 252 if (move->IsRedundant()) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 std::swap(*new_move, *it); 305 std::swap(*new_move, *it);
196 ++it; 306 ++it;
197 } 307 }
198 DCHECK_EQ(it, slot_1->move_operands()->end()); 308 DCHECK_EQ(it, slot_1->move_operands()->end());
199 new_moves.clear(); 309 new_moves.clear();
200 } 310 }
201 311
202 } // namespace compiler 312 } // namespace compiler
203 } // namespace internal 313 } // namespace internal
204 } // namespace v8 314 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/move-optimizer.h ('k') | src/compiler/register-allocator-verifier.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698