Commit c7aef552 authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[maglev] Fix dead fallthrough merging

Add a method which optionally merges dead fallthrough paths, in case the
iteration in EmitUnconditionalDeopt reaches a merge point that is live
from another jump but dead on the fallthrough.

Bug: v8:7700
Change-Id: Ie505cd5356fcf70208f2f6d3e52b805956485f74
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3663086
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80878}
parent c6527293
......@@ -151,6 +151,10 @@ class MaglevGraphBuilder {
// Loops that are unreachable aside from their back-edge are going to
// be entirely unreachable, thanks to irreducibility.
if (!merge_states_[iterator_.current_offset()]->is_unreachable_loop()) {
// We might be falling through into this merge state, so merge in that
// fallthrough as dead, if necessary.
merge_states_[iterator_.current_offset()]->MaybeMergeDeadFallthrough(
*compilation_unit_, iterator_.current_offset());
break;
}
}
......
......@@ -325,6 +325,18 @@ class MergePointInterpreterFrameState {
});
}
// Merges a dead fallthrough framestate (e.g. one which has been early
// terminated with a deopt), if that merge is needed. It is needed when there
// is exactly one missing predecessor.
void MaybeMergeDeadFallthrough(const MaglevCompilationUnit& compilation_unit,
int merge_offset) {
// We've seen all predecessors, so we're good.
if (predecessors_so_far_ == predecessor_count_) return;
// Otherwise exactly one should be missing.
DCHECK_EQ(predecessors_so_far_, predecessor_count_ - 1);
MergeDead(compilation_unit, merge_offset);
}
// Merges a dead loop framestate (e.g. one where the block containing the
// JumpLoop has been early terminated with a deopt).
void MergeDeadLoop() {
......@@ -356,7 +368,10 @@ class MergePointInterpreterFrameState {
}
bool is_unreachable_loop() const {
DCHECK_EQ(predecessors_so_far_, predecessor_count_);
// We should have either merged or removed all predecessors, except maybe
// the fallthrough.
DCHECK_GE(predecessors_so_far_, predecessor_count_ - 1);
DCHECK_LE(predecessors_so_far_, predecessor_count_);
// If there is only one predecessor, and it's not set, then this is a loop
// merge with no forward control flow entering it.
return predecessor_count_ == 1 &&
......
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