[liftoff] Fix i64.sub special case

In the case that {dst}, {lhs} and {rhs} all point to the same register,
we would emit wrong code (negating the register and adding it to
itself). This CL fixes this by checking if {lhs == rhs}, and just
clearing the {dst} register in that case.

R=thibaudm@chromium.org

Bug: chromium:1247659
Change-Id: I7913617850adb34a5ad812369f16a7422358454d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3151955
Reviewed-by: Thibaud Michaud <thibaudm@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#76765}
This commit is contained in:
Clemens Backes 2021-09-09 16:43:32 +02:00 committed by V8 LUCI CQ
parent 5b01050e9a
commit f235120c5e
2 changed files with 90 additions and 1 deletions

View File

@ -1317,7 +1317,9 @@ void LiftoffAssembler::emit_i64_addi(LiftoffRegister dst, LiftoffRegister lhs,
void LiftoffAssembler::emit_i64_sub(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs) {
if (dst.gp() == rhs.gp()) {
if (lhs.gp() == rhs.gp()) {
xorq(dst.gp(), dst.gp());
} else if (dst.gp() == rhs.gp()) {
negq(dst.gp());
addq(dst.gp(), lhs.gp());
} else {

View File

@ -0,0 +1,87 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
builder.addMemory(16, 17);
builder.addGlobal(kWasmI32, 1, WasmInitExpr.I32Const(10));
// Generate function 1 (out of 3).
builder.addFunction('load', kSig_i_v)
.addBody([
kExprI32Const, 0, // i32.const
kExprI32LoadMem8U, 0, 5, // i32.load8_u
])
.exportFunc();
// Generate function 2 (out of 3).
builder.addFunction(undefined, makeSig([kWasmI64, kWasmI32], []))
.addLocals(kWasmI64, 3)
.addLocals(kWasmI32, 5)
.addBody([
// locals: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]; stack: []
kExprGlobalGet, 0, // global.get
// locals: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]; stack: [10]
kExprLocalSet, 5, // local.set
// locals: [1, 0, 0, 0, 0, 10, 0, 0, 0, 0]; stack: []
kExprI32Const, 0, // i32.const
// locals: [1, 0, 0, 0, 0, 10, 0, 0, 0, 0]; stack: [0]
kExprI32Eqz, // i32.eqz
// locals: [1, 0, 0, 0, 0, 10, 0, 0, 0, 0]; stack: [1]
kExprLocalSet, 6, // local.set
// locals: [1, 0, 0, 0, 0, 10, 1, 0, 0, 0]; stack: []
kExprGlobalGet, 0, // global.get
// locals: [1, 0, 0, 0, 0, 10, 1, 0, 0, 0]; stack: [10]
kExprLocalSet, 7, // local.set
// locals: [1, 0, 0, 0, 0, 10, 1, 10, 0, 0]; stack: []
kExprI32Const, 0, // i32.const
// locals: [1, 0, 0, 0, 0, 10, 1, 10, 0, 0]; stack: [0]
kExprI32Const, 1, // i32.const
// locals: [1, 0, 0, 0, 0, 10, 1, 10, 0, 0]; stack: [0, 1]
kExprI32Sub, // i32.sub
// locals: [1, 0, 0, 0, 0, 10, 1, 10, 0, 0]; stack: [-1]
kExprLocalSet, 8, // local.set
// locals: [1, 0, 0, 0, 0, 10, 1, 10, -1, 0]; stack: []
kExprI32Const, 1, // i32.const
// locals: [1, 0, 0, 0, 0, 10, 1, 10, -1, 0]; stack: [1]
kExprI32Const, 15, // i32.const
// locals: [1, 0, 0, 0, 0, 10, 1, 10, -1, 0]; stack: [1, 15]
kExprI32And, // i32.and
// locals: [1, 0, 0, 0, 0, 10, 1, 10, -1, 0]; stack: [1]
kExprLocalSet, 9, // local.set
// locals: [1, 0, 0, 0, 0, 10, 1, 10, -1, 1]; stack: []
kExprLocalGet, 0, // local.get
// locals: [1, 0, 0, 0, 0, 10, 1, 10, -1, 1]; stack: [1]
kExprLocalSet, 2, // local.set
// locals: [1, 0, 1, 0, 0, 10, 1, 10, -1, 1]; stack: []
kExprLocalGet, 0, // local.get
// locals: [1, 0, 1, 0, 0, 10, 1, 10, -1, 1]; stack: [1]
kExprLocalSet, 3, // local.set
// locals: [1, 0, 1, 1, 0, 10, 1, 10, -1, 1]; stack: []
kExprLocalGet, 2, // local.get
// locals: [1, 0, 1, 1, 0, 10, 1, 10, -1, 1]; stack: [1]
kExprLocalGet, 3, // local.get
// locals: [1, 0, 1, 1, 0, 10, 1, 10, -1, 1]; stack: [1, 1]
kExprI64Sub, // i64.sub
// locals: [1, 0, 1, 1, 0, 10, 1, 10, -1, 1]; stack: [0]
kExprLocalSet, 4, // local.set
// locals: [1, 0, 1, 1, 0, 10, 1, 10, -1, 1]; stack: []
kExprI32Const, 1, // i32.const
// locals: [1, 0, 1, 1, 0, 10, 1, 10, -1, 1]; stack: [1]
kExprLocalGet, 4, // local.get
// locals: [1, 0, 1, 1, 0, 10, 1, 10, -1, 1]; stack: [1, 0]
kExprI64StoreMem16, 1, 0x03, // i64.store16
]);
// Generate function 3 (out of 3).
builder.addFunction('invoker', kSig_v_v)
.addBody([
...wasmI64Const(1), // i64.const
...wasmI32Const(0), // i32.const
kExprCallFunction, 1, // call function #1
])
.exportFunc();
const instance = builder.instantiate();
var exports = instance.exports;
exports.invoker();
assertEquals(0, exports.load());