Commit 12361e72 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[Liftoff] Remove Get{Unary,Binary}OpTargetRegister

The idea of GetUnaryOpTargetRegister and GetBinaryOpTargetRegister is
to reuse the register of one of the operands instead of using an
separate third one, because we can often generate better code if the
destination register matches the src or lhs.
This was implemented by looking at the top or the first two stack
entries, and using one of their registers if there is only one use.
Instead of doing that we can also just pop them and then later check
whether this was the only use. This makes the code smaller, more
readable and probably faster.

R=titzer@chromium.org

Bug: v8:6600
Change-Id: Ia5d9e320bdb3add5032400455a64a0c7fee77cbd
Reviewed-on: https://chromium-review.googlesource.com/950947Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51770}
parent 75d19b5b
...@@ -346,31 +346,6 @@ LiftoffAssembler::~LiftoffAssembler() { ...@@ -346,31 +346,6 @@ LiftoffAssembler::~LiftoffAssembler() {
} }
} }
LiftoffRegister LiftoffAssembler::GetBinaryOpTargetRegister(
RegClass rc, LiftoffRegList pinned) {
auto& slot_lhs = *(cache_state_.stack_state.end() - 2);
if (slot_lhs.is_reg() && GetNumUses(slot_lhs.reg()) == 1) {
DCHECK_EQ(rc, slot_lhs.reg().reg_class());
return slot_lhs.reg();
}
auto& slot_rhs = *(cache_state_.stack_state.end() - 1);
if (slot_rhs.is_reg() && GetNumUses(slot_rhs.reg()) == 1) {
DCHECK_EQ(rc, slot_rhs.reg().reg_class());
return slot_rhs.reg();
}
return GetUnusedRegister(rc, pinned);
}
LiftoffRegister LiftoffAssembler::GetUnaryOpTargetRegister(
RegClass rc, LiftoffRegList pinned) {
auto& slot_src = cache_state_.stack_state.back();
if (slot_src.is_reg() && GetNumUses(slot_src.reg()) == 1) {
DCHECK_EQ(rc, slot_src.reg().reg_class());
return slot_src.reg();
}
return GetUnusedRegister(rc, pinned);
}
LiftoffRegister LiftoffAssembler::PopToRegister(RegClass rc, LiftoffRegister LiftoffAssembler::PopToRegister(RegClass rc,
LiftoffRegList pinned) { LiftoffRegList pinned) {
DCHECK(!cache_state_.stack_state.empty()); DCHECK(!cache_state_.stack_state.empty());
......
...@@ -246,11 +246,6 @@ class LiftoffAssembler : public TurboAssembler { ...@@ -246,11 +246,6 @@ class LiftoffAssembler : public TurboAssembler {
explicit LiftoffAssembler(Isolate* isolate); explicit LiftoffAssembler(Isolate* isolate);
~LiftoffAssembler(); ~LiftoffAssembler();
LiftoffRegister GetBinaryOpTargetRegister(RegClass,
LiftoffRegList pinned = {});
LiftoffRegister GetUnaryOpTargetRegister(RegClass,
LiftoffRegList pinned = {});
LiftoffRegister PopToRegister(RegClass, LiftoffRegList pinned = {}); LiftoffRegister PopToRegister(RegClass, LiftoffRegList pinned = {});
void PushRegister(ValueType type, LiftoffRegister reg) { void PushRegister(ValueType type, LiftoffRegister reg) {
...@@ -265,6 +260,18 @@ class LiftoffAssembler : public TurboAssembler { ...@@ -265,6 +260,18 @@ class LiftoffAssembler : public TurboAssembler {
return cache_state_.get_use_count(reg); return cache_state_.get_use_count(reg);
} }
// Get an unused register for class {rc}, reusing one of {try_first} if
// possible.
LiftoffRegister GetUnusedRegister(
RegClass rc, std::initializer_list<LiftoffRegister> try_first,
LiftoffRegList pinned = {}) {
for (LiftoffRegister reg : try_first) {
DCHECK_EQ(reg.reg_class(), rc);
if (cache_state_.is_free(reg)) return reg;
}
return GetUnusedRegister(rc, pinned);
}
// Get an unused register for class {rc}, potentially spilling to free one. // Get an unused register for class {rc}, potentially spilling to free one.
LiftoffRegister GetUnusedRegister(RegClass rc, LiftoffRegList pinned = {}) { LiftoffRegister GetUnusedRegister(RegClass rc, LiftoffRegList pinned = {}) {
if (kNeedI64RegPair && rc == kGpRegPair) { if (kNeedI64RegPair && rc == kGpRegPair) {
......
...@@ -516,8 +516,8 @@ class LiftoffCompiler { ...@@ -516,8 +516,8 @@ class LiftoffCompiler {
void EmitUnOp(EmitFn fn) { void EmitUnOp(EmitFn fn) {
static RegClass rc = reg_class_for(type); static RegClass rc = reg_class_for(type);
LiftoffRegList pinned; LiftoffRegList pinned;
LiftoffRegister dst = pinned.set(__ GetUnaryOpTargetRegister(rc)); LiftoffRegister src = pinned.set(__ PopToRegister(rc, pinned));
LiftoffRegister src = __ PopToRegister(rc, pinned); LiftoffRegister dst = __ GetUnusedRegister(rc, {src}, pinned);
fn(dst, src); fn(dst, src);
__ PushRegister(type, dst); __ PushRegister(type, dst);
} }
...@@ -575,9 +575,9 @@ class LiftoffCompiler { ...@@ -575,9 +575,9 @@ class LiftoffCompiler {
void EmitMonomorphicBinOp(EmitFn fn) { void EmitMonomorphicBinOp(EmitFn fn) {
static constexpr RegClass rc = reg_class_for(type); static constexpr RegClass rc = reg_class_for(type);
LiftoffRegList pinned; LiftoffRegList pinned;
LiftoffRegister dst = pinned.set(__ GetBinaryOpTargetRegister(rc));
LiftoffRegister rhs = pinned.set(__ PopToRegister(rc, pinned)); LiftoffRegister rhs = pinned.set(__ PopToRegister(rc, pinned));
LiftoffRegister lhs = __ PopToRegister(rc, pinned); LiftoffRegister lhs = pinned.set(__ PopToRegister(rc, pinned));
LiftoffRegister dst = __ GetUnusedRegister(rc, {lhs, rhs}, pinned);
fn(dst, lhs, rhs); fn(dst, lhs, rhs);
__ PushRegister(type, dst); __ PushRegister(type, dst);
} }
......
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