Commit 24cfb075 authored by Clemens Backes's avatar Clemens Backes Committed by Commit Bot

[Liftoff] Implement i64_rol and i64_ror

For now, both are implemented via a C call, just like i32_rol and
i32_ror. If they turn out to be critical for performance, we can still
implement them via hardware instructions on selected platforms.

R=jkummerow@chromium.org

Bug: v8:9919
Change-Id: I16affdfe397a08ef6a51d310f018b3a099e80e44
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1900454
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64816}
parent bcd55e15
...@@ -287,6 +287,8 @@ FUNCTION_REFERENCE(wasm_word32_popcnt, wasm::word32_popcnt_wrapper) ...@@ -287,6 +287,8 @@ FUNCTION_REFERENCE(wasm_word32_popcnt, wasm::word32_popcnt_wrapper)
FUNCTION_REFERENCE(wasm_word64_popcnt, wasm::word64_popcnt_wrapper) FUNCTION_REFERENCE(wasm_word64_popcnt, wasm::word64_popcnt_wrapper)
FUNCTION_REFERENCE(wasm_word32_rol, wasm::word32_rol_wrapper) FUNCTION_REFERENCE(wasm_word32_rol, wasm::word32_rol_wrapper)
FUNCTION_REFERENCE(wasm_word32_ror, wasm::word32_ror_wrapper) FUNCTION_REFERENCE(wasm_word32_ror, wasm::word32_ror_wrapper)
FUNCTION_REFERENCE(wasm_word64_rol, wasm::word64_rol_wrapper)
FUNCTION_REFERENCE(wasm_word64_ror, wasm::word64_ror_wrapper)
FUNCTION_REFERENCE(wasm_memory_copy, wasm::memory_copy_wrapper) FUNCTION_REFERENCE(wasm_memory_copy, wasm::memory_copy_wrapper)
FUNCTION_REFERENCE(wasm_memory_fill, wasm::memory_fill_wrapper) FUNCTION_REFERENCE(wasm_memory_fill, wasm::memory_fill_wrapper)
......
...@@ -196,6 +196,8 @@ class StatsCounter; ...@@ -196,6 +196,8 @@ class StatsCounter;
V(wasm_word32_popcnt, "wasm::word32_popcnt") \ V(wasm_word32_popcnt, "wasm::word32_popcnt") \
V(wasm_word32_rol, "wasm::word32_rol") \ V(wasm_word32_rol, "wasm::word32_rol") \
V(wasm_word32_ror, "wasm::word32_ror") \ V(wasm_word32_ror, "wasm::word32_ror") \
V(wasm_word64_rol, "wasm::word64_rol") \
V(wasm_word64_ror, "wasm::word64_ror") \
V(wasm_word64_ctz, "wasm::word64_ctz") \ V(wasm_word64_ctz, "wasm::word64_ctz") \
V(wasm_word64_popcnt, "wasm::word64_popcnt") \ V(wasm_word64_popcnt, "wasm::word64_popcnt") \
V(wasm_memory_copy, "wasm::memory_copy") \ V(wasm_memory_copy, "wasm::memory_copy") \
......
...@@ -3001,13 +3001,11 @@ Node* WasmGraphBuilder::BuildI64Rol(Node* left, Node* right) { ...@@ -3001,13 +3001,11 @@ Node* WasmGraphBuilder::BuildI64Rol(Node* left, Node* right) {
// Implement Rol by Ror since TurboFan does not have Rol opcode. // Implement Rol by Ror since TurboFan does not have Rol opcode.
// TODO(weiliang): support Word64Rol opcode in TurboFan. // TODO(weiliang): support Word64Rol opcode in TurboFan.
Int64Matcher m(right); Int64Matcher m(right);
if (m.HasValue()) { Node* inv_right =
return Binop(wasm::kExprI64Ror, left, m.HasValue()
mcgraph()->Int64Constant(64 - (m.Value() & 0x3F))); ? mcgraph()->Int64Constant(64 - (m.Value() & 0x3F))
} else { : Binop(wasm::kExprI64Sub, mcgraph()->Int64Constant(64), right);
return Binop(wasm::kExprI64Ror, left, return Binop(wasm::kExprI64Ror, left, inv_right);
Binop(wasm::kExprI64Sub, mcgraph()->Int64Constant(64), right));
}
} }
Node* WasmGraphBuilder::Invert(Node* node) { Node* WasmGraphBuilder::Invert(Node* node) {
......
...@@ -1023,13 +1023,15 @@ class LiftoffCompiler { ...@@ -1023,13 +1023,15 @@ class LiftoffCompiler {
}); });
#define CASE_CCALL_BINOP(opcode, type, ext_ref_fn) \ #define CASE_CCALL_BINOP(opcode, type, ext_ref_fn) \
case kExpr##opcode: \ case kExpr##opcode: \
return EmitBinOp<kWasmI32, kWasmI32>( \ return EmitBinOp<kWasm##type, kWasm##type>( \
[=](LiftoffRegister dst, LiftoffRegister lhs, LiftoffRegister rhs) { \ [=](LiftoffRegister dst, LiftoffRegister lhs, LiftoffRegister rhs) { \
LiftoffRegister args[] = {lhs, rhs}; \ LiftoffRegister args[] = {lhs, rhs}; \
auto ext_ref = ExternalReference::ext_ref_fn(); \ auto ext_ref = ExternalReference::ext_ref_fn(); \
ValueType sig_i_ii_reps[] = {kWasmI32, kWasmI32, kWasmI32}; \ ValueType sig_reps[] = {kWasm##type, kWasm##type, kWasm##type}; \
FunctionSig sig_i_ii(1, 2, sig_i_ii_reps); \ const bool out_via_stack = kWasm##type == kWasmI64; \
GenerateCCall(&dst, &sig_i_ii, kWasmStmt, args, ext_ref); \ FunctionSig sig(out_via_stack ? 0 : 1, 2, sig_reps); \
ValueType out_arg_type = out_via_stack ? kWasmI64 : kWasmStmt; \
GenerateCCall(&dst, &sig, out_arg_type, args, ext_ref); \
}); });
switch (opcode) { switch (opcode) {
CASE_I32_BINOPI(I32Add, i32_add) CASE_I32_BINOPI(I32Add, i32_add)
...@@ -1079,11 +1081,13 @@ class LiftoffCompiler { ...@@ -1079,11 +1081,13 @@ class LiftoffCompiler {
CASE_I32_BINOPI(I32Shl, i32_shl) CASE_I32_BINOPI(I32Shl, i32_shl)
CASE_I32_BINOPI(I32ShrS, i32_sar) CASE_I32_BINOPI(I32ShrS, i32_sar)
CASE_I32_BINOPI(I32ShrU, i32_shr) CASE_I32_BINOPI(I32ShrU, i32_shr)
CASE_CCALL_BINOP(I32Rol, I32, wasm_word32_rol)
CASE_CCALL_BINOP(I32Ror, I32, wasm_word32_ror)
CASE_I64_SHIFTOP(I64Shl, i64_shl) CASE_I64_SHIFTOP(I64Shl, i64_shl)
CASE_I64_SHIFTOP(I64ShrS, i64_sar) CASE_I64_SHIFTOP(I64ShrS, i64_sar)
CASE_I64_SHIFTOP(I64ShrU, i64_shr) CASE_I64_SHIFTOP(I64ShrU, i64_shr)
CASE_CCALL_BINOP(I32Rol, I32, wasm_word32_rol) CASE_CCALL_BINOP(I64Rol, I64, wasm_word64_rol)
CASE_CCALL_BINOP(I32Ror, I32, wasm_word32_ror) CASE_CCALL_BINOP(I64Ror, I64, wasm_word64_ror)
CASE_FLOAT_BINOP(F32Add, F32, f32_add) CASE_FLOAT_BINOP(F32Add, F32, f32_add)
CASE_FLOAT_BINOP(F32Sub, F32, f32_sub) CASE_FLOAT_BINOP(F32Sub, F32, f32_sub)
CASE_FLOAT_BINOP(F32Mul, F32, f32_mul) CASE_FLOAT_BINOP(F32Mul, F32, f32_mul)
...@@ -1197,10 +1201,6 @@ class LiftoffCompiler { ...@@ -1197,10 +1201,6 @@ class LiftoffCompiler {
} }
}); });
break; break;
case kExprI64Rol:
case kExprI64Ror:
return unsupported(decoder, kComplexOperation,
WasmOpcodes::OpcodeName(opcode));
default: default:
UNREACHABLE(); UNREACHABLE();
} }
......
...@@ -303,6 +303,20 @@ uint32_t word32_ror_wrapper(Address data) { ...@@ -303,6 +303,20 @@ uint32_t word32_ror_wrapper(Address data) {
return (input >> shift) | (input << ((32 - shift) & 31)); return (input >> shift) | (input << ((32 - shift) & 31));
} }
void word64_rol_wrapper(Address data) {
uint64_t input = ReadUnalignedValue<uint64_t>(data);
uint64_t shift = ReadUnalignedValue<uint64_t>(data + sizeof(input)) & 63;
uint64_t result = (input << shift) | (input >> ((64 - shift) & 63));
WriteUnalignedValue<uint64_t>(data, result);
}
void word64_ror_wrapper(Address data) {
uint64_t input = ReadUnalignedValue<uint64_t>(data);
uint64_t shift = ReadUnalignedValue<uint64_t>(data + sizeof(input)) & 63;
uint64_t result = (input >> shift) | (input << ((64 - shift) & 63));
WriteUnalignedValue<uint64_t>(data, result);
}
void float64_pow_wrapper(Address data) { void float64_pow_wrapper(Address data) {
double x = ReadUnalignedValue<double>(data); double x = ReadUnalignedValue<double>(data);
double y = ReadUnalignedValue<double>(data + sizeof(x)); double y = ReadUnalignedValue<double>(data + sizeof(x));
......
...@@ -65,6 +65,10 @@ V8_EXPORT_PRIVATE uint32_t word32_rol_wrapper(Address data); ...@@ -65,6 +65,10 @@ V8_EXPORT_PRIVATE uint32_t word32_rol_wrapper(Address data);
V8_EXPORT_PRIVATE uint32_t word32_ror_wrapper(Address data); V8_EXPORT_PRIVATE uint32_t word32_ror_wrapper(Address data);
V8_EXPORT_PRIVATE void word64_rol_wrapper(Address data);
V8_EXPORT_PRIVATE void word64_ror_wrapper(Address data);
V8_EXPORT_PRIVATE void float64_pow_wrapper(Address data); V8_EXPORT_PRIVATE void float64_pow_wrapper(Address data);
void memory_copy_wrapper(Address dst, Address src, uint32_t size); void memory_copy_wrapper(Address dst, Address src, uint32_t size);
......
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