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 { ...@@ -64,6 +64,7 @@ class InstructionOperand {
INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED) INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED)
#undef INSTRUCTION_OPERAND_PREDICATE #undef INSTRUCTION_OPERAND_PREDICATE
inline bool IsAnyRegister() const;
inline bool IsRegister() const; inline bool IsRegister() const;
inline bool IsDoubleRegister() const; inline bool IsDoubleRegister() const;
inline bool IsStackSlot() const; inline bool IsStackSlot() const;
...@@ -504,17 +505,20 @@ class AllocatedOperand : public LocationOperand { ...@@ -504,17 +505,20 @@ class AllocatedOperand : public LocationOperand {
#undef INSTRUCTION_OPERAND_CASTS #undef INSTRUCTION_OPERAND_CASTS
bool InstructionOperand::IsRegister() const { bool InstructionOperand::IsAnyRegister() const {
return (IsAllocated() || IsExplicit()) && return (IsAllocated() || IsExplicit()) &&
LocationOperand::cast(this)->location_kind() == LocationOperand::cast(this)->location_kind() ==
LocationOperand::REGISTER && LocationOperand::REGISTER;
}
bool InstructionOperand::IsRegister() const {
return IsAnyRegister() &&
!IsFloatingPoint(LocationOperand::cast(this)->representation()); !IsFloatingPoint(LocationOperand::cast(this)->representation());
} }
bool InstructionOperand::IsDoubleRegister() const { bool InstructionOperand::IsDoubleRegister() const {
return (IsAllocated() || IsExplicit()) && return IsAnyRegister() &&
LocationOperand::cast(this)->location_kind() ==
LocationOperand::REGISTER &&
IsFloatingPoint(LocationOperand::cast(this)->representation()); IsFloatingPoint(LocationOperand::cast(this)->representation());
} }
......
...@@ -69,9 +69,9 @@ void SplinterLiveRange(TopLevelLiveRange *range, RegisterAllocationData *data) { ...@@ -69,9 +69,9 @@ void SplinterLiveRange(TopLevelLiveRange *range, RegisterAllocationData *data) {
while (interval != nullptr) { while (interval != nullptr) {
UseInterval *next_interval = interval->next(); UseInterval *next_interval = interval->next();
const InstructionBlock *first_block = const InstructionBlock *first_block =
code->GetInstructionBlock(interval->FirstInstructionIndex()); code->GetInstructionBlock(interval->FirstGapIndex());
const InstructionBlock *last_block = const InstructionBlock *last_block =
code->GetInstructionBlock(interval->LastInstructionIndex()); code->GetInstructionBlock(interval->LastGapIndex());
int first_block_nr = first_block->rpo_number().ToInt(); int first_block_nr = first_block->rpo_number().ToInt();
int last_block_nr = last_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) { for (int block_id = first_block_nr; block_id <= last_block_nr; ++block_id) {
...@@ -110,7 +110,7 @@ void LiveRangeSeparator::Splinter() { ...@@ -110,7 +110,7 @@ void LiveRangeSeparator::Splinter() {
if (range == nullptr || range->IsEmpty() || range->IsSplinter()) { if (range == nullptr || range->IsEmpty() || range->IsSplinter()) {
continue; continue;
} }
int first_instr = range->first_interval()->FirstInstructionIndex(); int first_instr = range->first_interval()->FirstGapIndex();
if (!data()->code()->GetInstructionBlock(first_instr)->IsDeferred()) { if (!data()->code()->GetInstructionBlock(first_instr)->IsDeferred()) {
SplinterLiveRange(range, data()); SplinterLiveRange(range, data());
} }
......
...@@ -1426,8 +1426,8 @@ bool RegisterAllocationData::RangesDefinedInDeferredStayInDeferred() { ...@@ -1426,8 +1426,8 @@ bool RegisterAllocationData::RangesDefinedInDeferredStayInDeferred() {
} }
for (const UseInterval* i = range->first_interval(); i != nullptr; for (const UseInterval* i = range->first_interval(); i != nullptr;
i = i->next()) { i = i->next()) {
int first = i->FirstInstructionIndex(); int first = i->FirstGapIndex();
int last = i->LastInstructionIndex(); int last = i->LastGapIndex();
for (int instr = first; instr <= last;) { for (int instr = first; instr <= last;) {
const InstructionBlock* block = code()->GetInstructionBlock(instr); const InstructionBlock* block = code()->GetInstructionBlock(instr);
if (!block->IsDeferred()) return false; if (!block->IsDeferred()) return false;
...@@ -3383,7 +3383,12 @@ void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) { ...@@ -3383,7 +3383,12 @@ void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) {
InstructionOperand pred_op = result.pred_cover_->GetAssignedOperand(); InstructionOperand pred_op = result.pred_cover_->GetAssignedOperand();
InstructionOperand cur_op = result.cur_cover_->GetAssignedOperand(); InstructionOperand cur_op = result.cur_cover_->GetAssignedOperand();
if (pred_op.Equals(cur_op)) continue; 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(); iterator.Advance();
} }
...@@ -3391,7 +3396,7 @@ void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) { ...@@ -3391,7 +3396,7 @@ void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) {
} }
void LiveRangeConnector::ResolveControlFlow(const InstructionBlock* block, int LiveRangeConnector::ResolveControlFlow(const InstructionBlock* block,
const InstructionOperand& cur_op, const InstructionOperand& cur_op,
const InstructionBlock* pred, const InstructionBlock* pred,
const InstructionOperand& pred_op) { const InstructionOperand& pred_op) {
...@@ -3410,6 +3415,7 @@ void LiveRangeConnector::ResolveControlFlow(const InstructionBlock* block, ...@@ -3410,6 +3415,7 @@ void LiveRangeConnector::ResolveControlFlow(const InstructionBlock* block,
position = Instruction::END; position = Instruction::END;
} }
data()->AddGapMove(gap_index, position, pred_op, cur_op); data()->AddGapMove(gap_index, position, pred_op, cur_op);
return gap_index;
} }
...@@ -3446,6 +3452,13 @@ void LiveRangeConnector::ConnectRanges(Zone* local_zone) { ...@@ -3446,6 +3452,13 @@ void LiveRangeConnector::ConnectRanges(Zone* local_zone) {
} }
gap_pos = delay_insertion ? Instruction::END : Instruction::START; 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 = ParallelMove* move =
code()->InstructionAt(gap_index)->GetOrCreateParallelMove( code()->InstructionAt(gap_index)->GetOrCreateParallelMove(
gap_pos, code_zone()); gap_pos, code_zone());
......
...@@ -196,17 +196,19 @@ class UseInterval final : public ZoneObject { ...@@ -196,17 +196,19 @@ class UseInterval final : public ZoneObject {
return start_ <= point && point < end_; 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(); int ret = start_.ToInstructionIndex();
if (start_.IsInstructionPosition() && start_.IsEnd()) { if (start_.IsInstructionPosition()) {
++ret; ++ret;
} }
return ret; return ret;
} }
int LastInstructionIndex() const { // Returns the index of the last gap covered by this interval.
int LastGapIndex() const {
int ret = end_.ToInstructionIndex(); int ret = end_.ToInstructionIndex();
if (end_.IsGapPosition() || end_.IsStart()) { if (end_.IsGapPosition() && end_.IsStart()) {
--ret; --ret;
} }
return ret; return ret;
...@@ -1150,7 +1152,7 @@ class LiveRangeConnector final : public ZoneObject { ...@@ -1150,7 +1152,7 @@ class LiveRangeConnector final : public ZoneObject {
bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const; bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const;
void ResolveControlFlow(const InstructionBlock* block, int ResolveControlFlow(const InstructionBlock* block,
const InstructionOperand& cur_op, const InstructionOperand& cur_op,
const InstructionBlock* pred, const InstructionBlock* pred,
const InstructionOperand& pred_op); const InstructionOperand& pred_op);
......
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