1014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved. 2014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// found in the LICENSE file. 4014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/live-range-separator.h" 6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/register-allocator.h" 7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace v8 { 9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace internal { 10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace compiler { 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define TRACE(...) \ 14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch do { \ 15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_trace_alloc) PrintF(__VA_ARGS__); \ 16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } while (false) 17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace { 20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CreateSplinter(TopLevelLiveRange *range, RegisterAllocationData *data, 23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LifetimePosition first_cut, LifetimePosition last_cut) { 24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!range->IsSplinter()); 25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We can ignore ranges that live solely in deferred blocks. 26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If a range ends right at the end of a deferred block, it is marked by 27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the range builder as ending at gap start of the next block - since the 28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // end is a position where the variable isn't live. We need to take that 29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // into consideration. 30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LifetimePosition max_allowed_end = last_cut.NextFullStart(); 31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (first_cut <= range->Start() && max_allowed_end >= range->End()) { 33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return; 34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LifetimePosition start = Max(first_cut, range->Start()); 37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LifetimePosition end = Min(last_cut, range->End()); 38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (start < end) { 40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Ensure the original range has a spill range associated, before it gets 41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // splintered. Splinters will point to it. This way, when attempting to 42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // reuse spill slots of splinters, during allocation, we avoid clobbering 43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // such slots. 44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (range->MayRequireSpillRange()) { 45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch data->CreateSpillRangeForLiveRange(range); 46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (range->splinter() == nullptr) { 48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TopLevelLiveRange *splinter = 49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch data->NextLiveRange(range->representation()); 50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_NULL(data->live_ranges()[splinter->vreg()]); 51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch data->live_ranges()[splinter->vreg()] = splinter; 52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch range->SetSplinter(splinter); 53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Zone *zone = data->allocation_zone(); 55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TRACE("creating splinter for range %d between %d and %d\n", range->vreg(), 56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch start.ToInstructionIndex(), end.ToInstructionIndex()); 57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch range->Splinter(start, end, zone); 58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid SplinterLiveRange(TopLevelLiveRange *range, RegisterAllocationData *data) { 63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const InstructionSequence *code = data->code(); 64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch UseInterval *interval = range->first_interval(); 65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LifetimePosition first_cut = LifetimePosition::Invalid(); 67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LifetimePosition last_cut = LifetimePosition::Invalid(); 68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch while (interval != nullptr) { 70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch UseInterval *next_interval = interval->next(); 71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const InstructionBlock *first_block = 72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch code->GetInstructionBlock(interval->FirstGapIndex()); 73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const InstructionBlock *last_block = 74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch code->GetInstructionBlock(interval->LastGapIndex()); 75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int first_block_nr = first_block->rpo_number().ToInt(); 76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int last_block_nr = last_block->rpo_number().ToInt(); 77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int block_id = first_block_nr; block_id <= last_block_nr; ++block_id) { 78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const InstructionBlock *current_block = 79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch code->InstructionBlockAt(RpoNumber::FromInt(block_id)); 80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (current_block->IsDeferred()) { 81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!first_cut.IsValid()) { 82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch first_cut = LifetimePosition::GapFromInstructionIndex( 83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch current_block->first_instruction_index()); 84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch last_cut = LifetimePosition::GapFromInstructionIndex( 86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch current_block->last_instruction_index()); 87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (first_cut.IsValid()) { 89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CreateSplinter(range, data, first_cut, last_cut); 90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch first_cut = LifetimePosition::Invalid(); 91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch last_cut = LifetimePosition::Invalid(); 92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch interval = next_interval; 96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // When the range ends in deferred blocks, first_cut will be valid here. 98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Splinter from there to the last instruction that was in a deferred block. 99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (first_cut.IsValid()) { 100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CreateSplinter(range, data, first_cut, last_cut); 101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace 104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LiveRangeSeparator::Splinter() { 107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch size_t virt_reg_count = data()->live_ranges().size(); 108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (size_t vreg = 0; vreg < virt_reg_count; ++vreg) { 109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TopLevelLiveRange *range = data()->live_ranges()[vreg]; 110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (range == nullptr || range->IsEmpty() || range->IsSplinter()) { 111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch continue; 112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int first_instr = range->first_interval()->FirstGapIndex(); 114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!data()->code()->GetInstructionBlock(first_instr)->IsDeferred()) { 115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SplinterLiveRange(range, data()); 116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LiveRangeMerger::MarkRangesSpilledInDeferredBlocks() { 122342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch const InstructionSequence *code = data()->code(); 123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (TopLevelLiveRange *top : data()->live_ranges()) { 124342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch if (top == nullptr || top->IsEmpty() || top->splinter() == nullptr || 125342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch top->HasSpillOperand() || !top->splinter()->HasSpillRange()) { 126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch continue; 127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LiveRange *child = top; 130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (; child != nullptr; child = child->next()) { 131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (child->spilled() || 132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch child->NextSlotPosition(child->Start()) != nullptr) { 133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch break; 134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 136342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch if (child == nullptr) { 137342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch top->TreatAsSpilledInDeferredBlock(data()->allocation_zone(), 138342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch code->InstructionBlockCount()); 139342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch } 140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LiveRangeMerger::Merge() { 145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MarkRangesSpilledInDeferredBlocks(); 146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int live_range_count = static_cast<int>(data()->live_ranges().size()); 148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < live_range_count; ++i) { 149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TopLevelLiveRange *range = data()->live_ranges()[i]; 150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (range == nullptr || range->IsEmpty() || !range->IsSplinter()) { 151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch continue; 152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TopLevelLiveRange *splinter_parent = range->splintered_from(); 154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int to_remove = range->vreg(); 156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch splinter_parent->Merge(range, data()->allocation_zone()); 157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch data()->live_ranges()[to_remove] = nullptr; 158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace compiler 163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 165