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

Side by Side Diff: src/compiler/register-allocator.h

Issue 671043004: [turbofan] cleanup register allocator interface a little (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 1 month 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 | Annotate | Revision Log
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 #ifndef V8_REGISTER_ALLOCATOR_H_ 5 #ifndef V8_REGISTER_ALLOCATOR_H_
6 #define V8_REGISTER_ALLOCATOR_H_ 6 #define V8_REGISTER_ALLOCATOR_H_
7 7
8 #include "src/allocation.h" 8 #include "src/allocation.h"
9 #include "src/compiler/instruction.h" 9 #include "src/compiler/instruction.h"
10 #include "src/compiler/zone-pool.h"
11 #include "src/macro-assembler.h" 10 #include "src/macro-assembler.h"
12 #include "src/zone.h" 11 #include "src/zone.h"
13 12
14 namespace v8 { 13 namespace v8 {
15 namespace internal { 14 namespace internal {
16 15
17 // Forward declarations. 16 // Forward declarations.
18 class BitVector; 17 class BitVector;
19 class InstructionOperand; 18 class InstructionOperand;
20 class UnallocatedOperand; 19 class UnallocatedOperand;
21 class ParallelMove; 20 class ParallelMove;
22 class PointerMap; 21 class PointerMap;
23 22
24 namespace compiler { 23 namespace compiler {
25 24
26 class PipelineStatistics; 25 class PipelineStatistics;
27 26
28 enum RegisterKind { 27 enum RegisterKind {
29 UNALLOCATED_REGISTERS, 28 UNALLOCATED_REGISTERS,
30 GENERAL_REGISTERS, 29 GENERAL_REGISTERS,
31 DOUBLE_REGISTERS 30 DOUBLE_REGISTERS
32 }; 31 };
33 32
34 33
35 // This class represents a single point of a InstructionOperand's lifetime. For 34 // This class represents a single point of a InstructionOperand's lifetime. For
36 // each instruction there are exactly two lifetime positions: the beginning and 35 // each instruction there are exactly two lifetime positions: the beginning and
37 // the end of the instruction. Lifetime positions for different instructions are 36 // the end of the instruction. Lifetime positions for different instructions are
38 // disjoint. 37 // disjoint.
39 class LifetimePosition { 38 class LifetimePosition FINAL {
40 public: 39 public:
41 // Return the lifetime position that corresponds to the beginning of 40 // Return the lifetime position that corresponds to the beginning of
42 // the instruction with the given index. 41 // the instruction with the given index.
43 static LifetimePosition FromInstructionIndex(int index) { 42 static LifetimePosition FromInstructionIndex(int index) {
44 return LifetimePosition(index * kStep); 43 return LifetimePosition(index * kStep);
45 } 44 }
46 45
47 // Returns a numeric representation of this lifetime position. 46 // Returns a numeric representation of this lifetime position.
48 int Value() const { return value_; } 47 int Value() const { return value_; }
49 48
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 // Code relies on kStep being a power of two. 107 // Code relies on kStep being a power of two.
109 STATIC_ASSERT(IS_POWER_OF_TWO(kStep)); 108 STATIC_ASSERT(IS_POWER_OF_TWO(kStep));
110 109
111 explicit LifetimePosition(int value) : value_(value) {} 110 explicit LifetimePosition(int value) : value_(value) {}
112 111
113 int value_; 112 int value_;
114 }; 113 };
115 114
116 115
117 // Representation of the non-empty interval [start,end[. 116 // Representation of the non-empty interval [start,end[.
118 class UseInterval : public ZoneObject { 117 class UseInterval FINAL : public ZoneObject {
119 public: 118 public:
120 UseInterval(LifetimePosition start, LifetimePosition end) 119 UseInterval(LifetimePosition start, LifetimePosition end)
121 : start_(start), end_(end), next_(NULL) { 120 : start_(start), end_(end), next_(NULL) {
122 DCHECK(start.Value() < end.Value()); 121 DCHECK(start.Value() < end.Value());
123 } 122 }
124 123
125 LifetimePosition start() const { return start_; } 124 LifetimePosition start() const { return start_; }
126 LifetimePosition end() const { return end_; } 125 LifetimePosition end() const { return end_; }
127 UseInterval* next() const { return next_; } 126 UseInterval* next() const { return next_; }
128 127
(...skipping 12 matching lines...) Expand all
141 bool Contains(LifetimePosition point) const { 140 bool Contains(LifetimePosition point) const {
142 return start_.Value() <= point.Value() && point.Value() < end_.Value(); 141 return start_.Value() <= point.Value() && point.Value() < end_.Value();
143 } 142 }
144 143
145 void set_start(LifetimePosition start) { start_ = start; } 144 void set_start(LifetimePosition start) { start_ = start; }
146 void set_next(UseInterval* next) { next_ = next; } 145 void set_next(UseInterval* next) { next_ = next; }
147 146
148 LifetimePosition start_; 147 LifetimePosition start_;
149 LifetimePosition end_; 148 LifetimePosition end_;
150 UseInterval* next_; 149 UseInterval* next_;
150
151 private:
152 DISALLOW_COPY_AND_ASSIGN(UseInterval);
151 }; 153 };
152 154
155
153 // Representation of a use position. 156 // Representation of a use position.
154 class UsePosition : public ZoneObject { 157 class UsePosition FINAL : public ZoneObject {
155 public: 158 public:
156 UsePosition(LifetimePosition pos, InstructionOperand* operand, 159 UsePosition(LifetimePosition pos, InstructionOperand* operand,
157 InstructionOperand* hint); 160 InstructionOperand* hint);
158 161
159 InstructionOperand* operand() const { return operand_; } 162 InstructionOperand* operand() const { return operand_; }
160 bool HasOperand() const { return operand_ != NULL; } 163 bool HasOperand() const { return operand_ != NULL; }
161 164
162 InstructionOperand* hint() const { return hint_; } 165 InstructionOperand* hint() const { return hint_; }
163 bool HasHint() const; 166 bool HasHint() const;
164 bool RequiresRegister() const; 167 bool RequiresRegister() const;
165 bool RegisterIsBeneficial() const; 168 bool RegisterIsBeneficial() const;
166 169
167 LifetimePosition pos() const { return pos_; } 170 LifetimePosition pos() const { return pos_; }
168 UsePosition* next() const { return next_; } 171 UsePosition* next() const { return next_; }
169 172
170 void set_next(UsePosition* next) { next_ = next; } 173 void set_next(UsePosition* next) { next_ = next; }
171 174
172 InstructionOperand* const operand_; 175 InstructionOperand* const operand_;
173 InstructionOperand* const hint_; 176 InstructionOperand* const hint_;
174 LifetimePosition const pos_; 177 LifetimePosition const pos_;
175 UsePosition* next_; 178 UsePosition* next_;
176 bool requires_reg_; 179 bool requires_reg_ : 1;
Jarin 2014/10/29 12:16:51 I do not think the bit field makes any difference.
177 bool register_beneficial_; 180 bool register_beneficial_ : 1;
181
182 private:
183 DISALLOW_COPY_AND_ASSIGN(UsePosition);
178 }; 184 };
179 185
186
180 // Representation of SSA values' live ranges as a collection of (continuous) 187 // Representation of SSA values' live ranges as a collection of (continuous)
181 // intervals over the instruction ordering. 188 // intervals over the instruction ordering.
182 class LiveRange : public ZoneObject { 189 class LiveRange FINAL : public ZoneObject {
183 public: 190 public:
184 static const int kInvalidAssignment = 0x7fffffff; 191 static const int kInvalidAssignment = 0x7fffffff;
185 192
186 LiveRange(int id, Zone* zone); 193 LiveRange(int id, Zone* zone);
187 194
188 UseInterval* first_interval() const { return first_interval_; } 195 UseInterval* first_interval() const { return first_interval_; }
189 UsePosition* first_pos() const { return first_pos_; } 196 UsePosition* first_pos() const { return first_pos_; }
190 LiveRange* parent() const { return parent_; } 197 LiveRange* parent() const { return parent_; }
191 LiveRange* TopLevel() { return (parent_ == NULL) ? this : parent_; } 198 LiveRange* TopLevel() { return (parent_ == NULL) ? this : parent_; }
192 LiveRange* next() const { return next_; } 199 LiveRange* next() const { return next_; }
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 void Verify() const; 296 void Verify() const;
290 #endif 297 #endif
291 298
292 private: 299 private:
293 void ConvertOperands(Zone* zone); 300 void ConvertOperands(Zone* zone);
294 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const; 301 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const;
295 void AdvanceLastProcessedMarker(UseInterval* to_start_of, 302 void AdvanceLastProcessedMarker(UseInterval* to_start_of,
296 LifetimePosition but_not_past) const; 303 LifetimePosition but_not_past) const;
297 304
298 int id_; 305 int id_;
299 bool spilled_;
300 bool is_phi_;
301 bool is_non_loop_phi_;
302 RegisterKind kind_;
303 int assigned_register_; 306 int assigned_register_;
307 bool spilled_ : 1;
308 bool is_phi_ : 1;
309 bool is_non_loop_phi_ : 1;
310 RegisterKind kind_ : 2;
Jarin 2014/10/29 12:16:51 Does the bitfield make any difference? If yes, th
304 UseInterval* last_interval_; 311 UseInterval* last_interval_;
305 UseInterval* first_interval_; 312 UseInterval* first_interval_;
306 UsePosition* first_pos_; 313 UsePosition* first_pos_;
307 LiveRange* parent_; 314 LiveRange* parent_;
308 LiveRange* next_; 315 LiveRange* next_;
309 // This is used as a cache, it doesn't affect correctness. 316 // This is used as a cache, it doesn't affect correctness.
310 mutable UseInterval* current_interval_; 317 mutable UseInterval* current_interval_;
311 UsePosition* last_processed_use_; 318 UsePosition* last_processed_use_;
312 // This is used as a cache, it's invalid outside of BuildLiveRanges. 319 // This is used as a cache, it's invalid outside of BuildLiveRanges.
313 InstructionOperand* current_hint_operand_; 320 InstructionOperand* current_hint_operand_;
314 InstructionOperand* spill_operand_; 321 InstructionOperand* spill_operand_;
315 int spill_start_index_; 322 int spill_start_index_;
316 323
317 friend class RegisterAllocator; // Assigns to kind_. 324 friend class RegisterAllocator; // Assigns to kind_.
325
326 DISALLOW_COPY_AND_ASSIGN(LiveRange);
318 }; 327 };
319 328
320 329
321 class RegisterAllocator BASE_EMBEDDED { 330 class RegisterAllocator BASE_EMBEDDED {
322 public: 331 public:
323 // TODO(dcarney): remove info
324 explicit RegisterAllocator(Zone* local_zone, Frame* frame, 332 explicit RegisterAllocator(Zone* local_zone, Frame* frame,
325 CompilationInfo* info, InstructionSequence* code); 333 InstructionSequence* code,
326 334 const char* debug_name = nullptr);
327 static void TraceAlloc(const char* msg, ...);
328
329 // Checks whether the value of a given virtual register is a reference.
330 // TODO(titzer): rename this to IsReference.
331 bool HasTaggedValue(int virtual_register) const;
332
333 // Returns the register kind required by the given virtual register.
334 RegisterKind RequiredRegisterKind(int virtual_register) const;
335 335
336 bool Allocate(PipelineStatistics* stats = NULL); 336 bool Allocate(PipelineStatistics* stats = NULL);
337 bool AllocationOk() { return allocation_ok_; }
338 BitVector* assigned_registers() { return assigned_registers_; }
339 BitVector* assigned_double_registers() { return assigned_double_registers_; }
337 340
338 const ZoneList<LiveRange*>* live_ranges() const { return &live_ranges_; } 341 const ZoneList<LiveRange*>* live_ranges() const { return &live_ranges_; }
339 const Vector<LiveRange*>* fixed_live_ranges() const { 342 const Vector<LiveRange*>* fixed_live_ranges() const {
340 return &fixed_live_ranges_; 343 return &fixed_live_ranges_;
341 } 344 }
342 const Vector<LiveRange*>* fixed_double_live_ranges() const { 345 const Vector<LiveRange*>* fixed_double_live_ranges() const {
343 return &fixed_double_live_ranges_; 346 return &fixed_double_live_ranges_;
344 } 347 }
348 InstructionSequence* code() const { return code_; }
345 349
346 CompilationInfo* info() const { return info_; } 350 private:
347 inline InstructionSequence* code() const { return code_; }
348
349 // This zone is for datastructures only needed during register allocation.
350 inline Zone* zone() const { return zone_; }
351
352 // This zone is for InstructionOperands and moves that live beyond register
353 // allocation.
354 inline Zone* code_zone() const { return code()->zone(); }
355
356 int GetVirtualRegister() { 351 int GetVirtualRegister() {
357 int vreg = code()->NextVirtualRegister(); 352 int vreg = code()->NextVirtualRegister();
358 if (vreg >= UnallocatedOperand::kMaxVirtualRegisters) { 353 if (vreg >= UnallocatedOperand::kMaxVirtualRegisters) {
359 allocation_ok_ = false; 354 allocation_ok_ = false;
360 // Maintain the invariant that we return something below the maximum. 355 // Maintain the invariant that we return something below the maximum.
361 return 0; 356 return 0;
362 } 357 }
363 return vreg; 358 return vreg;
364 } 359 }
365 360
366 bool AllocationOk() { return allocation_ok_; } 361 // Checks whether the value of a given virtual register is a reference.
362 // TODO(titzer): rename this to IsReference.
363 bool HasTaggedValue(int virtual_register) const;
364
365 // Returns the register kind required by the given virtual register.
366 RegisterKind RequiredRegisterKind(int virtual_register) const;
367
368 // This zone is for datastructures only needed during register allocation.
369 Zone* zone() const { return zone_; }
370
371 // This zone is for InstructionOperands and moves that live beyond register
372 // allocation.
373 Zone* code_zone() const { return code()->zone(); }
367 374
368 #ifdef DEBUG 375 #ifdef DEBUG
369 void Verify() const; 376 void Verify() const;
370 #endif 377 #endif
371 378
372 BitVector* assigned_registers() { return assigned_registers_; }
373 BitVector* assigned_double_registers() { return assigned_double_registers_; }
374
375 private:
376 void MeetRegisterConstraints(); 379 void MeetRegisterConstraints();
377 void ResolvePhis(); 380 void ResolvePhis();
378 void BuildLiveRanges(); 381 void BuildLiveRanges();
379 void AllocateGeneralRegisters(); 382 void AllocateGeneralRegisters();
380 void AllocateDoubleRegisters(); 383 void AllocateDoubleRegisters();
381 void ConnectRanges(); 384 void ConnectRanges();
382 void ResolveControlFlow(); 385 void ResolveControlFlow();
383 void PopulatePointerMaps(); // TODO(titzer): rename to PopulateReferenceMaps. 386 void PopulatePointerMaps(); // TODO(titzer): rename to PopulateReferenceMaps.
384 void AllocateRegisters(); 387 void AllocateRegisters();
385 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const; 388 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const;
386 inline bool SafePointsAreInOrder() const; 389 bool SafePointsAreInOrder() const;
387 390
388 // Liveness analysis support. 391 // Liveness analysis support.
389 void InitializeLivenessAnalysis(); 392 void InitializeLivenessAnalysis();
390 BitVector* ComputeLiveOut(const InstructionBlock* block); 393 BitVector* ComputeLiveOut(const InstructionBlock* block);
391 void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out); 394 void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out);
392 bool IsOutputRegisterOf(Instruction* instr, int index); 395 bool IsOutputRegisterOf(Instruction* instr, int index);
393 bool IsOutputDoubleRegisterOf(Instruction* instr, int index); 396 bool IsOutputDoubleRegisterOf(Instruction* instr, int index);
394 void ProcessInstructions(const InstructionBlock* block, BitVector* live); 397 void ProcessInstructions(const InstructionBlock* block, BitVector* live);
395 void MeetRegisterConstraints(const InstructionBlock* block); 398 void MeetRegisterConstraints(const InstructionBlock* block);
396 void MeetConstraintsBetween(Instruction* first, Instruction* second, 399 void MeetConstraintsBetween(Instruction* first, Instruction* second,
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 LifetimePosition FindOptimalSpillingPos(LiveRange* range, 470 LifetimePosition FindOptimalSpillingPos(LiveRange* range,
468 LifetimePosition pos); 471 LifetimePosition pos);
469 472
470 void Spill(LiveRange* range); 473 void Spill(LiveRange* range);
471 bool IsBlockBoundary(LifetimePosition pos); 474 bool IsBlockBoundary(LifetimePosition pos);
472 475
473 // Helper methods for resolving control flow. 476 // Helper methods for resolving control flow.
474 void ResolveControlFlow(LiveRange* range, const InstructionBlock* block, 477 void ResolveControlFlow(LiveRange* range, const InstructionBlock* block,
475 const InstructionBlock* pred); 478 const InstructionBlock* pred);
476 479
477 inline void SetLiveRangeAssignedRegister(LiveRange* range, int reg); 480 void SetLiveRangeAssignedRegister(LiveRange* range, int reg);
478 481
479 // Return parallel move that should be used to connect ranges split at the 482 // Return parallel move that should be used to connect ranges split at the
480 // given position. 483 // given position.
481 ParallelMove* GetConnectingParallelMove(LifetimePosition pos); 484 ParallelMove* GetConnectingParallelMove(LifetimePosition pos);
482 485
483 // Return the block which contains give lifetime position. 486 // Return the block which contains give lifetime position.
484 const InstructionBlock* GetInstructionBlock(LifetimePosition pos); 487 const InstructionBlock* GetInstructionBlock(LifetimePosition pos);
485 488
486 // Helper methods for the fixed registers. 489 // Helper methods for the fixed registers.
487 int RegisterCount() const; 490 int RegisterCount() const;
488 static int FixedLiveRangeID(int index) { return -index - 1; } 491 static int FixedLiveRangeID(int index) { return -index - 1; }
489 static int FixedDoubleLiveRangeID(int index); 492 static int FixedDoubleLiveRangeID(int index);
490 LiveRange* FixedLiveRangeFor(int index); 493 LiveRange* FixedLiveRangeFor(int index);
491 LiveRange* FixedDoubleLiveRangeFor(int index); 494 LiveRange* FixedDoubleLiveRangeFor(int index);
492 LiveRange* LiveRangeFor(int index); 495 LiveRange* LiveRangeFor(int index);
493 GapInstruction* GetLastGap(const InstructionBlock* block); 496 GapInstruction* GetLastGap(const InstructionBlock* block);
494 497
495 const char* RegisterName(int allocation_index); 498 const char* RegisterName(int allocation_index);
496 499
497 inline Instruction* InstructionAt(int index) { 500 Instruction* InstructionAt(int index) { return code()->InstructionAt(index); }
498 return code()->InstructionAt(index);
499 }
500 501
501 Frame* frame() const { return frame_; } 502 Frame* frame() const { return frame_; }
503 const char* debug_name() const { return debug_name_; }
502 504
503 Zone* const zone_; 505 Zone* const zone_;
504 Frame* const frame_; 506 Frame* const frame_;
505 CompilationInfo* const info_;
506 InstructionSequence* const code_; 507 InstructionSequence* const code_;
508 const char* const debug_name_;
507 509
508 // During liveness analysis keep a mapping from block id to live_in sets 510 // During liveness analysis keep a mapping from block id to live_in sets
509 // for blocks already analyzed. 511 // for blocks already analyzed.
510 ZoneList<BitVector*> live_in_sets_; 512 ZoneList<BitVector*> live_in_sets_;
511 513
512 // Liveness analysis results. 514 // Liveness analysis results.
513 ZoneList<LiveRange*> live_ranges_; 515 ZoneList<LiveRange*> live_ranges_;
514 516
515 // Lists of live ranges 517 // Lists of live ranges
516 EmbeddedVector<LiveRange*, Register::kMaxNumAllocatableRegisters> 518 EmbeddedVector<LiveRange*, Register::kMaxNumAllocatableRegisters>
(...skipping 19 matching lines...) Expand all
536 #endif 538 #endif
537 539
538 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator); 540 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator);
539 }; 541 };
540 542
541 } 543 }
542 } 544 }
543 } // namespace v8::internal::compiler 545 } // namespace v8::internal::compiler
544 546
545 #endif // V8_REGISTER_ALLOCATOR_H_ 547 #endif // V8_REGISTER_ALLOCATOR_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698