[Liftoff] Add i32.eq and i32.ne

Also refactor the implementation of i32.eqz such that the same
platform-specific code can be reused.
As a next step, it should be straight-forward to add other i32
comparison operations.

R=titzer@chromium.org

Bug: v8:6600
Change-Id: I4e8768d4ceb7294ba35777b7777ddd69d1a58cf1
Reviewed-on: https://chromium-review.googlesource.com/877889
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Ben Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50868}
This commit is contained in:
Clemens Hammacher 2018-01-22 12:37:05 +01:00 committed by Commit Bot
parent 55efb6cc5d
commit 664dc868b9
10 changed files with 73 additions and 29 deletions

View File

@ -104,7 +104,6 @@ UNIMPLEMENTED_GP_BINOP(i32_xor)
UNIMPLEMENTED_SHIFTOP(i32_shl)
UNIMPLEMENTED_SHIFTOP(i32_sar)
UNIMPLEMENTED_SHIFTOP(i32_shr)
UNIMPLEMENTED_GP_UNOP(i32_eqz)
UNIMPLEMENTED_GP_UNOP(i32_clz)
UNIMPLEMENTED_GP_UNOP(i32_ctz)
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
@ -134,6 +133,10 @@ void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_set_cond(Condition cond, Register dst) {
UNIMPLEMENTED();
}
void LiftoffAssembler::StackCheck(Label* ool_code) { UNIMPLEMENTED(); }
void LiftoffAssembler::CallTrapCallbackForTesting() { UNIMPLEMENTED(); }

View File

@ -104,7 +104,6 @@ UNIMPLEMENTED_GP_BINOP(i32_xor)
UNIMPLEMENTED_SHIFTOP(i32_shl)
UNIMPLEMENTED_SHIFTOP(i32_sar)
UNIMPLEMENTED_SHIFTOP(i32_shr)
UNIMPLEMENTED_GP_UNOP(i32_eqz)
UNIMPLEMENTED_GP_UNOP(i32_clz)
UNIMPLEMENTED_GP_UNOP(i32_ctz)
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
@ -134,6 +133,10 @@ void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_set_cond(Condition cond, Register dst) {
UNIMPLEMENTED();
}
void LiftoffAssembler::StackCheck(Label* ool_code) { UNIMPLEMENTED(); }
void LiftoffAssembler::CallTrapCallbackForTesting() { UNIMPLEMENTED(); }

View File

@ -358,20 +358,6 @@ void LiftoffAssembler::emit_i32_shr(Register dst, Register lhs, Register rhs,
liftoff::EmitShiftOperation(this, dst, lhs, rhs, &Assembler::shr_cl, pinned);
}
bool LiftoffAssembler::emit_i32_eqz(Register dst, Register src) {
Register tmp_byte_reg = dst;
// Only the lower 4 registers can be addressed as 8-bit registers.
if (!dst.is_byte_register()) {
LiftoffRegList pinned = LiftoffRegList::ForRegs(src);
tmp_byte_reg = GetUnusedRegister(liftoff::kByteRegs, pinned).gp();
}
test(src, src);
setcc(zero, tmp_byte_reg);
movzx_b(dst, tmp_byte_reg);
return true;
}
bool LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
Label nonzero_input;
Label continuation;
@ -475,6 +461,20 @@ void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label) {
j(cond, label);
}
void LiftoffAssembler::emit_i32_set_cond(Condition cond, Register dst) {
Register tmp_byte_reg = dst;
// Only the lower 4 registers can be addressed as 8-bit registers.
if (!dst.is_byte_register()) {
LiftoffRegList pinned = LiftoffRegList::ForRegs(dst);
// {mov} does not change the status flags, so calling {GetUnusedRegister}
// should be fine here.
tmp_byte_reg = GetUnusedRegister(liftoff::kByteRegs, pinned).gp();
}
setcc(cond, tmp_byte_reg);
movzx_b(dst, tmp_byte_reg);
}
void LiftoffAssembler::StackCheck(Label* ool_code) {
Register limit = GetUnusedRegister(kGpReg).gp();
mov(limit, Immediate(ExternalReference::address_of_stack_limit(isolate())));

View File

@ -321,7 +321,6 @@ class LiftoffAssembler : public TurboAssembler {
LiftoffRegList pinned = {});
// i32 unops.
inline bool emit_i32_eqz(Register dst, Register src);
inline bool emit_i32_clz(Register dst, Register src);
inline bool emit_i32_ctz(Register dst, Register src);
inline bool emit_i32_popcnt(Register dst, Register src);
@ -340,6 +339,8 @@ class LiftoffAssembler : public TurboAssembler {
inline void emit_ptrsize_compare(Register, Register);
inline void emit_jump(Label*);
inline void emit_cond_jump(Condition, Label*);
// Set {dst} to 1 if condition holds, 0 otherwise.
inline void emit_i32_set_cond(Condition, Register dst);
inline void StackCheck(Label* ool_code);

View File

@ -481,6 +481,15 @@ class LiftoffCompiler {
__ PushRegister(kWasmI32, dst_reg);
}
void I32Eqz() {
LiftoffRegList pinned;
LiftoffRegister dst = pinned.set(__ GetUnaryOpTargetRegister(kGpReg));
LiftoffRegister src = pinned.set(__ PopToRegister(kGpReg, pinned));
asm_->emit_i32_test(src.gp());
asm_->emit_i32_set_cond(kEqual, dst.gp());
__ PushRegister(kWasmI32, dst);
}
void UnOp(Decoder* decoder, WasmOpcode opcode, FunctionSig*,
const Value& value, Value* result) {
#define CASE_UNOP(opcode, type, fn, ext_ref_fn) \
@ -488,11 +497,13 @@ class LiftoffCompiler {
type##UnOp(&LiftoffAssembler::emit_##fn, ext_ref_fn); \
break;
switch (opcode) {
CASE_UNOP(I32Eqz, I32, i32_eqz, nullptr)
CASE_UNOP(I32Clz, I32, i32_clz, nullptr)
CASE_UNOP(I32Ctz, I32, i32_ctz, nullptr)
CASE_UNOP(I32Popcnt, I32, i32_popcnt,
&ExternalReference::wasm_word32_popcnt)
case WasmOpcode::kExprI32Eqz:
I32Eqz();
break;
default:
return unsupported(decoder, WasmOpcodes::OpcodeName(opcode));
}
@ -509,6 +520,16 @@ class LiftoffCompiler {
__ PushRegister(kWasmI32, dst_reg);
}
void I32CmpOp(Condition cond) {
LiftoffRegList pinned;
LiftoffRegister dst = pinned.set(__ GetBinaryOpTargetRegister(kGpReg));
LiftoffRegister rhs = pinned.set(__ PopToRegister(kGpReg, pinned));
LiftoffRegister lhs = __ PopToRegister(kGpReg, pinned);
__ emit_i32_compare(lhs.gp(), rhs.gp());
__ emit_i32_set_cond(cond, dst.gp());
__ PushRegister(kWasmI32, dst);
}
void I32ShiftOp(void (LiftoffAssembler::*emit_fn)(Register, Register,
Register, LiftoffRegList)) {
LiftoffRegList pinned;
@ -546,6 +567,9 @@ class LiftoffCompiler {
#define CASE_BINOP(opcode, type, fn) \
case WasmOpcode::kExpr##opcode: \
return type##BinOp(&LiftoffAssembler::emit_##fn);
#define CASE_CMPOP(opcode, cond) \
case WasmOpcode::kExpr##opcode: \
return I32CmpOp(cond);
#define CASE_SHIFTOP(opcode, fn) \
case WasmOpcode::kExpr##opcode: \
return I32ShiftOp(&LiftoffAssembler::emit_##fn);
@ -560,6 +584,8 @@ class LiftoffCompiler {
CASE_BINOP(I32And, I32, i32_and)
CASE_BINOP(I32Ior, I32, i32_or)
CASE_BINOP(I32Xor, I32, i32_xor)
CASE_CMPOP(I32Eq, kEqual)
CASE_CMPOP(I32Ne, kUnequal)
CASE_SHIFTOP(I32Shl, i32_shl)
CASE_SHIFTOP(I32ShrS, i32_sar)
CASE_SHIFTOP(I32ShrU, i32_shr)
@ -573,6 +599,7 @@ class LiftoffCompiler {
}
#undef CASE_BINOP
#undef CASE_SHIFTOP
#undef CASE_CMPOP
#undef CASE_CCALL_BINOP
}

View File

@ -104,7 +104,6 @@ UNIMPLEMENTED_GP_BINOP(i32_xor)
UNIMPLEMENTED_SHIFTOP(i32_shl)
UNIMPLEMENTED_SHIFTOP(i32_sar)
UNIMPLEMENTED_SHIFTOP(i32_shr)
UNIMPLEMENTED_GP_UNOP(i32_eqz)
UNIMPLEMENTED_GP_UNOP(i32_clz)
UNIMPLEMENTED_GP_UNOP(i32_ctz)
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
@ -134,6 +133,10 @@ void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_set_cond(Condition cond, Register dst) {
UNIMPLEMENTED();
}
void LiftoffAssembler::StackCheck(Label* ool_code) { UNIMPLEMENTED(); }
void LiftoffAssembler::CallTrapCallbackForTesting() { UNIMPLEMENTED(); }

View File

@ -104,7 +104,6 @@ UNIMPLEMENTED_GP_BINOP(i32_xor)
UNIMPLEMENTED_SHIFTOP(i32_shl)
UNIMPLEMENTED_SHIFTOP(i32_sar)
UNIMPLEMENTED_SHIFTOP(i32_shr)
UNIMPLEMENTED_GP_UNOP(i32_eqz)
UNIMPLEMENTED_GP_UNOP(i32_clz)
UNIMPLEMENTED_GP_UNOP(i32_ctz)
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
@ -134,6 +133,10 @@ void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_set_cond(Condition cond, Register dst) {
UNIMPLEMENTED();
}
void LiftoffAssembler::StackCheck(Label* ool_code) { UNIMPLEMENTED(); }
void LiftoffAssembler::CallTrapCallbackForTesting() { UNIMPLEMENTED(); }

View File

@ -104,7 +104,6 @@ UNIMPLEMENTED_GP_BINOP(i32_xor)
UNIMPLEMENTED_SHIFTOP(i32_shl)
UNIMPLEMENTED_SHIFTOP(i32_sar)
UNIMPLEMENTED_SHIFTOP(i32_shr)
UNIMPLEMENTED_GP_UNOP(i32_eqz)
UNIMPLEMENTED_GP_UNOP(i32_clz)
UNIMPLEMENTED_GP_UNOP(i32_ctz)
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
@ -134,6 +133,10 @@ void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_set_cond(Condition cond, Register dst) {
UNIMPLEMENTED();
}
void LiftoffAssembler::StackCheck(Label* ool_code) { UNIMPLEMENTED(); }
void LiftoffAssembler::CallTrapCallbackForTesting() { UNIMPLEMENTED(); }

View File

@ -104,7 +104,6 @@ UNIMPLEMENTED_GP_BINOP(i32_xor)
UNIMPLEMENTED_SHIFTOP(i32_shl)
UNIMPLEMENTED_SHIFTOP(i32_sar)
UNIMPLEMENTED_SHIFTOP(i32_shr)
UNIMPLEMENTED_GP_UNOP(i32_eqz)
UNIMPLEMENTED_GP_UNOP(i32_clz)
UNIMPLEMENTED_GP_UNOP(i32_ctz)
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
@ -134,6 +133,10 @@ void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_set_cond(Condition cond, Register dst) {
UNIMPLEMENTED();
}
void LiftoffAssembler::StackCheck(Label* ool_code) { UNIMPLEMENTED(); }
void LiftoffAssembler::CallTrapCallbackForTesting() { UNIMPLEMENTED(); }

View File

@ -361,13 +361,6 @@ void LiftoffAssembler::emit_i32_shr(Register dst, Register lhs, Register rhs,
liftoff::EmitShiftOperation(this, dst, lhs, rhs, &Assembler::shrl_cl, pinned);
}
bool LiftoffAssembler::emit_i32_eqz(Register dst, Register src) {
testl(src, src);
setcc(zero, dst);
movzxbl(dst, dst);
return true;
}
bool LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
Label nonzero_input;
Label continuation;
@ -475,6 +468,11 @@ void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label) {
j(cond, label);
}
void LiftoffAssembler::emit_i32_set_cond(Condition cond, Register dst) {
setcc(cond, dst);
movzxbl(dst, dst);
}
void LiftoffAssembler::StackCheck(Label* ool_code) {
Register limit = GetUnusedRegister(kGpReg).gp();
LoadAddress(limit, ExternalReference::address_of_stack_limit(isolate()));