5#ifndef RUNTIME_VM_COMPILER_BACKEND_LINEARSCAN_H_
6#define RUNTIME_VM_COMPILER_BACKEND_LINEARSCAN_H_
8#if defined(DART_PRECOMPILED_RUNTIME)
9#error "AOT runtime should not use compiler sources (including header files)"
18class AllocationFinger;
27 : flow_graph_(flow_graph), phis_(10) {}
43 graph_entry_(flow_graph.graph_entry()) {}
62 bool intrinsic_mode =
false);
84 void CollectRepresentations();
106 void NumberInstructions();
109 bool IsBlockEntry(intptr_t
pos)
const;
115 void BuildLiveRanges();
121 const intptr_t block_start_pos,
122 const intptr_t use_pos,
135 bool output_same_as_first_input,
144 static constexpr intptr_t kNormalEntryPos = 2;
147 void ProcessInitialDefinition(
Definition* defn,
150 intptr_t initial_definition_index,
151 bool second_location_for_definition =
false);
153 void BlockLocation(
Location loc, intptr_t from, intptr_t to);
154 void BlockRegisterLocation(
Location loc,
157 bool* blocked_registers,
160 void BlockCpuRegisters(intptr_t registers, intptr_t from, intptr_t to);
162 void BlockFpuRegisters(intptr_t fpu_registers, intptr_t from, intptr_t to);
164 intptr_t NumberOfRegisters()
const {
return number_of_registers_; }
167 bool IsLiveAfterCatchEntry(CatchBlockEntryInstr* catch_entry,
168 ParameterInstr* param);
171 void AssignSafepoints(Definition* defn, LiveRange* range);
174 intptr_t number_of_registers,
175 const GrowableArray<LiveRange*>& unallocated,
176 LiveRange** blocking_ranges,
177 bool* blocked_registers);
181 void AllocateUnallocatedRanges();
182 void AdvanceActiveIntervals(
const intptr_t start);
184 void RemoveFrameIfNotNeeded();
187 void ResolveControlFlow();
189 void ScheduleParallelMoves();
192 bool TargetLocationIsSpillSlot(LiveRange* range,
Location target);
196 void ConvertUseTo(UsePosition* use,
Location loc);
197 void ConvertAllUses(LiveRange* range);
201 void AddToUnallocated(LiveRange* range);
204 bool UnallocatedIsSorted();
208 bool AllocateFreeRegister(LiveRange* unallocated);
214 void AllocateAnyRegister(LiveRange* unallocated);
218 bool RangeHasOnlyUnconstrainedUsesInLoop(LiveRange* range, intptr_t loop_id);
226 bool HasCheapEvictionCandidate(LiveRange* phi_range);
227 bool IsCheapToEvictRegisterInLoop(LoopInfo* loop_info, intptr_t reg);
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);
239 intptr_t FirstIntersectionWithAllocated(intptr_t reg, LiveRange* unallocated);
241 bool UpdateFreeUntil(intptr_t reg,
242 LiveRange* unallocated,
243 intptr_t* cur_free_until,
244 intptr_t* cur_blocked_at);
247 LiveRange* SplitBetween(LiveRange* range, intptr_t from, intptr_t to);
250 void AllocateSpillSlotFor(LiveRange* range);
253 void AllocateSpillSlotForSuspendState();
257 void UpdateStackmapsForSuspendState();
261 bool IsSuspendStateParameter(Definition* defn);
265 void AllocateSpillSlotForInitialDefinition(intptr_t slot_index,
269 void Spill(LiveRange* range);
272 void SpillAfter(LiveRange* range, intptr_t from);
276 void SpillBetween(LiveRange* range, intptr_t from, intptr_t to);
280 void MarkAsObjectAtSafepoints(LiveRange* range);
284 Location MakeRegisterLocation(intptr_t reg) {
288 void SplitInitialDefinitionAt(LiveRange* range,
292 void PrintLiveRanges();
297 void AllocateOutgoingArguments();
299 const FlowGraph& flow_graph_;
301 ReachingDefs reaching_defs_;
304 GrowableArray<Representation> value_representations_;
306 const GrowableArray<BlockEntryInstr*>& block_order_;
307 const GrowableArray<BlockEntryInstr*>& postorder_;
310 GrowableArray<Instruction*> instructions_;
313 GrowableArray<BlockEntryInstr*> block_entries_;
316 GrowableArray<ExtraLoopInfo*> extra_loop_info_;
318 SSALivenessAnalysis liveness_;
322 const intptr_t vreg_count_;
325 GrowableArray<LiveRange*> live_ranges_;
327 GrowableArray<LiveRange*> unallocated_cpu_;
328 GrowableArray<LiveRange*> unallocated_fpu_;
337 GrowableArray<LiveRange*> temporaries_;
341 GrowableArray<LiveRange*> spilled_;
344 GrowableArray<Instruction*> safepoints_;
348 intptr_t number_of_registers_;
355 GrowableArray<ZoneGrowableArray<LiveRange*>*> registers_;
357 GrowableArray<bool> blocked_registers_;
361 GrowableArray<LiveRange*> unallocated_;
365 GrowableArray<intptr_t> spill_slots_;
370 GrowableArray<bool> quad_spill_slots_;
375 GrowableArray<bool> untagged_spill_slots_;
377 intptr_t cpu_spill_slot_count_;
379 const bool intrinsic_mode_;
413 intptr_t
pos()
const {
return pos_; }
438 intptr_t
start()
const {
return start_; }
439 intptr_t
end()
const {
return end_; }
465 : first_pending_use_interval_(nullptr),
466 first_register_use_(nullptr),
467 first_register_beneficial_use_(nullptr),
468 first_hinted_use_(nullptr) {}
475 return first_pending_use_interval_;
495 : pos_(
pos), locs_(
locs), next_(nullptr) {}
500 intptr_t
pos()
const {
return pos_; }
516 representation_(rep),
517 assigned_location_(),
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),
529 intptr_t
vreg()
const {
return vreg_; }
546 assigned_location_ = location;
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;
585 if (loop_id < kMaxLoops) {
586 has_only_any_uses_in_loops_ |=
static_cast<uint64_t
>(1) << loop_id;
594 has_uses_which_require_stack_ =
true;
597 return has_uses_which_require_stack_;
609 representation_(rep),
610 assigned_location_(),
615 last_safepoint_(nullptr),
617 has_only_any_uses_in_loops_(0),
621 const intptr_t vreg_;
627 UseInterval* first_use_interval_;
628 UseInterval* last_use_interval_;
630 SafepointPosition* first_safepoint_;
631 SafepointPosition* last_safepoint_;
635 static constexpr intptr_t kMaxLoops =
sizeof(uint64_t) *
kBitsPerByte;
636 uint64_t has_only_any_uses_in_loops_;
640 bool has_uses_which_require_stack_ =
false;
642 AllocationFinger finger_;
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
static DART_FORCE_INLINE bool HasLifetimePosition(Instruction *instr)
static DART_FORCE_INLINE intptr_t GetLifetimePosition(const Instruction *instr)
static DART_FORCE_INLINE void SetLifetimePosition(Instruction *instr, intptr_t pos)
LiveRange * GetLiveRange(intptr_t vreg)
static constexpr intptr_t kDoubleSpillFactor
FlowGraphAllocator(const FlowGraph &flow_graph, bool intrinsic_mode=false)
bool HasPassSpecificId(CompilerPass::Id pass) const
intptr_t GetPassSpecificId(CompilerPass::Id pass) const
void SetPassSpecificId(CompilerPass::Id pass, intptr_t id)
void DefineAt(intptr_t pos)
void set_first_use(UsePosition *use)
UseInterval * last_use_interval() const
bool has_uses_which_require_stack() const
bool Contains(intptr_t pos) const
Location spill_slot() const
UsePosition * first_use() const
bool HasOnlyUnconstrainedUsesInLoop(intptr_t loop_id) const
void AddHintedUse(intptr_t pos, Location *location_slot, Location *hint)
Location * assigned_location_slot()
void mark_has_uses_which_require_stack()
void MarkHasOnlyUnconstrainedUsesInLoop(intptr_t loop_id)
Location assigned_location() const
Representation representation() const
LiveRange(intptr_t vreg, Representation rep)
AllocationFinger * finger()
LiveRange * next_sibling() const
void set_spill_slot(Location spill_slot)
UseInterval * first_use_interval() const
UsePosition * AddUse(intptr_t pos, Location *location_slot)
void AddUseInterval(intptr_t start, intptr_t end)
SafepointPosition * first_safepoint() const
LiveRange * SplitAt(intptr_t pos)
bool CanCover(intptr_t pos) const
void set_assigned_location(Location location)
void AddSafepoint(intptr_t pos, LocationSummary *locs)
static Location MachineRegisterLocation(Kind kind, intptr_t reg)
bool IsUnallocated() const
ReachingDefs(const FlowGraph &flow_graph)
BitVector * Get(PhiInstr *phi)
SSALivenessAnalysis(const FlowGraph &flow_graph)
virtual void ComputeInitialSets()
SafepointPosition * next() const
LocationSummary * locs() const
SafepointPosition(intptr_t pos, LocationSummary *locs)
void set_next(SafepointPosition *next)
bool Contains(intptr_t pos) const
UseInterval * next() const
intptr_t Intersect(UseInterval *other)
UseInterval(intptr_t start, intptr_t end, UseInterval *next)
void set_location_slot(Location *location_slot)
UsePosition(intptr_t pos, UsePosition *next, Location *location_slot)
void set_next(UsePosition *next)
Location * location_slot() const
UsePosition * next() const
void set_hint(Location *hint)
static constexpr intptr_t kWordSize
constexpr intptr_t kBitsPerByte
const int kNumberOfFpuRegisters
constexpr intptr_t kDoubleSize
static SkString join(const CommandLineFlags::StringArray &)