[wasm][simd] Fix SpillAdjacentFpRegisters...
...to honor the {pinned} list under all circumstances. Drive-by: DEBUG-mode helpers to print FunctionSig and LiftoffRegList objects to stdout. Fixed: chromium:1356718 Change-Id: I487db12294f687790cec1d658d7a7d754f3c2f99 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3859752 Reviewed-by: Clemens Backes <clemensb@chromium.org> Auto-Submit: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/main@{#82815}
This commit is contained in:
parent
f1e800f064
commit
8e069d6294
@ -1274,6 +1274,14 @@ void LiftoffAssembler::MoveToReturnLocations(
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
void LiftoffRegList::Print() const {
|
||||||
|
std::ostringstream os;
|
||||||
|
os << *this << "\n";
|
||||||
|
PrintF("%s", os.str().c_str());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_SLOW_DCHECKS
|
#ifdef ENABLE_SLOW_DCHECKS
|
||||||
bool LiftoffAssembler::ValidateCacheState() const {
|
bool LiftoffAssembler::ValidateCacheState() const {
|
||||||
uint32_t register_use_count[kAfterMaxLiftoffRegCode] = {0};
|
uint32_t register_use_count[kAfterMaxLiftoffRegCode] = {0};
|
||||||
@ -1337,6 +1345,10 @@ LiftoffRegister LiftoffAssembler::SpillAdjacentFpRegisters(
|
|||||||
if (last_fp.fp().code() % 2 == 0) {
|
if (last_fp.fp().code() % 2 == 0) {
|
||||||
pinned.set(last_fp);
|
pinned.set(last_fp);
|
||||||
}
|
}
|
||||||
|
// If half of an adjacent pair is pinned, consider the whole pair pinned.
|
||||||
|
// Otherwise the code below would potentially spill the pinned register
|
||||||
|
// (after first spilling the unpinned half of the pair).
|
||||||
|
pinned = pinned.SpreadSetBitsToAdjacentFpRegs();
|
||||||
|
|
||||||
// We can try to optimize the spilling here:
|
// We can try to optimize the spilling here:
|
||||||
// 1. Try to get a free fp register, either:
|
// 1. Try to get a free fp register, either:
|
||||||
|
@ -344,6 +344,8 @@ class LiftoffRegList {
|
|||||||
// Sets all even numbered fp registers.
|
// Sets all even numbered fp registers.
|
||||||
static constexpr uint64_t kEvenFpSetMask = uint64_t{0x5555555555555555}
|
static constexpr uint64_t kEvenFpSetMask = uint64_t{0x5555555555555555}
|
||||||
<< kAfterMaxLiftoffGpRegCode;
|
<< kAfterMaxLiftoffGpRegCode;
|
||||||
|
static constexpr uint64_t kOddFpSetMask = uint64_t{0xAAAAAAAAAAAAAAAA}
|
||||||
|
<< kAfterMaxLiftoffGpRegCode;
|
||||||
|
|
||||||
constexpr LiftoffRegList() = default;
|
constexpr LiftoffRegList() = default;
|
||||||
|
|
||||||
@ -426,6 +428,15 @@ class LiftoffRegList {
|
|||||||
return !GetAdjacentFpRegsSet().is_empty();
|
return !GetAdjacentFpRegsSet().is_empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a list where if any part of an adjacent pair of FP regs was set,
|
||||||
|
// both are set in the result. For example, [1, 4] is turned into [0, 1, 4, 5]
|
||||||
|
// because (0, 1) and (4, 5) are adjacent pairs.
|
||||||
|
constexpr LiftoffRegList SpreadSetBitsToAdjacentFpRegs() const {
|
||||||
|
storage_t odd_regs = regs_ & kOddFpSetMask;
|
||||||
|
storage_t even_regs = regs_ & kEvenFpSetMask;
|
||||||
|
return FromBits(regs_ | (odd_regs >> 1) | ((even_regs << 1) & kFpMask));
|
||||||
|
}
|
||||||
|
|
||||||
constexpr bool operator==(const LiftoffRegList other) const {
|
constexpr bool operator==(const LiftoffRegList other) const {
|
||||||
return regs_ == other.regs_;
|
return regs_ == other.regs_;
|
||||||
}
|
}
|
||||||
@ -461,7 +472,7 @@ class LiftoffRegList {
|
|||||||
inline Iterator begin() const;
|
inline Iterator begin() const;
|
||||||
inline Iterator end() const;
|
inline Iterator end() const;
|
||||||
|
|
||||||
static LiftoffRegList FromBits(storage_t bits) {
|
static constexpr LiftoffRegList FromBits(storage_t bits) {
|
||||||
DCHECK_EQ(bits, bits & (kGpMask | kFpMask));
|
DCHECK_EQ(bits, bits & (kGpMask | kFpMask));
|
||||||
return LiftoffRegList(bits);
|
return LiftoffRegList(bits);
|
||||||
}
|
}
|
||||||
@ -472,6 +483,10 @@ class LiftoffRegList {
|
|||||||
return LiftoffRegList{bits};
|
return LiftoffRegList{bits};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
void Print() const;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Unchecked constructor. Only use for valid bits.
|
// Unchecked constructor. Only use for valid bits.
|
||||||
explicit constexpr LiftoffRegList(storage_t bits) : regs_(bits) {}
|
explicit constexpr LiftoffRegList(storage_t bits) : regs_(bits) {}
|
||||||
|
@ -29,6 +29,21 @@ base::Optional<wasm::ValueKind> WasmReturnTypeFromSignature(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
V8_EXPORT_PRIVATE extern void PrintFunctionSig(const wasm::FunctionSig* sig) {
|
||||||
|
std::ostringstream os;
|
||||||
|
os << sig->parameter_count() << " parameters:\n";
|
||||||
|
for (size_t i = 0; i < sig->parameter_count(); i++) {
|
||||||
|
os << " " << i << ": " << sig->GetParam(i) << "\n";
|
||||||
|
}
|
||||||
|
os << sig->return_count() << " returns:\n";
|
||||||
|
for (size_t i = 0; i < sig->return_count(); i++) {
|
||||||
|
os << " " << i << ": " << sig->GetReturn() << "\n";
|
||||||
|
}
|
||||||
|
PrintF("%s", os.str().c_str());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace wasm
|
} // namespace wasm
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
14
test/mjsunit/regress/wasm/regress-crbug-1356718.js
Normal file
14
test/mjsunit/regress/wasm/regress-crbug-1356718.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2022 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");
|
||||||
|
|
||||||
|
let builder = new WasmModuleBuilder();
|
||||||
|
|
||||||
|
builder.addFunction('crash', makeSig([
|
||||||
|
kWasmF64, kWasmS128, kWasmS128, kWasmS128, kWasmS128, kWasmS128, kWasmS128,
|
||||||
|
kWasmF64, kWasmI32
|
||||||
|
], [])).addBody([kExprNop]);
|
||||||
|
|
||||||
|
builder.instantiate();
|
@ -25,7 +25,8 @@
|
|||||||
#include "src/execution/riscv/frame-constants-riscv.h"
|
#include "src/execution/riscv/frame-constants-riscv.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "src/base/macros.h"
|
#include "src/wasm/baseline/liftoff-register.h"
|
||||||
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
@ -38,6 +39,32 @@ static_assert(kLiftoffAssemblerGpCacheRegs ==
|
|||||||
|
|
||||||
static_assert(kLiftoffAssemblerFpCacheRegs ==
|
static_assert(kLiftoffAssemblerFpCacheRegs ==
|
||||||
WasmDebugBreakFrameConstants::kPushedFpRegs);
|
WasmDebugBreakFrameConstants::kPushedFpRegs);
|
||||||
|
|
||||||
|
class WasmRegisterTest : public ::testing::Test {};
|
||||||
|
|
||||||
|
TEST_F(WasmRegisterTest, SpreadSetBitsToAdjacentFpRegs) {
|
||||||
|
LiftoffRegList input(
|
||||||
|
// GP reg selection criteria: an even and an odd register belonging to
|
||||||
|
// separate adjacent pairs, and contained in kLiftoffAssemblerGpCacheRegs
|
||||||
|
// for the given platform.
|
||||||
|
#if V8_TARGET_ARCH_S390X || V8_TARGET_ARCH_PPC64
|
||||||
|
LiftoffRegister::from_code(kGpReg, 4),
|
||||||
|
LiftoffRegister::from_code(kGpReg, 7),
|
||||||
|
#else
|
||||||
|
LiftoffRegister::from_code(kGpReg, 1),
|
||||||
|
LiftoffRegister::from_code(kGpReg, 2),
|
||||||
|
#endif
|
||||||
|
LiftoffRegister::from_code(kFpReg, 1),
|
||||||
|
LiftoffRegister::from_code(kFpReg, 4));
|
||||||
|
// GP regs are left alone, FP regs are spread to adjacent pairs starting
|
||||||
|
// at an even index: 1 → (0, 1) and 4 → (4, 5).
|
||||||
|
LiftoffRegList expected =
|
||||||
|
input | LiftoffRegList(LiftoffRegister::from_code(kFpReg, 0),
|
||||||
|
LiftoffRegister::from_code(kFpReg, 5));
|
||||||
|
LiftoffRegList actual = input.SpreadSetBitsToAdjacentFpRegs();
|
||||||
|
EXPECT_EQ(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace wasm
|
} // namespace wasm
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
Loading…
Reference in New Issue
Block a user