Skip to content

Commit b429b8f

Browse files
backesCommit Bot
authored andcommitted
[liftoff] Handle unordered register pairs
For 64-bit binary operations, Liftoff on arm made the assumption that register pairs are always ordered, i.e. the register code for the low word is lower than the register code for the high word. Ensuring this was only implemented in {GetUnusedRegister} in https://crrev.com/c/2168875. Other cases were missing though, e.g. return values, but also different places were we construct register pairs internally. Thus, this CL removes this constraint again and instead handles unordered register pairs in 64-bit binary operations on arm. [email protected] Bug: chromium:1101304 Change-Id: I4cd9fb1577f82ab06d34c9dde6533cf04a2cade7 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2287870 Reviewed-by: Thibaud Michaud <[email protected]> Commit-Queue: Clemens Backes <[email protected]> Cr-Commit-Position: refs/heads/master@{#68752}
1 parent d6a14ab commit b429b8f

3 files changed

Lines changed: 37 additions & 12 deletions

File tree

src/wasm/baseline/arm/liftoff-assembler-arm.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,16 @@ template <void (Assembler::*op)(Register, Register, Register, SBit, Condition),
120120
SBit, Condition)>
121121
inline void I64Binop(LiftoffAssembler* assm, LiftoffRegister dst,
122122
LiftoffRegister lhs, LiftoffRegister rhs) {
123-
DCHECK_NE(dst.low_gp(), lhs.high_gp());
124-
DCHECK_NE(dst.low_gp(), rhs.high_gp());
125-
(assm->*op)(dst.low_gp(), lhs.low_gp(), rhs.low_gp(), SetCC, al);
123+
Register dst_low = dst.low_gp();
124+
if (dst_low == lhs.high_gp() || dst_low == rhs.high_gp()) {
125+
dst_low = assm->GetUnusedRegister(
126+
kGpReg, LiftoffRegList::ForRegs(lhs, rhs, dst.high_gp()))
127+
.gp();
128+
}
129+
(assm->*op)(dst_low, lhs.low_gp(), rhs.low_gp(), SetCC, al);
126130
(assm->*op_with_carry)(dst.high_gp(), lhs.high_gp(), Operand(rhs.high_gp()),
127131
LeaveCC, al);
132+
if (dst_low != dst.low_gp()) assm->mov(dst.low_gp(), dst_low);
128133
}
129134

130135
template <void (Assembler::*op)(Register, Register, const Operand&, SBit,

src/wasm/baseline/liftoff-assembler.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -371,15 +371,6 @@ class LiftoffAssembler : public TurboAssembler {
371371
LiftoffRegList candidates = kGpCacheRegList;
372372
Register low = pinned.set(GetUnusedRegister(candidates, pinned)).gp();
373373
Register high = GetUnusedRegister(candidates, pinned).gp();
374-
if (low.code() > high.code()) {
375-
// Establish the invariant that the register of the low word always has
376-
// a lower code than the register of the high word. This guarantees that
377-
// if a register pair of an input is reused for the result, the low
378-
// word and high word registers are not swapped, i.e. the low word
379-
// register of the result is not the high word register of the input,
380-
// and vice versa.
381-
std::swap(low, high);
382-
}
383374
return LiftoffRegister::ForPair(low, high);
384375
} else if (kNeedS128RegPair && rc == kFpRegPair) {
385376
// kFpRegPair specific logic here because we need adjacent registers, not
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2020 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
load('test/mjsunit/wasm/wasm-module-builder.js');
6+
7+
const builder = new WasmModuleBuilder();
8+
builder.addType(makeSig(
9+
[kWasmI64, kWasmI32, kWasmF64, kWasmI64, kWasmI64, kWasmI32, kWasmI64],
10+
[]));
11+
builder.addFunction(undefined, 0 /* sig */).addBody([
12+
kExprI32Const, 0, // i32.const
13+
kExprIf, kWasmStmt, // if @3
14+
kExprI32Const, 1, // i32.const
15+
kExprIf, kWasmStmt, // if @7
16+
kExprNop, // nop
17+
kExprElse, // else @10
18+
kExprUnreachable, // unreachable
19+
kExprEnd, // end @12
20+
kExprLocalGet, 0x06, // local.get
21+
kExprLocalSet, 0x00, // local.set
22+
kExprLocalGet, 0x03, // local.get
23+
kExprLocalGet, 0x00, // local.get
24+
kExprI64Sub, // i64.sub
25+
kExprDrop, // drop
26+
kExprUnreachable, // unreachable
27+
kExprEnd // end @24
28+
]);
29+
builder.toModule();

0 commit comments

Comments
 (0)