Commit 0bcfb26e authored by mtrofin's avatar mtrofin Committed by Commit bot

[turbofan] reduce ResolveControlFlow overhead.

I found this optimization opportunity when analyzing some pathological
compile-time examples. When tying together live ranges across control
flow boundaries, we used to repeatedly check if the top level range was
spilled in deferred blocks or not. This proved to be a hotspot in such
cases (i.e. the pathological compile time ones).

Because the analysis needs to progress block by block and not live range by live range, we cannot feasibly save per-range information to
remove the hotspot. Instead, we save this information when
constructing LiveRangeBounds.

The result is 2.5 to 7% improvement in the pathological cases, and a few
similar bonuses in perf in a couple of other benchmarks.

Also, opportunistically removed the loop counting the number of child
ranges, since we have that count from the new (post - refactoring)
range numbering technique.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#32071}
parent 3e328bf2
...@@ -3174,8 +3174,8 @@ namespace { ...@@ -3174,8 +3174,8 @@ namespace {
class LiveRangeBound { class LiveRangeBound {
public: public:
explicit LiveRangeBound(const LiveRange* range) explicit LiveRangeBound(const LiveRange* range, bool skip)
: range_(range), start_(range->Start()), end_(range->End()) { : range_(range), start_(range->Start()), end_(range->End()), skip_(skip) {
DCHECK(!range->IsEmpty()); DCHECK(!range->IsEmpty());
} }
...@@ -3186,6 +3186,7 @@ class LiveRangeBound { ...@@ -3186,6 +3186,7 @@ class LiveRangeBound {
const LiveRange* const range_; const LiveRange* const range_;
const LifetimePosition start_; const LifetimePosition start_;
const LifetimePosition end_; const LifetimePosition end_;
const bool skip_;
private: private:
DISALLOW_COPY_AND_ASSIGN(LiveRangeBound); DISALLOW_COPY_AND_ASSIGN(LiveRangeBound);
...@@ -3204,14 +3205,17 @@ class LiveRangeBoundArray { ...@@ -3204,14 +3205,17 @@ class LiveRangeBoundArray {
bool ShouldInitialize() { return start_ == nullptr; } bool ShouldInitialize() { return start_ == nullptr; }
void Initialize(Zone* zone, const LiveRange* const range) { void Initialize(Zone* zone, const TopLevelLiveRange* const range) {
size_t length = 0; length_ = range->GetChildCount();
for (auto i = range; i != nullptr; i = i->next()) length++;
start_ = zone->NewArray<LiveRangeBound>(length); start_ = zone->NewArray<LiveRangeBound>(length_);
length_ = length; LiveRangeBound* curr = start_;
auto curr = start_; // Normally, spilled ranges do not need connecting moves, because the spill
for (auto i = range; i != nullptr; i = i->next(), ++curr) { // location has been assigned at definition. For ranges spilled in deferred
new (curr) LiveRangeBound(i); // blocks, that is not the case, so we need to connect the spilled children.
bool spilled_in_blocks = range->IsSpilledOnlyInDeferredBlocks();
for (const LiveRange *i = range; i != nullptr; i = i->next(), ++curr) {
new (curr) LiveRangeBound(i, !spilled_in_blocks && i->spilled());
} }
} }
...@@ -3244,21 +3248,29 @@ class LiveRangeBoundArray { ...@@ -3244,21 +3248,29 @@ class LiveRangeBoundArray {
return Find(succ_start); return Find(succ_start);
} }
void Find(const InstructionBlock* block, const InstructionBlock* pred, bool FindConnectableSubranges(const InstructionBlock* block,
const InstructionBlock* pred,
FindResult* result) const { FindResult* result) const {
auto pred_end = LifetimePosition::InstructionFromInstructionIndex( LifetimePosition pred_end =
LifetimePosition::InstructionFromInstructionIndex(
pred->last_instruction_index()); pred->last_instruction_index());
auto bound = Find(pred_end); LiveRangeBound* bound = Find(pred_end);
result->pred_cover_ = bound->range_; result->pred_cover_ = bound->range_;
auto cur_start = LifetimePosition::GapFromInstructionIndex( LifetimePosition cur_start = LifetimePosition::GapFromInstructionIndex(
block->first_instruction_index()); block->first_instruction_index());
// Common case.
if (bound->CanCover(cur_start)) { if (bound->CanCover(cur_start)) {
result->cur_cover_ = bound->range_; // Both blocks are covered by the same range, so there is nothing to
return; // connect.
return false;
}
bound = Find(cur_start);
if (bound->skip_) {
return false;
} }
result->cur_cover_ = Find(cur_start)->range_; result->cur_cover_ = bound->range_;
DCHECK(result->pred_cover_ != nullptr && result->cur_cover_ != nullptr); DCHECK(result->pred_cover_ != nullptr && result->cur_cover_ != nullptr);
return (result->cur_cover_ != result->pred_cover_);
} }
private: private:
...@@ -3346,11 +3358,9 @@ void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) { ...@@ -3346,11 +3358,9 @@ void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) {
for (auto pred : block->predecessors()) { for (auto pred : block->predecessors()) {
FindResult result; FindResult result;
const auto* pred_block = code()->InstructionBlockAt(pred); const auto* pred_block = code()->InstructionBlockAt(pred);
array->Find(block, pred_block, &result); if (!array->FindConnectableSubranges(block, pred_block, &result)) {
if (result.cur_cover_ == result.pred_cover_ ||
(!result.cur_cover_->TopLevel()->IsSpilledOnlyInDeferredBlocks() &&
result.cur_cover_->spilled()))
continue; continue;
}
auto pred_op = result.pred_cover_->GetAssignedOperand(); auto pred_op = result.pred_cover_->GetAssignedOperand();
auto cur_op = result.cur_cover_->GetAssignedOperand(); auto cur_op = result.cur_cover_->GetAssignedOperand();
if (pred_op.Equals(cur_op)) continue; if (pred_op.Equals(cur_op)) continue;
......
...@@ -572,6 +572,8 @@ class TopLevelLiveRange final : public LiveRange { ...@@ -572,6 +572,8 @@ class TopLevelLiveRange final : public LiveRange {
: ++last_child_id_; : ++last_child_id_;
} }
int GetChildCount() const { return last_child_id_ + 1; }
bool IsSpilledOnlyInDeferredBlocks() const { bool IsSpilledOnlyInDeferredBlocks() const {
return spilled_in_deferred_blocks_; return spilled_in_deferred_blocks_;
} }
......
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