Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
linearscan.h
Go to the documentation of this file.
1// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_COMPILER_BACKEND_LINEARSCAN_H_
6#define RUNTIME_VM_COMPILER_BACKEND_LINEARSCAN_H_
7
8#if defined(DART_PRECOMPILED_RUNTIME)
9#error "AOT runtime should not use compiler sources (including header files)"
10#endif // defined(DART_PRECOMPILED_RUNTIME)
11
14#include "vm/growable_array.h"
15
16namespace dart {
17
18class AllocationFinger;
19class FlowGraph;
20class LiveRange;
21class UseInterval;
22class UsePosition;
23
24class ReachingDefs : public ValueObject {
25 public:
26 explicit ReachingDefs(const FlowGraph& flow_graph)
27 : flow_graph_(flow_graph), phis_(10) {}
28
29 BitVector* Get(PhiInstr* phi);
30
31 private:
32 void AddPhi(PhiInstr* phi);
33 void Compute();
34
35 const FlowGraph& flow_graph_;
37};
38
40 public:
41 explicit SSALivenessAnalysis(const FlowGraph& flow_graph)
42 : LivenessAnalysis(flow_graph.max_vreg(), flow_graph.postorder()),
43 graph_entry_(flow_graph.graph_entry()) {}
44
45 private:
46 // Compute initial values for live-out, kill and live-in sets.
47 virtual void ComputeInitialSets();
48
49 GraphEntryInstr* graph_entry_;
50};
51
52// Forward.
53struct ExtraLoopInfo;
54
56 public:
57 // Number of stack slots needed for a fpu register spill slot.
58 static constexpr intptr_t kDoubleSpillFactor =
59 kDoubleSize / compiler::target::kWordSize;
60
61 explicit FlowGraphAllocator(const FlowGraph& flow_graph,
62 bool intrinsic_mode = false);
63
64 void AllocateRegisters();
65
66 // Map a virtual register number to its live range.
67 LiveRange* GetLiveRange(intptr_t vreg);
68
69 DART_FORCE_INLINE static void SetLifetimePosition(Instruction* instr,
70 intptr_t pos) {
71 instr->SetPassSpecificId(CompilerPass::kAllocateRegisters, pos);
72 }
73
74 DART_FORCE_INLINE static bool HasLifetimePosition(Instruction* instr) {
75 return instr->HasPassSpecificId(CompilerPass::kAllocateRegisters);
76 }
77
78 DART_FORCE_INLINE static intptr_t GetLifetimePosition(
79 const Instruction* instr) {
80 return instr->GetPassSpecificId(CompilerPass::kAllocateRegisters);
81 }
82
83 private:
84 void CollectRepresentations();
85
86 // Visit blocks in the code generation order (reverse post order) and
87 // linearly assign consequent lifetime positions to every instruction.
88 // We assign position as follows:
89 //
90 // 2 * n - even position corresponding to instruction's start;
91 //
92 // 2 * n + 1 - odd position corresponding to instruction's end;
93 //
94 // Having two positions per instruction allows us to capture non-trivial
95 // shapes of use intervals: e.g. by placing a use at the start or the
96 // end position we can distinguish between instructions that need value
97 // at the register only at their start and those instructions that
98 // need value in the register until the end of instruction's body.
99 // Register allocator can perform splitting of live ranges at any position.
100 // An implicit ParallelMove will be inserted by ConnectSplitSiblings where
101 // required to resolve data flow between split siblings when allocation
102 // is finished.
103 // For specific examples see comments inside ProcessOneInstruction.
104 // Additionally creates parallel moves at the joins' predecessors
105 // that will be used for phi resolution.
106 void NumberInstructions();
107 Instruction* InstructionAt(intptr_t pos) const;
108 BlockEntryInstr* BlockEntryAt(intptr_t pos) const;
109 bool IsBlockEntry(intptr_t pos) const;
110
111 LiveRange* MakeLiveRangeForTemporary();
112
113 // Visit instructions in the postorder and build live ranges for
114 // all SSA values.
115 void BuildLiveRanges();
116
117 Instruction* ConnectOutgoingPhiMoves(BlockEntryInstr* block,
118 BitVector* interference_set);
119 void ProcessEnvironmentUses(BlockEntryInstr* block, Instruction* current);
120 void ProcessMaterializationUses(BlockEntryInstr* block,
121 const intptr_t block_start_pos,
122 const intptr_t use_pos,
124 void ProcessOneInput(BlockEntryInstr* block,
125 intptr_t pos,
126 Location* in_ref,
127 Value* input,
128 intptr_t vreg,
129 RegisterSet* live_registers);
130 void ProcessOneOutput(BlockEntryInstr* block,
131 intptr_t pos,
132 Location* out,
133 Definition* def,
134 intptr_t vreg,
135 bool output_same_as_first_input,
136 Location* in_ref,
137 Definition* input,
138 intptr_t input_vreg,
139 BitVector* interference_set);
140 void ProcessOneInstruction(BlockEntryInstr* block,
141 Instruction* instr,
142 BitVector* interference_set);
143
144 static constexpr intptr_t kNormalEntryPos = 2;
145
146 void CompleteRange(Definition* defn, LiveRange* range);
147 void ProcessInitialDefinition(Definition* defn,
148 LiveRange* range,
149 BlockEntryInstr* block,
150 intptr_t initial_definition_index,
151 bool second_location_for_definition = false);
152 void ConnectIncomingPhiMoves(JoinEntryInstr* join);
153 void BlockLocation(Location loc, intptr_t from, intptr_t to);
154 void BlockRegisterLocation(Location loc,
155 intptr_t from,
156 intptr_t to,
157 bool* blocked_registers,
158 LiveRange** blocking_ranges);
159
160 void BlockCpuRegisters(intptr_t registers, intptr_t from, intptr_t to);
161
162 void BlockFpuRegisters(intptr_t fpu_registers, intptr_t from, intptr_t to);
163
164 intptr_t NumberOfRegisters() const { return number_of_registers_; }
165
166 // Test if [param] is live only after [catch_entry].
167 bool IsLiveAfterCatchEntry(CatchBlockEntryInstr* catch_entry,
168 ParameterInstr* param);
169
170 // Find all safepoints that are covered by this live range.
171 void AssignSafepoints(Definition* defn, LiveRange* range);
172
173 void PrepareForAllocation(Location::Kind register_kind,
174 intptr_t number_of_registers,
175 const GrowableArray<LiveRange*>& unallocated,
176 LiveRange** blocking_ranges,
177 bool* blocked_registers);
178
179 // Process live ranges sorted by their start and assign registers
180 // to them
181 void AllocateUnallocatedRanges();
182 void AdvanceActiveIntervals(const intptr_t start);
183
184 void RemoveFrameIfNotNeeded();
185
186 // Connect split siblings over non-linear control flow edges.
187 void ResolveControlFlow();
188
189 void ScheduleParallelMoves();
190
191 // Returns true if the target location is the spill slot for the given range.
192 bool TargetLocationIsSpillSlot(LiveRange* range, Location target);
193
194 // Update location slot corresponding to the use with location allocated for
195 // the use's live range.
196 void ConvertUseTo(UsePosition* use, Location loc);
197 void ConvertAllUses(LiveRange* range);
198
199 // Add live range to the list of unallocated live ranges to be processed
200 // by the allocator.
201 void AddToUnallocated(LiveRange* range);
202 void CompleteRange(LiveRange* range, Location::Kind kind);
203#if defined(DEBUG)
204 bool UnallocatedIsSorted();
205#endif
206
207 // Try to find a free register for an unallocated live range.
208 bool AllocateFreeRegister(LiveRange* unallocated);
209
210 // Try to find a register that can be used by a given live range.
211 // If all registers are occupied consider evicting interference for
212 // a register that is going to be used as far from the start of
213 // the unallocated live range as possible.
214 void AllocateAnyRegister(LiveRange* unallocated);
215
216 // Returns true if the given range has only unconstrained uses in
217 // the given loop.
218 bool RangeHasOnlyUnconstrainedUsesInLoop(LiveRange* range, intptr_t loop_id);
219
220 // Returns true if there is a register blocked by a range that
221 // has only unconstrained uses in the loop. Such range is a good
222 // eviction candidate when allocator tries to allocate loop phi.
223 // Spilling loop phi will have a bigger negative impact on the
224 // performance because it introduces multiple operations with memory
225 // inside the loop body and on the back edge.
226 bool HasCheapEvictionCandidate(LiveRange* phi_range);
227 bool IsCheapToEvictRegisterInLoop(LoopInfo* loop_info, intptr_t reg);
228
229 // Assign selected non-free register to an unallocated live range and
230 // evict any interference that can be evicted by splitting and spilling
231 // parts of interfering live ranges. Place non-spilled parts into
232 // the list of unallocated ranges.
233 void AssignNonFreeRegister(LiveRange* unallocated, intptr_t reg);
234 bool EvictIntersection(LiveRange* allocated, LiveRange* unallocated);
235 void RemoveEvicted(intptr_t reg, intptr_t first_evicted);
236
237 // Find first intersection between unallocated live range and
238 // live ranges currently allocated to the given register.
239 intptr_t FirstIntersectionWithAllocated(intptr_t reg, LiveRange* unallocated);
240
241 bool UpdateFreeUntil(intptr_t reg,
242 LiveRange* unallocated,
243 intptr_t* cur_free_until,
244 intptr_t* cur_blocked_at);
245
246 // Split given live range in an optimal position between given positions.
247 LiveRange* SplitBetween(LiveRange* range, intptr_t from, intptr_t to);
248
249 // Find a spill slot that can be used by the given live range.
250 void AllocateSpillSlotFor(LiveRange* range);
251
252 // Allocate spill slot for synthetic :suspend_state variable.
253 void AllocateSpillSlotForSuspendState();
254
255 // Mark synthetic :suspend_state variable as object in stackmaps
256 // at all safepoints.
257 void UpdateStackmapsForSuspendState();
258
259 // Returns true if [defn] is an OsrEntry or CatchBlockEntry parameter
260 // corresponding to a synthetic :suspend_state variable.
261 bool IsSuspendStateParameter(Definition* defn);
262
263 // Allocates spill slot [slot_index] for the initial definition of
264 // OsrEntry or CatchBlockEntry (Parameter or Constant).
265 void AllocateSpillSlotForInitialDefinition(intptr_t slot_index,
266 intptr_t range_end);
267
268 // Allocate the given live range to a spill slot.
269 void Spill(LiveRange* range);
270
271 // Spill the given live range from the given position onwards.
272 void SpillAfter(LiveRange* range, intptr_t from);
273
274 // Spill the given live range from the given position until some
275 // position preceding the to position.
276 void SpillBetween(LiveRange* range, intptr_t from, intptr_t to);
277
278 // Mark the live range as a live object pointer at all safepoints
279 // contained in the range.
280 void MarkAsObjectAtSafepoints(LiveRange* range);
281
282 MoveOperands* AddMoveAt(intptr_t pos, Location to, Location from);
283
284 Location MakeRegisterLocation(intptr_t reg) {
285 return Location::MachineRegisterLocation(register_kind_, reg);
286 }
287
288 void SplitInitialDefinitionAt(LiveRange* range,
289 intptr_t pos,
290 Location::Kind kind);
291
292 void PrintLiveRanges();
293
294 // Assign locations for each outgoing argument. Outgoing argumenst are
295 // currently stored at the top of the stack in direct order (last argument
296 // at the top of the stack).
297 void AllocateOutgoingArguments();
298
299 const FlowGraph& flow_graph_;
300
301 ReachingDefs reaching_defs_;
302
303 // Representation for SSA values indexed by SSA temp index.
304 GrowableArray<Representation> value_representations_;
305
306 const GrowableArray<BlockEntryInstr*>& block_order_;
307 const GrowableArray<BlockEntryInstr*>& postorder_;
308
309 // Mapping between lifetime positions and instructions.
310 GrowableArray<Instruction*> instructions_;
311
312 // Mapping between lifetime positions and block entries.
313 GrowableArray<BlockEntryInstr*> block_entries_;
314
315 // Mapping between loops and additional information.
316 GrowableArray<ExtraLoopInfo*> extra_loop_info_;
317
318 SSALivenessAnalysis liveness_;
319
320 // Number of virtual registers. Currently equal to the number of
321 // SSA values.
322 const intptr_t vreg_count_;
323
324 // LiveRanges corresponding to SSA values.
325 GrowableArray<LiveRange*> live_ranges_;
326
327 GrowableArray<LiveRange*> unallocated_cpu_;
328 GrowableArray<LiveRange*> unallocated_fpu_;
329
330 LiveRange* cpu_regs_[kNumberOfCpuRegisters];
331 LiveRange* fpu_regs_[kNumberOfFpuRegisters];
332
333 bool blocked_cpu_registers_[kNumberOfCpuRegisters];
334 bool blocked_fpu_registers_[kNumberOfFpuRegisters];
335
336#if defined(DEBUG)
337 GrowableArray<LiveRange*> temporaries_;
338#endif
339
340 // List of spilled live ranges.
341 GrowableArray<LiveRange*> spilled_;
342
343 // List of instructions containing calls.
344 GrowableArray<Instruction*> safepoints_;
345
346 Location::Kind register_kind_;
347
348 intptr_t number_of_registers_;
349
350 // Per register lists of allocated live ranges. Contain only those
351 // ranges that can be affected by future allocation decisions.
352 // Those live ranges that end before the start of the current live range are
353 // removed from the list and will not be affected.
354 // The length of both arrays is 'number_of_registers_'
355 GrowableArray<ZoneGrowableArray<LiveRange*>*> registers_;
356
357 GrowableArray<bool> blocked_registers_;
358
359 // Worklist for register allocator. Always maintained sorted according
360 // to ShouldBeAllocatedBefore predicate.
361 GrowableArray<LiveRange*> unallocated_;
362
363 // List of used spill slots. Contains positions after which spill slots
364 // become free and can be reused for allocation.
365 GrowableArray<intptr_t> spill_slots_;
366
367 // For every used spill slot contains a flag determines whether it is
368 // QuadSpillSlot to ensure that indexes of quad and double spill slots
369 // are disjoint.
370 GrowableArray<bool> quad_spill_slots_;
371
372 // Track whether a spill slot is expected to hold a tagged or untagged value.
373 // This is used to keep tagged and untagged spill slots disjoint. See bug
374 // #18955 for details.
375 GrowableArray<bool> untagged_spill_slots_;
376
377 intptr_t cpu_spill_slot_count_;
378
379 const bool intrinsic_mode_;
380
381 DISALLOW_COPY_AND_ASSIGN(FlowGraphAllocator);
382};
383
384// UsePosition represents a single use of an SSA value by some instruction.
385// It points to a location slot which either tells register allocator
386// where instruction expects the value (if slot contains a fixed location) or
387// asks register allocator to allocate storage (register or spill slot) for
388// this use with certain properties (if slot contains an unallocated location).
390 public:
392 : pos_(pos), location_slot_(location_slot), hint_(nullptr), next_(next) {
393 ASSERT(location_slot != nullptr);
394 }
395
396 Location* location_slot() const { return location_slot_; }
398 location_slot_ = location_slot;
399 }
400
401 Location hint() const {
402 ASSERT(HasHint());
403 return *hint_;
404 }
405
406 void set_hint(Location* hint) { hint_ = hint; }
407
408 bool HasHint() const { return (hint_ != nullptr) && !hint_->IsUnallocated(); }
409
410 void set_next(UsePosition* next) { next_ = next; }
411 UsePosition* next() const { return next_; }
412
413 intptr_t pos() const { return pos_; }
414
415 private:
416 const intptr_t pos_;
417 Location* location_slot_;
418 Location* hint_;
419 UsePosition* next_;
420
422};
423
424// UseInterval represents a holeless half open interval of liveness for a given
425// SSA value: [start, end) in terms of lifetime positions that
426// NumberInstructions assigns to instructions. Register allocator has to keep
427// a value live in the register or in a spill slot from start position and until
428// the end position. The interval can cover zero or more uses.
429// Note: currently all uses of the same SSA value are linked together into a
430// single list (and not split between UseIntervals).
432 public:
433 UseInterval(intptr_t start, intptr_t end, UseInterval* next)
434 : start_(start), end_(end), next_(next) {}
435
436 void Print();
437
438 intptr_t start() const { return start_; }
439 intptr_t end() const { return end_; }
440 UseInterval* next() const { return next_; }
441
442 bool Contains(intptr_t pos) const {
443 return (start() <= pos) && (pos < end());
444 }
445
446 // Return the smallest position that is covered by both UseIntervals or
447 // kIllegalPosition if intervals do not intersect.
448 intptr_t Intersect(UseInterval* other);
449
450 private:
451 friend class LiveRange;
452
453 intptr_t start_;
454 intptr_t end_;
455 UseInterval* next_;
456
458};
459
460// AllocationFinger is used to keep track of currently active position
461// for the register allocator and cache lookup results.
463 public:
465 : first_pending_use_interval_(nullptr),
466 first_register_use_(nullptr),
467 first_register_beneficial_use_(nullptr),
468 first_hinted_use_(nullptr) {}
469
470 void Initialize(LiveRange* range);
471 void UpdateAfterSplit(intptr_t first_use_after_split_pos);
472 bool Advance(intptr_t start);
473
475 return first_pending_use_interval_;
476 }
477
479 UsePosition* FirstRegisterUse(intptr_t after_pos);
480 UsePosition* FirstRegisterBeneficialUse(intptr_t after_pos);
481 UsePosition* FirstInterferingUse(intptr_t after_pos);
482
483 private:
484 UseInterval* first_pending_use_interval_;
485 UsePosition* first_register_use_;
486 UsePosition* first_register_beneficial_use_;
487 UsePosition* first_hinted_use_;
488
490};
491
493 public:
495 : pos_(pos), locs_(locs), next_(nullptr) {}
496
498 SafepointPosition* next() const { return next_; }
499
500 intptr_t pos() const { return pos_; }
501
502 LocationSummary* locs() const { return locs_; }
503
504 private:
505 const intptr_t pos_;
506 LocationSummary* const locs_;
507
508 SafepointPosition* next_;
509};
510
511// LiveRange represents a sequence of UseIntervals for a given SSA value.
512class LiveRange : public ZoneAllocated {
513 public:
514 explicit LiveRange(intptr_t vreg, Representation rep)
515 : vreg_(vreg),
516 representation_(rep),
517 assigned_location_(),
518 spill_slot_(),
519 uses_(nullptr),
520 first_use_interval_(nullptr),
521 last_use_interval_(nullptr),
522 first_safepoint_(nullptr),
523 last_safepoint_(nullptr),
524 next_sibling_(nullptr),
525 has_only_any_uses_in_loops_(0),
526 is_loop_phi_(false),
527 finger_() {}
528
529 intptr_t vreg() const { return vreg_; }
530 Representation representation() const { return representation_; }
531 LiveRange* next_sibling() const { return next_sibling_; }
532 UsePosition* first_use() const { return uses_; }
533 void set_first_use(UsePosition* use) { uses_ = use; }
534 UseInterval* first_use_interval() const { return first_use_interval_; }
535 UseInterval* last_use_interval() const { return last_use_interval_; }
536 Location assigned_location() const { return assigned_location_; }
537 Location* assigned_location_slot() { return &assigned_location_; }
538 intptr_t Start() const { return first_use_interval()->start(); }
539 intptr_t End() const { return last_use_interval()->end(); }
540
541 SafepointPosition* first_safepoint() const { return first_safepoint_; }
542
543 AllocationFinger* finger() { return &finger_; }
544
546 assigned_location_ = location;
547 }
548
550
551 void DefineAt(intptr_t pos);
552
553 void AddSafepoint(intptr_t pos, LocationSummary* locs);
554
555 UsePosition* AddUse(intptr_t pos, Location* location_slot);
556 void AddHintedUse(intptr_t pos, Location* location_slot, Location* hint);
557
558 void AddUseInterval(intptr_t start, intptr_t end);
559
560 void Print();
561
562 LiveRange* SplitAt(intptr_t pos);
563
564 // A fast conservative check if the range might contain a given position
565 // -- can return true when the range does not contain the position (e.g.,
566 // the position lies in a lifetime hole between range start and end).
567 bool CanCover(intptr_t pos) const {
568 return (Start() <= pos) && (pos < End());
569 }
570
571 // True if the range contains the given position.
572 bool Contains(intptr_t pos) const;
573
574 Location spill_slot() const { return spill_slot_; }
575
576 bool HasOnlyUnconstrainedUsesInLoop(intptr_t loop_id) const {
577 if (loop_id < kMaxLoops) {
578 const uint64_t mask = static_cast<uint64_t>(1) << loop_id;
579 return (has_only_any_uses_in_loops_ & mask) != 0;
580 }
581 return false;
582 }
583
584 void MarkHasOnlyUnconstrainedUsesInLoop(intptr_t loop_id) {
585 if (loop_id < kMaxLoops) {
586 has_only_any_uses_in_loops_ |= static_cast<uint64_t>(1) << loop_id;
587 }
588 }
589
590 bool is_loop_phi() const { return is_loop_phi_; }
591 void mark_loop_phi() { is_loop_phi_ = true; }
592
594 has_uses_which_require_stack_ = true;
595 }
597 return has_uses_which_require_stack_;
598 }
599
600 private:
601 LiveRange(intptr_t vreg,
602 Representation rep,
603 UsePosition* uses,
608 : vreg_(vreg),
609 representation_(rep),
610 assigned_location_(),
611 uses_(uses),
612 first_use_interval_(first_use_interval),
613 last_use_interval_(last_use_interval),
614 first_safepoint_(first_safepoint),
615 last_safepoint_(nullptr),
616 next_sibling_(next_sibling),
617 has_only_any_uses_in_loops_(0),
618 is_loop_phi_(false),
619 finger_() {}
620
621 const intptr_t vreg_;
622 Representation representation_;
623 Location assigned_location_;
624 Location spill_slot_;
625
626 UsePosition* uses_;
627 UseInterval* first_use_interval_;
628 UseInterval* last_use_interval_;
629
630 SafepointPosition* first_safepoint_;
631 SafepointPosition* last_safepoint_;
632
633 LiveRange* next_sibling_;
634
635 static constexpr intptr_t kMaxLoops = sizeof(uint64_t) * kBitsPerByte;
636 uint64_t has_only_any_uses_in_loops_;
637 bool is_loop_phi_;
638
639 // Does this range have any unallocated uses with kRequiresStack policy.
640 bool has_uses_which_require_stack_ = false;
641
642 AllocationFinger finger_;
643
644 DISALLOW_COPY_AND_ASSIGN(LiveRange);
645};
646
647} // namespace dart
648
649#endif // RUNTIME_VM_COMPILER_BACKEND_LINEARSCAN_H_
SkPoint pos
bool Advance(intptr_t start)
UsePosition * FirstRegisterBeneficialUse(intptr_t after_pos)
void Initialize(LiveRange *range)
void UpdateAfterSplit(intptr_t first_use_after_split_pos)
UsePosition * FirstInterferingUse(intptr_t after_pos)
UsePosition * FirstRegisterUse(intptr_t after_pos)
UseInterval * first_pending_use_interval() const
Definition linearscan.h:474
static DART_FORCE_INLINE bool HasLifetimePosition(Instruction *instr)
Definition linearscan.h:74
static DART_FORCE_INLINE intptr_t GetLifetimePosition(const Instruction *instr)
Definition linearscan.h:78
static DART_FORCE_INLINE void SetLifetimePosition(Instruction *instr, intptr_t pos)
Definition linearscan.h:69
LiveRange * GetLiveRange(intptr_t vreg)
static constexpr intptr_t kDoubleSpillFactor
Definition linearscan.h:58
bool HasPassSpecificId(CompilerPass::Id pass) const
Definition il.h:1226
intptr_t GetPassSpecificId(CompilerPass::Id pass) const
Definition il.h:1218
void SetPassSpecificId(CompilerPass::Id pass, intptr_t id)
Definition il.h:1223
void DefineAt(intptr_t pos)
void set_first_use(UsePosition *use)
Definition linearscan.h:533
UseInterval * last_use_interval() const
Definition linearscan.h:535
bool has_uses_which_require_stack() const
Definition linearscan.h:596
void mark_loop_phi()
Definition linearscan.h:591
bool Contains(intptr_t pos) const
bool is_loop_phi() const
Definition linearscan.h:590
Location spill_slot() const
Definition linearscan.h:574
UsePosition * first_use() const
Definition linearscan.h:532
bool HasOnlyUnconstrainedUsesInLoop(intptr_t loop_id) const
Definition linearscan.h:576
intptr_t vreg() const
Definition linearscan.h:529
void AddHintedUse(intptr_t pos, Location *location_slot, Location *hint)
Location * assigned_location_slot()
Definition linearscan.h:537
void mark_has_uses_which_require_stack()
Definition linearscan.h:593
void MarkHasOnlyUnconstrainedUsesInLoop(intptr_t loop_id)
Definition linearscan.h:584
Location assigned_location() const
Definition linearscan.h:536
Representation representation() const
Definition linearscan.h:530
LiveRange(intptr_t vreg, Representation rep)
Definition linearscan.h:514
AllocationFinger * finger()
Definition linearscan.h:543
LiveRange * next_sibling() const
Definition linearscan.h:531
void set_spill_slot(Location spill_slot)
Definition linearscan.h:549
UseInterval * first_use_interval() const
Definition linearscan.h:534
UsePosition * AddUse(intptr_t pos, Location *location_slot)
void AddUseInterval(intptr_t start, intptr_t end)
intptr_t End() const
Definition linearscan.h:539
SafepointPosition * first_safepoint() const
Definition linearscan.h:541
LiveRange * SplitAt(intptr_t pos)
intptr_t Start() const
Definition linearscan.h:538
bool CanCover(intptr_t pos) const
Definition linearscan.h:567
void set_assigned_location(Location location)
Definition linearscan.h:545
void AddSafepoint(intptr_t pos, LocationSummary *locs)
static Location MachineRegisterLocation(Kind kind, intptr_t reg)
Definition locations.h:425
bool IsUnallocated() const
Definition locations.h:341
ReachingDefs(const FlowGraph &flow_graph)
Definition linearscan.h:26
BitVector * Get(PhiInstr *phi)
SSALivenessAnalysis(const FlowGraph &flow_graph)
Definition linearscan.h:41
virtual void ComputeInitialSets()
SafepointPosition * next() const
Definition linearscan.h:498
LocationSummary * locs() const
Definition linearscan.h:502
SafepointPosition(intptr_t pos, LocationSummary *locs)
Definition linearscan.h:494
void set_next(SafepointPosition *next)
Definition linearscan.h:497
intptr_t pos() const
Definition linearscan.h:500
bool Contains(intptr_t pos) const
Definition linearscan.h:442
UseInterval * next() const
Definition linearscan.h:440
intptr_t Intersect(UseInterval *other)
UseInterval(intptr_t start, intptr_t end, UseInterval *next)
Definition linearscan.h:433
intptr_t start() const
Definition linearscan.h:438
intptr_t end() const
Definition linearscan.h:439
Location hint() const
Definition linearscan.h:401
void set_location_slot(Location *location_slot)
Definition linearscan.h:397
bool HasHint() const
Definition linearscan.h:408
UsePosition(intptr_t pos, UsePosition *next, Location *location_slot)
Definition linearscan.h:391
void set_next(UsePosition *next)
Definition linearscan.h:410
Location * location_slot() const
Definition linearscan.h:396
intptr_t pos() const
Definition linearscan.h:413
UsePosition * next() const
Definition linearscan.h:411
void set_hint(Location *hint)
Definition linearscan.h:406
#define ASSERT(E)
glong glong end
uint32_t * target
Representation
Definition locations.h:66
constexpr intptr_t kBitsPerByte
Definition globals.h:463
@ kNumberOfCpuRegisters
const int kNumberOfFpuRegisters
constexpr intptr_t kDoubleSize
Definition globals.h:456
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition globals.h:581