[regalloc] Fix S128 slot interference check

When checking for operand interference, if both operands are slots and
one of them is 128 bit wide, check that the slot ranges don't intersect.

R=nicohartmann@chromium.org

Bug: chromium:1248817
Change-Id: Ib18b6e596dbb23427508b7cc07947a0ab4665e85
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3162141
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/main@{#76904}
This commit is contained in:
Thibaud Michaud 2021-09-16 11:37:06 +02:00 committed by V8 LUCI CQ
parent 8e3d7e82c4
commit 82cc2677ac
2 changed files with 42 additions and 12 deletions

View File

@ -7,7 +7,9 @@
#include <cstddef>
#include <iomanip>
#include "src/codegen/aligned-slot-allocator.h"
#include "src/codegen/interface-descriptors.h"
#include "src/codegen/machine-type.h"
#include "src/codegen/register-configuration.h"
#include "src/codegen/source-position.h"
#include "src/compiler/common-operator.h"
@ -77,10 +79,15 @@ FlagsCondition CommuteFlagsCondition(FlagsCondition condition) {
}
bool InstructionOperand::InterferesWith(const InstructionOperand& other) const {
if (kSimpleFPAliasing || !this->IsFPLocationOperand() ||
!other.IsFPLocationOperand())
const bool kComplexFPAliasing = !kSimpleFPAliasing &&
this->IsFPLocationOperand() &&
other.IsFPLocationOperand();
const bool kComplexS128SlotAliasing =
(this->IsSimd128StackSlot() && other.IsAnyStackSlot()) ||
(other.IsSimd128StackSlot() && this->IsAnyStackSlot());
if (!kComplexFPAliasing && !kComplexS128SlotAliasing) {
return EqualsCanonicalized(other);
// Aliasing is complex and both operands are fp locations.
}
const LocationOperand& loc = *LocationOperand::cast(this);
const LocationOperand& other_loc = LocationOperand::cast(other);
LocationOperand::LocationKind kind = loc.location_kind();
@ -88,22 +95,29 @@ bool InstructionOperand::InterferesWith(const InstructionOperand& other) const {
if (kind != other_kind) return false;
MachineRepresentation rep = loc.representation();
MachineRepresentation other_rep = other_loc.representation();
if (rep == other_rep) return EqualsCanonicalized(other);
if (kind == LocationOperand::REGISTER) {
// FP register-register interference.
return GetRegConfig()->AreAliases(rep, loc.register_code(), other_rep,
other_loc.register_code());
if (kComplexFPAliasing && !kComplexS128SlotAliasing) {
if (rep == other_rep) return EqualsCanonicalized(other);
if (kind == LocationOperand::REGISTER) {
// FP register-register interference.
return GetRegConfig()->AreAliases(rep, loc.register_code(), other_rep,
other_loc.register_code());
}
}
// FP slot-slot interference. Slots of different FP reps can alias because
// the gap resolver may break a move into 2 or 4 equivalent smaller moves.
// Complex multi-slot operand interference:
// - slots of different FP reps can alias because the gap resolver may break a
// move into 2 or 4 equivalent smaller moves,
// - stack layout can be rearranged for tail calls
DCHECK_EQ(LocationOperand::STACK_SLOT, kind);
int index_hi = loc.index();
int index_lo =
index_hi - (1 << ElementSizeLog2Of(rep)) / kSystemPointerSize + 1;
index_hi -
AlignedSlotAllocator::NumSlotsForWidth(ElementSizeInBytes(rep)) + 1;
int other_index_hi = other_loc.index();
int other_index_lo =
other_index_hi -
(1 << ElementSizeLog2Of(other_rep)) / kSystemPointerSize + 1;
AlignedSlotAllocator::NumSlotsForWidth(ElementSizeInBytes(other_rep)) + 1;
return other_index_hi >= index_lo && index_hi >= other_index_lo;
}

View File

@ -61,6 +61,22 @@ TEST_F(InstructionTest, OperandInterference) {
}
}
// 128 bit slots can interfere with other slots at a different index.
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 128 / kBitsPerByte / kSystemPointerSize; ++j) {
EXPECT_TRUE(Interfere(LocationOperand::STACK_SLOT,
MachineRepresentation::kSimd128, i, kWord, i - j));
EXPECT_TRUE(Interfere(LocationOperand::STACK_SLOT,
MachineRepresentation::kSimd128, i, kFloat, i - j));
EXPECT_TRUE(Interfere(LocationOperand::STACK_SLOT,
MachineRepresentation::kSimd128, i, kDouble,
i - j));
EXPECT_TRUE(Interfere(LocationOperand::STACK_SLOT,
MachineRepresentation::kSimd128, i,
MachineRepresentation::kSimd128, i - j));
}
}
// All FP registers interfere with themselves.
for (int i = 0; i < RegisterConfiguration::kMaxFPRegisters; ++i) {
EXPECT_TRUE(Interfere(LocationOperand::REGISTER, kFloat, i, kFloat, i));