Commit f7f7cd2e authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[Liftoff] Allow more register reuse

For binary operations and unary operations, we were pinning too many
registers, thereby disallowing to reuse a src register for the result.

R=ahaas@chromium.org

Bug: v8:6600
Change-Id: Id4eea1e35d29c170e191249ef42d11ed1d284490
Reviewed-on: https://chromium-review.googlesource.com/1021818Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52720}
parent 8da9631b
......@@ -588,13 +588,26 @@ template <void (LiftoffAssembler::*op)(Register, Register, Register)>
void EmitI64IndependentHalfOperation(LiftoffAssembler* assm,
LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs) {
// Register pairs are either the same, or they don't overlap at all, so the
// low and high registers must be disjoint. Just handle them separately.
DCHECK_EQ(LiftoffRegList{},
LiftoffRegList::ForRegs(dst.low(), lhs.low(), rhs.low()) &
LiftoffRegList::ForRegs(dst.high(), lhs.high(), rhs.high()));
(assm->*op)(dst.low_gp(), lhs.low_gp(), rhs.low_gp());
// If {dst.low_gp()} does not overlap with {lhs.high_gp()} or {rhs.high_gp()},
// just first compute the lower half, then the upper half.
if (dst.low() != lhs.high() && dst.low() != rhs.high()) {
(assm->*op)(dst.low_gp(), lhs.low_gp(), rhs.low_gp());
(assm->*op)(dst.high_gp(), lhs.high_gp(), rhs.high_gp());
return;
}
// If {dst.high_gp()} does not overlap with {lhs.low_gp()} or {rhs.low_gp()},
// we can compute this the other way around.
if (dst.high() != lhs.low() && dst.high() != rhs.low()) {
(assm->*op)(dst.high_gp(), lhs.high_gp(), rhs.high_gp());
(assm->*op)(dst.low_gp(), lhs.low_gp(), rhs.low_gp());
return;
}
// Otherwise, we need a temporary register.
Register tmp =
assm->GetUnusedRegister(kGpReg, LiftoffRegList::ForRegs(lhs, rhs)).gp();
(assm->*op)(tmp, lhs.low_gp(), rhs.low_gp());
(assm->*op)(dst.high_gp(), lhs.high_gp(), rhs.high_gp());
assm->Move(dst.low_gp(), tmp, kWasmI32);
}
} // namespace liftoff
......
......@@ -592,11 +592,10 @@ class LiftoffCompiler {
void EmitUnOp(EmitFn fn) {
static RegClass src_rc = reg_class_for(src_type);
static RegClass result_rc = reg_class_for(result_type);
LiftoffRegList pinned;
LiftoffRegister src = pinned.set(__ PopToRegister(pinned));
LiftoffRegister src = __ PopToRegister();
LiftoffRegister dst = src_rc == result_rc
? __ GetUnusedRegister(result_rc, {src}, pinned)
: __ GetUnusedRegister(result_rc, pinned);
? __ GetUnusedRegister(result_rc, {src})
: __ GetUnusedRegister(result_rc);
fn(dst, src);
__ PushRegister(result_type, dst);
}
......@@ -622,11 +621,9 @@ class LiftoffCompiler {
wasm::WasmCodePosition trap_position) {
static constexpr RegClass src_rc = reg_class_for(src_type);
static constexpr RegClass dst_rc = reg_class_for(dst_type);
LiftoffRegList pinned;
LiftoffRegister src = pinned.set(__ PopToRegister());
LiftoffRegister dst = pinned.set(
src_rc == dst_rc ? __ GetUnusedRegister(dst_rc, {src}, pinned)
: __ GetUnusedRegister(dst_rc, pinned));
LiftoffRegister src = __ PopToRegister();
LiftoffRegister dst = src_rc == dst_rc ? __ GetUnusedRegister(dst_rc, {src})
: __ GetUnusedRegister(dst_rc);
DCHECK_EQ(can_trap, trap_position > 0);
Label* trap = can_trap ? AddOutOfLineTrap(
trap_position,
......@@ -639,7 +636,8 @@ class LiftoffCompiler {
// External references for potentially trapping conversions return int.
ValueType sig_reps[] = {kWasmI32, src_type};
FunctionSig sig(1, 1, sig_reps);
LiftoffRegister ret_reg = __ GetUnusedRegister(kGpReg, pinned);
LiftoffRegister ret_reg =
__ GetUnusedRegister(kGpReg, LiftoffRegList::ForRegs(dst));
LiftoffRegister dst_regs[] = {ret_reg, dst};
GenerateCCall(dst_regs, &sig, dst_type, &src, ext_ref);
__ emit_cond_jump(kEqual, trap, kWasmI32, ret_reg.gp());
......@@ -746,13 +744,11 @@ class LiftoffCompiler {
void EmitBinOp(EmitFn fn) {
static constexpr RegClass src_rc = reg_class_for(src_type);
static constexpr RegClass result_rc = reg_class_for(result_type);
LiftoffRegList pinned;
LiftoffRegister rhs = pinned.set(__ PopToRegister(pinned));
LiftoffRegister lhs = pinned.set(__ PopToRegister(pinned));
LiftoffRegister dst =
src_rc == result_rc
? __ GetUnusedRegister(result_rc, {lhs, rhs}, pinned)
: __ GetUnusedRegister(result_rc);
LiftoffRegister rhs = __ PopToRegister();
LiftoffRegister lhs = __ PopToRegister(LiftoffRegList::ForRegs(rhs));
LiftoffRegister dst = src_rc == result_rc
? __ GetUnusedRegister(result_rc, {lhs, rhs})
: __ GetUnusedRegister(result_rc);
fn(dst, lhs, rhs);
__ PushRegister(result_type, dst);
}
......
......@@ -316,6 +316,16 @@ static constexpr LiftoffRegList GetCacheRegList(RegClass rc) {
return rc == kGpReg ? kGpCacheRegList : kFpCacheRegList;
}
inline std::ostream& operator<<(std::ostream& os, LiftoffRegList reglist) {
os << "{";
for (bool first = true; !reglist.is_empty(); first = false) {
LiftoffRegister reg = reglist.GetFirstRegSet();
reglist.clear(reg);
os << (first ? "" : ", ") << reg;
}
return os << "}";
}
} // namespace wasm
} // namespace internal
} // namespace v8
......
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