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

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

Issue 1041163002: [turbofan] smash GapInstruction into Instruction (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: arm compile 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/compiler/move-optimizer.h ('k') | src/compiler/register-allocator.h » ('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; 13 typedef std::pair<InstructionOperand, InstructionOperand> MoveKey;
14 typedef ZoneMap<MoveKey, unsigned> MoveMap; 14 typedef ZoneMap<MoveKey, unsigned> MoveMap;
15 typedef ZoneSet<InstructionOperand> OperandSet; 15 typedef ZoneSet<InstructionOperand> OperandSet;
16 16
17 17
18 bool GapsCanMoveOver(Instruction* instr) { 18 bool GapsCanMoveOver(Instruction* instr) {
19 DCHECK(!instr->IsGapMoves());
20 return instr->IsSourcePosition() || instr->IsNop(); 19 return instr->IsSourcePosition() || instr->IsNop();
21 } 20 }
22 21
23 22
24 int FindFirstNonEmptySlot(GapInstruction* gap) { 23 int FindFirstNonEmptySlot(Instruction* instr) {
25 int i = GapInstruction::FIRST_INNER_POSITION; 24 int i = Instruction::FIRST_GAP_POSITION;
26 for (; i <= GapInstruction::LAST_INNER_POSITION; i++) { 25 for (; i <= Instruction::LAST_GAP_POSITION; i++) {
27 auto move = gap->parallel_moves()[i]; 26 auto move = instr->parallel_moves()[i];
28 if (move == nullptr) continue; 27 if (move == nullptr) continue;
29 auto move_ops = move->move_operands(); 28 auto move_ops = move->move_operands();
30 auto op = move_ops->begin(); 29 auto op = move_ops->begin();
31 for (; op != move_ops->end(); ++op) { 30 for (; op != move_ops->end(); ++op) {
32 if (!op->IsRedundant()) break; 31 if (!op->IsRedundant()) break;
33 op->Eliminate(); 32 op->Eliminate();
34 } 33 }
35 if (op != move_ops->end()) break; // Found non-redundant move. 34 if (op != move_ops->end()) break; // Found non-redundant move.
36 move_ops->Rewind(0); // Clear this redundant move. 35 move_ops->Rewind(0); // Clear this redundant move.
37 } 36 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 // Nuke right. 89 // Nuke right.
91 move_ops->Rewind(0); 90 move_ops->Rewind(0);
92 } 91 }
93 92
94 93
95 // Smash all consecutive moves into the left most move slot and accumulate them 94 // Smash all consecutive moves into the left most move slot and accumulate them
96 // as much as possible across instructions. 95 // as much as possible across instructions.
97 void MoveOptimizer::CompressBlock(InstructionBlock* block) { 96 void MoveOptimizer::CompressBlock(InstructionBlock* block) {
98 auto temp_vector = temp_vector_0(); 97 auto temp_vector = temp_vector_0();
99 DCHECK(temp_vector.empty()); 98 DCHECK(temp_vector.empty());
100 GapInstruction* prev_gap = nullptr; 99 Instruction* prev_instr = nullptr;
101 for (int index = block->code_start(); index < block->code_end(); ++index) { 100 for (int index = block->code_start(); index < block->code_end(); ++index) {
102 auto instr = code()->instructions()[index]; 101 auto instr = code()->instructions()[index];
103 if (!instr->IsGapMoves()) { 102 int i = FindFirstNonEmptySlot(instr);
104 if (GapsCanMoveOver(instr)) continue; 103 if (i <= Instruction::LAST_GAP_POSITION) {
105 if (prev_gap != nullptr) to_finalize_.push_back(prev_gap); 104 // Move the first non-empty gap to position 0.
106 prev_gap = nullptr; 105 std::swap(instr->parallel_moves()[0], instr->parallel_moves()[i]);
107 continue; 106 auto left = instr->parallel_moves()[0];
107 // Compress everything into position 0.
108 for (++i; i <= Instruction::LAST_GAP_POSITION; ++i) {
109 auto move = instr->parallel_moves()[i];
110 if (move == nullptr) continue;
111 CompressMoves(&temp_vector, left, move);
112 }
113 if (prev_instr != nullptr) {
114 // Smash left into prev_instr, killing left.
115 auto pred_moves = prev_instr->parallel_moves()[0];
116 CompressMoves(&temp_vector, pred_moves, left);
117 }
108 } 118 }
109 auto gap = GapInstruction::cast(instr); 119 if (prev_instr != nullptr) {
110 int i = FindFirstNonEmptySlot(gap); 120 // Slide prev_instr down so we always know where to look for it.
111 // Nothing to do here. 121 std::swap(prev_instr->parallel_moves()[0], instr->parallel_moves()[0]);
112 if (i == GapInstruction::LAST_INNER_POSITION + 1) {
113 if (prev_gap != nullptr) {
114 // Slide prev_gap down so we always know where to look for it.
115 std::swap(prev_gap->parallel_moves()[0], gap->parallel_moves()[0]);
116 prev_gap = gap;
117 }
118 continue;
119 } 122 }
120 // Move the first non-empty gap to position 0. 123 prev_instr = instr->parallel_moves()[0] == nullptr ? nullptr : instr;
121 std::swap(gap->parallel_moves()[0], gap->parallel_moves()[i]); 124 if (GapsCanMoveOver(instr)) continue;
122 auto left = gap->parallel_moves()[0]; 125 if (prev_instr != nullptr) {
123 // Compress everything into position 0. 126 to_finalize_.push_back(prev_instr);
124 for (++i; i <= GapInstruction::LAST_INNER_POSITION; ++i) { 127 prev_instr = nullptr;
125 auto move = gap->parallel_moves()[i];
126 if (move == nullptr) continue;
127 CompressMoves(&temp_vector, left, move);
128 } 128 }
129 if (prev_gap != nullptr) {
130 // Smash left into prev_gap, killing left.
131 auto pred_moves = prev_gap->parallel_moves()[0];
132 CompressMoves(&temp_vector, pred_moves, left);
133 // Slide prev_gap down so we always know where to look for it.
134 std::swap(prev_gap->parallel_moves()[0], gap->parallel_moves()[0]);
135 }
136 prev_gap = gap;
137 } 129 }
138 if (prev_gap != nullptr) to_finalize_.push_back(prev_gap); 130 if (prev_instr != nullptr) {
131 to_finalize_.push_back(prev_instr);
132 }
139 } 133 }
140 134
141 135
142 GapInstruction* MoveOptimizer::LastGap(InstructionBlock* block) { 136 Instruction* MoveOptimizer::LastInstruction(InstructionBlock* block) {
143 int gap_index = block->last_instruction_index() - 1; 137 return code()->instructions()[block->last_instruction_index()];
144 auto instr = code()->instructions()[gap_index];
145 return GapInstruction::cast(instr);
146 } 138 }
147 139
148 140
149 void MoveOptimizer::OptimizeMerge(InstructionBlock* block) { 141 void MoveOptimizer::OptimizeMerge(InstructionBlock* block) {
150 DCHECK(block->PredecessorCount() > 1); 142 DCHECK(block->PredecessorCount() > 1);
151 // Ensure that the last instruction in all incoming blocks don't contain 143 // Ensure that the last instruction in all incoming blocks don't contain
152 // things that would prevent moving gap moves across them. 144 // things that would prevent moving gap moves across them.
153 for (auto pred_index : block->predecessors()) { 145 for (auto pred_index : block->predecessors()) {
154 auto pred = code()->InstructionBlockAt(pred_index); 146 auto pred = code()->InstructionBlockAt(pred_index);
155 auto last_instr = code()->instructions()[pred->last_instruction_index()]; 147 auto last_instr = code()->instructions()[pred->last_instruction_index()];
156 DCHECK(!last_instr->IsGapMoves());
157 if (last_instr->IsSourcePosition()) continue; 148 if (last_instr->IsSourcePosition()) continue;
158 if (last_instr->IsCall()) return; 149 if (last_instr->IsCall()) return;
159 if (last_instr->TempCount() != 0) return; 150 if (last_instr->TempCount() != 0) return;
160 if (last_instr->OutputCount() != 0) return; 151 if (last_instr->OutputCount() != 0) return;
161 for (size_t i = 0; i < last_instr->InputCount(); ++i) { 152 for (size_t i = 0; i < last_instr->InputCount(); ++i) {
162 auto op = last_instr->InputAt(i); 153 auto op = last_instr->InputAt(i);
163 if (!op->IsConstant() && !op->IsImmediate()) return; 154 if (!op->IsConstant() && !op->IsImmediate()) return;
164 } 155 }
165 } 156 }
166 // TODO(dcarney): pass a ZonePool down for this? 157 // TODO(dcarney): pass a ZonePool down for this?
167 MoveMap move_map(local_zone()); 158 MoveMap move_map(local_zone());
168 size_t correct_counts = 0; 159 size_t correct_counts = 0;
169 // Accumulate set of shared moves. 160 // Accumulate set of shared moves.
170 for (auto pred_index : block->predecessors()) { 161 for (auto pred_index : block->predecessors()) {
171 auto pred = code()->InstructionBlockAt(pred_index); 162 auto pred = code()->InstructionBlockAt(pred_index);
172 auto gap = LastGap(pred); 163 auto instr = LastInstruction(pred);
173 if (gap->parallel_moves()[0] == nullptr || 164 if (instr->parallel_moves()[0] == nullptr ||
174 gap->parallel_moves()[0]->move_operands()->is_empty()) { 165 instr->parallel_moves()[0]->move_operands()->is_empty()) {
175 return; 166 return;
176 } 167 }
177 auto move_ops = gap->parallel_moves()[0]->move_operands(); 168 auto move_ops = instr->parallel_moves()[0]->move_operands();
178 for (auto op = move_ops->begin(); op != move_ops->end(); ++op) { 169 for (auto op = move_ops->begin(); op != move_ops->end(); ++op) {
179 if (op->IsRedundant()) continue; 170 if (op->IsRedundant()) continue;
180 auto src = *op->source(); 171 auto src = *op->source();
181 auto dst = *op->destination(); 172 auto dst = *op->destination();
182 MoveKey key = {src, dst}; 173 MoveKey key = {src, dst};
183 auto res = move_map.insert(std::make_pair(key, 1)); 174 auto res = move_map.insert(std::make_pair(key, 1));
184 if (!res.second) { 175 if (!res.second) {
185 res.first->second++; 176 res.first->second++;
186 if (res.first->second == block->PredecessorCount()) { 177 if (res.first->second == block->PredecessorCount()) {
187 correct_counts++; 178 correct_counts++;
188 } 179 }
189 } 180 }
190 } 181 }
191 } 182 }
192 if (move_map.empty() || correct_counts != move_map.size()) return; 183 if (move_map.empty() || correct_counts != move_map.size()) return;
193 // Find insertion point. 184 // Find insertion point.
194 GapInstruction* gap = nullptr; 185 Instruction* instr = nullptr;
195 for (int i = block->first_instruction_index(); 186 for (int i = block->first_instruction_index();
196 i <= block->last_instruction_index(); ++i) { 187 i <= block->last_instruction_index(); ++i) {
197 auto instr = code()->instructions()[i]; 188 instr = code()->instructions()[i];
198 if (instr->IsGapMoves()) { 189 if (!GapsCanMoveOver(instr) || !instr->AreMovesRedundant()) break;
199 gap = GapInstruction::cast(instr);
200 continue;
201 }
202 if (!GapsCanMoveOver(instr)) break;
203 } 190 }
204 DCHECK(gap != nullptr); 191 DCHECK(instr != nullptr);
205 bool gap_initialized = true; 192 bool gap_initialized = true;
206 if (gap->parallel_moves()[0] == nullptr || 193 if (instr->parallel_moves()[0] == nullptr ||
207 gap->parallel_moves()[0]->move_operands()->is_empty()) { 194 instr->parallel_moves()[0]->move_operands()->is_empty()) {
208 to_finalize_.push_back(gap); 195 to_finalize_.push_back(instr);
209 } else { 196 } else {
210 // Will compress after insertion. 197 // Will compress after insertion.
211 gap_initialized = false; 198 gap_initialized = false;
212 std::swap(gap->parallel_moves()[0], gap->parallel_moves()[1]); 199 std::swap(instr->parallel_moves()[0], instr->parallel_moves()[1]);
213 } 200 }
214 auto move = gap->GetOrCreateParallelMove( 201 auto move = instr->GetOrCreateParallelMove(
215 static_cast<GapInstruction::InnerPosition>(0), code_zone()); 202 static_cast<Instruction::GapPosition>(0), code_zone());
216 // Delete relevant entries in predecessors and move everything to block. 203 // Delete relevant entries in predecessors and move everything to block.
217 bool first_iteration = true; 204 bool first_iteration = true;
218 for (auto pred_index : block->predecessors()) { 205 for (auto pred_index : block->predecessors()) {
219 auto pred = code()->InstructionBlockAt(pred_index); 206 auto pred = code()->InstructionBlockAt(pred_index);
220 auto gap = LastGap(pred); 207 auto instr = LastInstruction(pred);
221 auto move_ops = gap->parallel_moves()[0]->move_operands(); 208 auto move_ops = instr->parallel_moves()[0]->move_operands();
222 for (auto op = move_ops->begin(); op != move_ops->end(); ++op) { 209 for (auto op = move_ops->begin(); op != move_ops->end(); ++op) {
223 if (op->IsRedundant()) continue; 210 if (op->IsRedundant()) continue;
224 MoveKey key = {*op->source(), *op->destination()}; 211 MoveKey key = {*op->source(), *op->destination()};
225 auto it = move_map.find(key); 212 auto it = move_map.find(key);
226 USE(it); 213 USE(it);
227 DCHECK(it != move_map.end()); 214 DCHECK(it != move_map.end());
228 if (first_iteration) { 215 if (first_iteration) {
229 move->AddMove(op->source(), op->destination(), code_zone()); 216 move->AddMove(op->source(), op->destination(), code_zone());
230 } 217 }
231 op->Eliminate(); 218 op->Eliminate();
232 } 219 }
233 first_iteration = false; 220 first_iteration = false;
234 } 221 }
235 // Compress. 222 // Compress.
236 if (!gap_initialized) { 223 if (!gap_initialized) {
237 CompressMoves(&temp_vector_0(), gap->parallel_moves()[0], 224 CompressMoves(&temp_vector_0(), instr->parallel_moves()[0],
238 gap->parallel_moves()[1]); 225 instr->parallel_moves()[1]);
239 } 226 }
240 } 227 }
241 228
242 229
243 // Split multiple loads of the same constant or stack slot off into the second 230 // Split multiple loads of the same constant or stack slot off into the second
244 // slot and keep remaining moves in the first slot. 231 // slot and keep remaining moves in the first slot.
245 void MoveOptimizer::FinalizeMoves(GapInstruction* gap) { 232 void MoveOptimizer::FinalizeMoves(Instruction* instr) {
246 auto loads = temp_vector_0(); 233 auto loads = temp_vector_0();
247 DCHECK(loads.empty()); 234 DCHECK(loads.empty());
248 auto new_moves = temp_vector_1(); 235 auto new_moves = temp_vector_1();
249 DCHECK(new_moves.empty()); 236 DCHECK(new_moves.empty());
250 auto move_ops = gap->parallel_moves()[0]->move_operands(); 237 auto move_ops = instr->parallel_moves()[0]->move_operands();
251 for (auto move = move_ops->begin(); move != move_ops->end(); ++move) { 238 for (auto move = move_ops->begin(); move != move_ops->end(); ++move) {
252 if (move->IsRedundant()) { 239 if (move->IsRedundant()) {
253 move->Eliminate(); 240 move->Eliminate();
254 continue; 241 continue;
255 } 242 }
256 if (!(move->source()->IsConstant() || move->source()->IsStackSlot() || 243 if (!(move->source()->IsConstant() || move->source()->IsStackSlot() ||
257 move->source()->IsDoubleStackSlot())) 244 move->source()->IsDoubleStackSlot()))
258 continue; 245 continue;
259 // Search for existing move to this slot. 246 // Search for existing move to this slot.
260 MoveOperands* found = nullptr; 247 MoveOperands* found = nullptr;
(...skipping 26 matching lines...) Expand all
287 found->destination()->ConvertTo(dest->kind(), dest->index()); 274 found->destination()->ConvertTo(dest->kind(), dest->index());
288 move->set_destination(next_dest); 275 move->set_destination(next_dest);
289 } 276 }
290 // move from load destination. 277 // move from load destination.
291 move->set_source(found->destination()); 278 move->set_source(found->destination());
292 new_moves.push_back(move); 279 new_moves.push_back(move);
293 } 280 }
294 loads.clear(); 281 loads.clear();
295 if (new_moves.empty()) return; 282 if (new_moves.empty()) return;
296 // Insert all new moves into slot 1. 283 // Insert all new moves into slot 1.
297 auto slot_1 = gap->GetOrCreateParallelMove( 284 auto slot_1 = instr->GetOrCreateParallelMove(
298 static_cast<GapInstruction::InnerPosition>(1), code_zone()); 285 static_cast<Instruction::GapPosition>(1), code_zone());
299 DCHECK(slot_1->move_operands()->is_empty()); 286 DCHECK(slot_1->move_operands()->is_empty());
300 slot_1->move_operands()->AddBlock(MoveOperands(nullptr, nullptr), 287 slot_1->move_operands()->AddBlock(MoveOperands(nullptr, nullptr),
301 static_cast<int>(new_moves.size()), 288 static_cast<int>(new_moves.size()),
302 code_zone()); 289 code_zone());
303 auto it = slot_1->move_operands()->begin(); 290 auto it = slot_1->move_operands()->begin();
304 for (auto new_move : new_moves) { 291 for (auto new_move : new_moves) {
305 std::swap(*new_move, *it); 292 std::swap(*new_move, *it);
306 ++it; 293 ++it;
307 } 294 }
308 DCHECK_EQ(it, slot_1->move_operands()->end()); 295 DCHECK_EQ(it, slot_1->move_operands()->end());
309 new_moves.clear(); 296 new_moves.clear();
310 } 297 }
311 298
312 } // namespace compiler 299 } // namespace compiler
313 } // namespace internal 300 } // namespace internal
314 } // namespace v8 301 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/move-optimizer.h ('k') | src/compiler/register-allocator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698