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

Unified Diff: src/compiler/register-allocator.cc

Issue 1472803004: [turbofan] Simplified splintering code. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/register-allocator.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/register-allocator.cc
diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc
index 65dadddda3ad368e417ded8330e87a7841190d72..13f7ceeb91f5e8969c4f48690f5fee7a0cd723f8 100644
--- a/src/compiler/register-allocator.cc
+++ b/src/compiler/register-allocator.cc
@@ -713,52 +713,6 @@ void TopLevelLiveRange::RecordSpillLocation(Zone* zone, int gap_index,
}
-void TopLevelLiveRange::MarkSpilledInDeferredBlock(
- const InstructionSequence* code) {
- if (!FLAG_turbo_preprocess_ranges || IsEmpty() || HasNoSpillType() ||
- !HasSpillRange()) {
- return;
- }
-
- int count = 0;
- for (const LiveRange* child = this; child != nullptr; child = child->next()) {
- int first_instr = child->Start().ToInstructionIndex();
-
- // If the range starts at instruction end, the first instruction index is
- // the next one.
- if (!child->Start().IsGapPosition() && !child->Start().IsStart()) {
- ++first_instr;
- }
-
- // We only look at where the range starts. It doesn't matter where it ends:
- // if it ends past this block, then either there is a phi there already,
- // or ResolveControlFlow will adapt the last instruction gap of this block
- // as if there were a phi. In either case, data flow will be correct.
- const InstructionBlock* block = code->GetInstructionBlock(first_instr);
-
- // If we have slot uses in a subrange, bail out, because we need the value
- // on the stack before that use.
- bool has_slot_use = child->NextSlotPosition(child->Start()) != nullptr;
- if (!block->IsDeferred()) {
- if (child->spilled() || has_slot_use) {
- TRACE(
- "Live Range %d must be spilled at definition: found a "
- "slot-requiring non-deferred child range %d.\n",
- TopLevel()->vreg(), child->relative_id());
- return;
- }
- } else {
- if (child->spilled() || has_slot_use) ++count;
- }
- }
- if (count == 0) return;
-
- spill_start_index_ = -1;
- spilled_in_deferred_blocks_ = true;
- spill_move_insertion_locations_ = nullptr;
-}
-
-
bool TopLevelLiveRange::TryCommitSpillInDeferredBlock(
InstructionSequence* code, const InstructionOperand& spill_operand) {
if (!IsSpilledOnlyInDeferredBlocks()) return false;
@@ -854,17 +808,12 @@ void TopLevelLiveRange::Splinter(LifetimePosition start, LifetimePosition end,
TopLevelLiveRange splinter_temp(-1, machine_type());
UsePosition* last_in_splinter = nullptr;
- if (start <= Start()) {
- // TODO(mtrofin): here, the TopLevel part is in the deferred range, so we
- // may want to continue processing the splinter. However, if the value is
- // defined in a cold block, and then used in a hot block, it follows that
- // it should terminate on the RHS of a phi, defined on the hot path. We
- // should check this, however, this may not be the place, because we don't
- // have access to the instruction sequence.
- DCHECK(end < End());
- DetachAt(end, &splinter_temp, zone);
- next_ = nullptr;
- } else if (end >= End()) {
+ // Live ranges defined in deferred blocks stay in deferred blocks, so we
+ // don't need to splinter them. That means that start should always be
+ // after the beginning of the range.
+ DCHECK(start > Start());
+
+ if (end >= End()) {
DCHECK(start > Start());
DetachAt(start, &splinter_temp, zone);
next_ = nullptr;
@@ -1397,6 +1346,37 @@ bool RegisterAllocationData::ExistsUseWithoutDefinition() {
}
+// If a range is defined in a deferred block, we can expect all the range
+// to only cover positions in deferred blocks. Otherwise, a block on the
+// hot path would be dominated by a deferred block, meaning it is unreachable
+// without passing through the deferred block, which is contradictory.
+// In particular, when such a range contributes a result back on the hot
+// path, it will be as one of the inputs of a phi. In that case, the value
+// will be transferred via a move in the Gap::END's of the last instruction
+// of a deferred block.
+bool RegisterAllocationData::RangesDefinedInDeferredStayInDeferred() {
+ for (const TopLevelLiveRange* range : live_ranges()) {
+ if (range == nullptr || range->IsEmpty() ||
+ !code()
+ ->GetInstructionBlock(range->Start().ToInstructionIndex())
+ ->IsDeferred()) {
+ continue;
+ }
+ for (const UseInterval* i = range->first_interval(); i != nullptr;
+ i = i->next()) {
+ int first = i->FirstInstructionIndex();
+ int last = i->LastInstructionIndex();
+ for (int instr = first; instr <= last;) {
+ const InstructionBlock* block = code()->GetInstructionBlock(instr);
+ if (!block->IsDeferred()) return false;
+ instr = block->last_instruction_index() + 1;
+ }
+ }
+ }
+ return true;
+}
+
+
SpillRange* RegisterAllocationData::AssignSpillRangeToLiveRange(
TopLevelLiveRange* range) {
DCHECK(!range->HasSpillOperand());
@@ -2964,7 +2944,6 @@ void SpillSlotLocator::LocateSpillSlots() {
if (range == nullptr || range->IsEmpty()) continue;
// We care only about ranges which spill in the frame.
if (!range->HasSpillRange()) continue;
- range->MarkSpilledInDeferredBlock(data()->code());
if (range->IsSpilledOnlyInDeferredBlocks()) {
for (LiveRange* child = range; child != nullptr; child = child->next()) {
if (child->spilled()) {
« no previous file with comments | « src/compiler/register-allocator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698