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)> ...@@ -588,13 +588,26 @@ template <void (LiftoffAssembler::*op)(Register, Register, Register)>
void EmitI64IndependentHalfOperation(LiftoffAssembler* assm, void EmitI64IndependentHalfOperation(LiftoffAssembler* assm,
LiftoffRegister dst, LiftoffRegister lhs, LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs) { LiftoffRegister rhs) {
// Register pairs are either the same, or they don't overlap at all, so the // If {dst.low_gp()} does not overlap with {lhs.high_gp()} or {rhs.high_gp()},
// low and high registers must be disjoint. Just handle them separately. // just first compute the lower half, then the upper half.
DCHECK_EQ(LiftoffRegList{}, if (dst.low() != lhs.high() && dst.low() != rhs.high()) {
LiftoffRegList::ForRegs(dst.low(), lhs.low(), rhs.low()) & (assm->*op)(dst.low_gp(), lhs.low_gp(), rhs.low_gp());
LiftoffRegList::ForRegs(dst.high(), lhs.high(), rhs.high())); (assm->*op)(dst.high_gp(), lhs.high_gp(), rhs.high_gp());
(assm->*op)(dst.low_gp(), lhs.low_gp(), rhs.low_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->*op)(dst.high_gp(), lhs.high_gp(), rhs.high_gp());
assm->Move(dst.low_gp(), tmp, kWasmI32);
} }
} // namespace liftoff } // namespace liftoff
......
...@@ -592,11 +592,10 @@ class LiftoffCompiler { ...@@ -592,11 +592,10 @@ class LiftoffCompiler {
void EmitUnOp(EmitFn fn) { void EmitUnOp(EmitFn fn) {
static RegClass src_rc = reg_class_for(src_type); static RegClass src_rc = reg_class_for(src_type);
static RegClass result_rc = reg_class_for(result_type); static RegClass result_rc = reg_class_for(result_type);
LiftoffRegList pinned; LiftoffRegister src = __ PopToRegister();
LiftoffRegister src = pinned.set(__ PopToRegister(pinned));
LiftoffRegister dst = src_rc == result_rc LiftoffRegister dst = src_rc == result_rc
? __ GetUnusedRegister(result_rc, {src}, pinned) ? __ GetUnusedRegister(result_rc, {src})
: __ GetUnusedRegister(result_rc, pinned); : __ GetUnusedRegister(result_rc);
fn(dst, src); fn(dst, src);
__ PushRegister(result_type, dst); __ PushRegister(result_type, dst);
} }
...@@ -622,11 +621,9 @@ class LiftoffCompiler { ...@@ -622,11 +621,9 @@ class LiftoffCompiler {
wasm::WasmCodePosition trap_position) { wasm::WasmCodePosition trap_position) {
static constexpr RegClass src_rc = reg_class_for(src_type); static constexpr RegClass src_rc = reg_class_for(src_type);
static constexpr RegClass dst_rc = reg_class_for(dst_type); static constexpr RegClass dst_rc = reg_class_for(dst_type);
LiftoffRegList pinned; LiftoffRegister src = __ PopToRegister();
LiftoffRegister src = pinned.set(__ PopToRegister()); LiftoffRegister dst = src_rc == dst_rc ? __ GetUnusedRegister(dst_rc, {src})
LiftoffRegister dst = pinned.set( : __ GetUnusedRegister(dst_rc);
src_rc == dst_rc ? __ GetUnusedRegister(dst_rc, {src}, pinned)
: __ GetUnusedRegister(dst_rc, pinned));
DCHECK_EQ(can_trap, trap_position > 0); DCHECK_EQ(can_trap, trap_position > 0);
Label* trap = can_trap ? AddOutOfLineTrap( Label* trap = can_trap ? AddOutOfLineTrap(
trap_position, trap_position,
...@@ -639,7 +636,8 @@ class LiftoffCompiler { ...@@ -639,7 +636,8 @@ class LiftoffCompiler {
// External references for potentially trapping conversions return int. // External references for potentially trapping conversions return int.
ValueType sig_reps[] = {kWasmI32, src_type}; ValueType sig_reps[] = {kWasmI32, src_type};
FunctionSig sig(1, 1, sig_reps); 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}; LiftoffRegister dst_regs[] = {ret_reg, dst};
GenerateCCall(dst_regs, &sig, dst_type, &src, ext_ref); GenerateCCall(dst_regs, &sig, dst_type, &src, ext_ref);
__ emit_cond_jump(kEqual, trap, kWasmI32, ret_reg.gp()); __ emit_cond_jump(kEqual, trap, kWasmI32, ret_reg.gp());
...@@ -746,13 +744,11 @@ class LiftoffCompiler { ...@@ -746,13 +744,11 @@ class LiftoffCompiler {
void EmitBinOp(EmitFn fn) { void EmitBinOp(EmitFn fn) {
static constexpr RegClass src_rc = reg_class_for(src_type); static constexpr RegClass src_rc = reg_class_for(src_type);
static constexpr RegClass result_rc = reg_class_for(result_type); static constexpr RegClass result_rc = reg_class_for(result_type);
LiftoffRegList pinned; LiftoffRegister rhs = __ PopToRegister();
LiftoffRegister rhs = pinned.set(__ PopToRegister(pinned)); LiftoffRegister lhs = __ PopToRegister(LiftoffRegList::ForRegs(rhs));
LiftoffRegister lhs = pinned.set(__ PopToRegister(pinned)); LiftoffRegister dst = src_rc == result_rc
LiftoffRegister dst = ? __ GetUnusedRegister(result_rc, {lhs, rhs})
src_rc == result_rc : __ GetUnusedRegister(result_rc);
? __ GetUnusedRegister(result_rc, {lhs, rhs}, pinned)
: __ GetUnusedRegister(result_rc);
fn(dst, lhs, rhs); fn(dst, lhs, rhs);
__ PushRegister(result_type, dst); __ PushRegister(result_type, dst);
} }
......
...@@ -316,6 +316,16 @@ static constexpr LiftoffRegList GetCacheRegList(RegClass rc) { ...@@ -316,6 +316,16 @@ static constexpr LiftoffRegList GetCacheRegList(RegClass rc) {
return rc == kGpReg ? kGpCacheRegList : kFpCacheRegList; 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 wasm
} // namespace internal } // namespace internal
} // namespace v8 } // 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