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

[compiler] Share liveness across straight-line bytecode

Straight-line bytecode with exactly one "next" bytecode (i.e. everything
that can't affect control flow) will always have the same "out" liveness
as the next bytecode's "in" liveness. For those cases, we can save a bit
of time and memory by aliasing the pointers between the bytecode's out
liveness and the next bytecode's in liveness, and skipping copying
between them.

This is done by specializing the current liveness update on whether this
is the first pass (which will allocate and initialize the liveness
bitvectors) or an update pass (which will revisit loops to collect
liveness crossing over the back-edge, and propagate this liveness
through the loop bodies). On the first pass, we can delay allocation of
the out liveness until we know it needs to be union of multiple in
livenesses, and on the update pass we can skip it if it is an alias.

As a drive-by, tweak BitVector::CopyFrom to require copying from a
vector with the same size (same as Union or Intersect), and move the
only different sized vector use (in Resize) to be inline.

Change-Id: Iad1b2e1b927a37ad925ef68e2a224152aaa2ba18
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3350452
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78425}
parent aeec6e1b
This diff is collapsed.
......@@ -8,10 +8,6 @@ namespace v8 {
namespace internal {
namespace compiler {
BytecodeLiveness::BytecodeLiveness(int register_count, Zone* zone)
: in(zone->New<BytecodeLivenessState>(register_count, zone)),
out(zone->New<BytecodeLivenessState>(register_count, zone)) {}
BytecodeLivenessMap::BytecodeLivenessMap(int bytecode_size, Zone* zone)
: liveness_map_(base::bits::RoundUpToPowerOfTwo32(bytecode_size / 4 + 1),
base::KeyEqualityMatcher<int>(),
......@@ -19,13 +15,8 @@ BytecodeLivenessMap::BytecodeLivenessMap(int bytecode_size, Zone* zone)
uint32_t OffsetHash(int offset) { return offset; }
BytecodeLiveness& BytecodeLivenessMap::InitializeLiveness(int offset,
int register_count,
Zone* zone) {
return liveness_map_
.LookupOrInsert(offset, OffsetHash(offset),
[&]() { return BytecodeLiveness(register_count, zone); })
->value;
BytecodeLiveness& BytecodeLivenessMap::InsertNewLiveness(int offset) {
return liveness_map_.LookupOrInsert(offset, OffsetHash(offset))->value;
}
BytecodeLiveness& BytecodeLivenessMap::GetLiveness(int offset) {
......
......@@ -23,6 +23,9 @@ class BytecodeLivenessState : public ZoneObject {
BytecodeLivenessState(const BytecodeLivenessState&) = delete;
BytecodeLivenessState& operator=(const BytecodeLivenessState&) = delete;
BytecodeLivenessState(const BytecodeLivenessState& other, Zone* zone)
: bit_vector_(other.bit_vector_, zone) {}
const BitVector& bit_vector() const { return bit_vector_; }
BitVector& bit_vector() { return bit_vector_; }
......@@ -78,16 +81,13 @@ class BytecodeLivenessState : public ZoneObject {
struct BytecodeLiveness {
BytecodeLivenessState* in;
BytecodeLivenessState* out;
BytecodeLiveness(int register_count, Zone* zone);
};
class V8_EXPORT_PRIVATE BytecodeLivenessMap {
public:
BytecodeLivenessMap(int size, Zone* zone);
BytecodeLiveness& InitializeLiveness(int offset, int register_count,
Zone* zone);
BytecodeLiveness& InsertNewLiveness(int offset);
BytecodeLiveness& GetLiveness(int offset);
const BytecodeLiveness& GetLiveness(int offset) const;
......
......@@ -18,7 +18,7 @@ class V8_EXPORT_PRIVATE BitVector : public ZoneObject {
uintptr_t* ptr_; // valid if data_length_ > 1
uintptr_t inline_; // valid if data_length_ == 1
DataStorage(uintptr_t value) : inline_(value) {}
explicit DataStorage(uintptr_t value) : inline_(value) {}
};
// Iterator for the elements of this BitVector.
......@@ -111,8 +111,15 @@ class V8_EXPORT_PRIVATE BitVector : public ZoneObject {
}
void CopyFrom(const BitVector& other) {
DCHECK_LE(other.length(), length());
CopyFrom(other.data_, other.data_length_);
DCHECK_EQ(other.length(), length());
if (is_inline()) {
DCHECK(other.is_inline());
data_.inline_ = other.data_.inline_;
} else {
for (int i = 0; i < data_length_; i++) {
data_.ptr_[i] = other.data_.ptr_[i];
}
}
}
void Resize(int new_length, Zone* zone) {
......@@ -126,7 +133,19 @@ class V8_EXPORT_PRIVATE BitVector : public ZoneObject {
DCHECK_GT(new_data_length, kDataLengthForInline);
data_.ptr_ = zone->NewArray<uintptr_t>(new_data_length);
data_length_ = new_data_length;
CopyFrom(old_data, old_data_length);
// Copy over the data.
if (old_data_length == kDataLengthForInline) {
data_.ptr_[0] = old_data.inline_;
} else {
for (int i = 0; i < old_data_length; i++) {
data_.ptr_[i] = old_data.ptr_[i];
}
}
// Zero out the rest of the data.
for (int i = old_data_length; i < data_length_; i++) {
data_.ptr_[i] = 0;
}
}
length_ = new_length;
}
......@@ -288,27 +307,6 @@ class V8_EXPORT_PRIVATE BitVector : public ZoneObject {
DataStorage data_;
bool is_inline() const { return data_length_ == kDataLengthForInline; }
void CopyFrom(DataStorage other_data, int other_data_length) {
DCHECK_LE(other_data_length, data_length_);
if (is_inline()) {
DCHECK_EQ(other_data_length, kDataLengthForInline);
data_.inline_ = other_data.inline_;
} else if (other_data_length == kDataLengthForInline) {
data_.ptr_[0] = other_data.inline_;
for (int i = 1; i < data_length_; i++) {
data_.ptr_[i] = 0;
}
} else {
for (int i = 0; i < other_data_length; i++) {
data_.ptr_[i] = other_data.ptr_[i];
}
for (int i = other_data_length; i < data_length_; i++) {
data_.ptr_[i] = 0;
}
}
}
};
class GrowableBitVector {
......
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