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

[Liftoff] Refactor unops

Refactor EmitUnOp to be templatized in the type and the emit function,
similar to EmitBinOp. This simplified adding f32 and f64 unops.

R=ahaas@chromium.org

Bug: v8:6600
Change-Id: Iaab473a3bbcc45673ff6190d6b56244c48bfa5a6
Reviewed-on: https://chromium-review.googlesource.com/937201
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51568}
parent 087e9daa
...@@ -512,45 +512,52 @@ class LiftoffCompiler { ...@@ -512,45 +512,52 @@ class LiftoffCompiler {
} }
} }
void I32UnOp(bool (LiftoffAssembler::*emit_fn)(Register, Register), template <ValueType type, class EmitFn>
ExternalReference (*fallback_fn)(Isolate*)) { void EmitUnOp(EmitFn fn) {
static RegClass rc = reg_class_for(type);
LiftoffRegList pinned; LiftoffRegList pinned;
LiftoffRegister dst_reg = pinned.set(__ GetUnaryOpTargetRegister(kGpReg)); LiftoffRegister dst = pinned.set(__ GetUnaryOpTargetRegister(rc));
LiftoffRegister src_reg = pinned.set(__ PopToRegister(kGpReg, pinned)); LiftoffRegister src = __ PopToRegister(rc, pinned);
if (!emit_fn || !(asm_->*emit_fn)(dst_reg.gp(), src_reg.gp())) { fn(dst, src);
ExternalReference ext_ref = fallback_fn(asm_->isolate()); __ PushRegister(type, dst);
Register args[] = {src_reg.gp()};
GenerateCCall(dst_reg.gp(), arraysize(args), args, ext_ref);
}
__ PushRegister(kWasmI32, dst_reg);
} }
void I32Eqz() { void EmitI32UnOpWithCFallback(bool (LiftoffAssembler::*emit_fn)(Register,
LiftoffRegList pinned; Register),
LiftoffRegister dst = pinned.set(__ GetUnaryOpTargetRegister(kGpReg)); ExternalReference (*fallback_fn)(Isolate*)) {
LiftoffRegister src = pinned.set(__ PopToRegister(kGpReg, pinned)); auto emit_with_c_fallback = [=](LiftoffRegister dst, LiftoffRegister src) {
asm_->emit_i32_set_cond(kEqual, dst.gp(), src.gp()); if (emit_fn && (asm_->*emit_fn)(dst.gp(), src.gp())) return;
__ PushRegister(kWasmI32, dst); ExternalReference ext_ref = fallback_fn(asm_->isolate());
Register args[] = {src.gp()};
GenerateCCall(dst.gp(), arraysize(args), args, ext_ref);
};
EmitUnOp<kWasmI32>(emit_with_c_fallback);
} }
void UnOp(Decoder* decoder, WasmOpcode opcode, FunctionSig*, void UnOp(Decoder* decoder, WasmOpcode opcode, FunctionSig*,
const Value& value, Value* result) { const Value& value, Value* result) {
#define CASE_UNOP(opcode, type, fn, ext_ref_fn) \ #define CASE_I32_UNOP(opcode, fn) \
case WasmOpcode::kExpr##opcode: \ case WasmOpcode::kExpr##opcode: \
type##UnOp(&LiftoffAssembler::emit_##fn, ext_ref_fn); \ EmitUnOp<kWasmI32>([=](LiftoffRegister dst, LiftoffRegister src) { \
__ emit_##fn(dst.gp(), src.gp()); \
}); \
break; break;
switch (opcode) { switch (opcode) {
CASE_UNOP(I32Clz, I32, i32_clz, nullptr) CASE_I32_UNOP(I32Clz, i32_clz)
CASE_UNOP(I32Ctz, I32, i32_ctz, nullptr) CASE_I32_UNOP(I32Ctz, i32_ctz)
CASE_UNOP(I32Popcnt, I32, i32_popcnt, case kExprI32Popcnt:
&ExternalReference::wasm_word32_popcnt) EmitI32UnOpWithCFallback(&LiftoffAssembler::emit_i32_popcnt,
case WasmOpcode::kExprI32Eqz: &ExternalReference::wasm_word32_popcnt);
I32Eqz(); break;
case kExprI32Eqz:
EmitUnOp<kWasmI32>([=](LiftoffRegister dst, LiftoffRegister src) {
__ emit_i32_set_cond(kEqual, dst.gp(), src.gp());
});
break; break;
default: default:
return unsupported(decoder, WasmOpcodes::OpcodeName(opcode)); return unsupported(decoder, WasmOpcodes::OpcodeName(opcode));
} }
#undef CASE_UNOP #undef CASE_I32_UNOP
} }
template <ValueType type, typename EmitFn> template <ValueType type, typename EmitFn>
......
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