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

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

Powered by Google App Engine
This is Rietveld 408576698