Commit 83683e92 authored by mtrofin's avatar mtrofin Committed by Commit bot

[turbofan] Splinter when range ends at hot block start

We were sometimes losing a splintering opportunity when a range was
ending at the beginning of a hot (==non-deferred) block, when giving
its value to some fixed range - i.e. a fixed operand of the first instruction
in that hot block.

Renamed 2 APIs to better reflect what their intent is.

Added self-checking when introducing moves connecting ranges, to
ensure we don't spill/fill in hot blocks ranges spilled only in deferred
blocks. Verified locally that these checks would have tripped in a few
cases before this change.

BUG=

Review URL: https://codereview.chromium.org/1564583002

Cr-Commit-Position: refs/heads/master@{#33301}
parent 2b90397d
......@@ -64,6 +64,7 @@ class InstructionOperand {
INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED)
#undef INSTRUCTION_OPERAND_PREDICATE
inline bool IsAnyRegister() const;
inline bool IsRegister() const;
inline bool IsDoubleRegister() const;
inline bool IsStackSlot() const;
......@@ -504,17 +505,20 @@ class AllocatedOperand : public LocationOperand {
#undef INSTRUCTION_OPERAND_CASTS
bool InstructionOperand::IsRegister() const {
bool InstructionOperand::IsAnyRegister() const {
return (IsAllocated() || IsExplicit()) &&
LocationOperand::cast(this)->location_kind() ==
LocationOperand::REGISTER &&
LocationOperand::REGISTER;
}
bool InstructionOperand::IsRegister() const {
return IsAnyRegister() &&
!IsFloatingPoint(LocationOperand::cast(this)->representation());
}
bool InstructionOperand::IsDoubleRegister() const {
return (IsAllocated() || IsExplicit()) &&
LocationOperand::cast(this)->location_kind() ==
LocationOperand::REGISTER &&
return IsAnyRegister() &&
IsFloatingPoint(LocationOperand::cast(this)->representation());
}
......
......@@ -69,9 +69,9 @@ void SplinterLiveRange(TopLevelLiveRange *range, RegisterAllocationData *data) {
while (interval != nullptr) {
UseInterval *next_interval = interval->next();
const InstructionBlock *first_block =
code->GetInstructionBlock(interval->FirstInstructionIndex());
code->GetInstructionBlock(interval->FirstGapIndex());
const InstructionBlock *last_block =
code->GetInstructionBlock(interval->LastInstructionIndex());
code->GetInstructionBlock(interval->LastGapIndex());
int first_block_nr = first_block->rpo_number().ToInt();
int last_block_nr = last_block->rpo_number().ToInt();
for (int block_id = first_block_nr; block_id <= last_block_nr; ++block_id) {
......@@ -110,7 +110,7 @@ void LiveRangeSeparator::Splinter() {
if (range == nullptr || range->IsEmpty() || range->IsSplinter()) {
continue;
}
int first_instr = range->first_interval()->FirstInstructionIndex();
int first_instr = range->first_interval()->FirstGapIndex();
if (!data()->code()->GetInstructionBlock(first_instr)->IsDeferred()) {
SplinterLiveRange(range, data());
}
......
......@@ -1426,8 +1426,8 @@ bool RegisterAllocationData::RangesDefinedInDeferredStayInDeferred() {
}
for (const UseInterval* i = range->first_interval(); i != nullptr;
i = i->next()) {
int first = i->FirstInstructionIndex();
int last = i->LastInstructionIndex();
int first = i->FirstGapIndex();
int last = i->LastGapIndex();
for (int instr = first; instr <= last;) {
const InstructionBlock* block = code()->GetInstructionBlock(instr);
if (!block->IsDeferred()) return false;
......@@ -3383,7 +3383,12 @@ void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) {
InstructionOperand pred_op = result.pred_cover_->GetAssignedOperand();
InstructionOperand cur_op = result.cur_cover_->GetAssignedOperand();
if (pred_op.Equals(cur_op)) continue;
ResolveControlFlow(block, cur_op, pred_block, pred_op);
int move_loc = ResolveControlFlow(block, cur_op, pred_block, pred_op);
USE(move_loc);
DCHECK_IMPLIES(
result.cur_cover_->TopLevel()->IsSpilledOnlyInDeferredBlocks() &&
!(pred_op.IsAnyRegister() && cur_op.IsAnyRegister()),
code()->GetInstructionBlock(move_loc)->IsDeferred());
}
iterator.Advance();
}
......@@ -3391,10 +3396,10 @@ void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) {
}
void LiveRangeConnector::ResolveControlFlow(const InstructionBlock* block,
const InstructionOperand& cur_op,
const InstructionBlock* pred,
const InstructionOperand& pred_op) {
int LiveRangeConnector::ResolveControlFlow(const InstructionBlock* block,
const InstructionOperand& cur_op,
const InstructionBlock* pred,
const InstructionOperand& pred_op) {
DCHECK(!pred_op.Equals(cur_op));
int gap_index;
Instruction::GapPosition position;
......@@ -3410,6 +3415,7 @@ void LiveRangeConnector::ResolveControlFlow(const InstructionBlock* block,
position = Instruction::END;
}
data()->AddGapMove(gap_index, position, pred_op, cur_op);
return gap_index;
}
......@@ -3446,6 +3452,13 @@ void LiveRangeConnector::ConnectRanges(Zone* local_zone) {
}
gap_pos = delay_insertion ? Instruction::END : Instruction::START;
}
// Fills or spills for spilled in deferred blocks ranges must happen
// only in deferred blocks.
DCHECK_IMPLIES(
connect_spilled &&
!(prev_operand.IsAnyRegister() && cur_operand.IsAnyRegister()),
code()->GetInstructionBlock(gap_index)->IsDeferred());
ParallelMove* move =
code()->InstructionAt(gap_index)->GetOrCreateParallelMove(
gap_pos, code_zone());
......
......@@ -196,17 +196,19 @@ class UseInterval final : public ZoneObject {
return start_ <= point && point < end_;
}
int FirstInstructionIndex() const {
// Returns the index of the first gap covered by this interval.
int FirstGapIndex() const {
int ret = start_.ToInstructionIndex();
if (start_.IsInstructionPosition() && start_.IsEnd()) {
if (start_.IsInstructionPosition()) {
++ret;
}
return ret;
}
int LastInstructionIndex() const {
// Returns the index of the last gap covered by this interval.
int LastGapIndex() const {
int ret = end_.ToInstructionIndex();
if (end_.IsGapPosition() || end_.IsStart()) {
if (end_.IsGapPosition() && end_.IsStart()) {
--ret;
}
return ret;
......@@ -1150,10 +1152,10 @@ class LiveRangeConnector final : public ZoneObject {
bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const;
void ResolveControlFlow(const InstructionBlock* block,
const InstructionOperand& cur_op,
const InstructionBlock* pred,
const InstructionOperand& pred_op);
int ResolveControlFlow(const InstructionBlock* block,
const InstructionOperand& cur_op,
const InstructionBlock* pred,
const InstructionOperand& pred_op);
RegisterAllocationData* const data_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment