Commit 7352b3f8 authored by Predrag Rudic's avatar Predrag Rudic Committed by Commit Bot

MIPS[64] Port:"[cctest] Support testing Simd128 moves and swaps"

Port 0761b55d

Original Commit Message:

"Extend the code-generator tests to cover AssembleMove and AssembleSwap with
Simd128 registers and stack slots, for targets that support them.

For this to work however, we need support for passing Simd128 stack parameters
in TurboFan which this patch implements for Arm and x86. PPC and S390 both do
not support the Simd128 representation and it appears MIPS and MIPS64's
implementation of AssembleMove and AssembleSwap do not support it either.

As per the design of the tests, the set of values to perform moves on are
represented in a FixedArray of Smis (for kTagged) and HeapNumbers (for kFloat32
and kFloat64). They are converted to raw values for the moves to be performed
on, to be then converted back into a FixedArray. For the kSimd128
representation, we represent values as a FixedArray of 4 Smis, each representing
a lane. They are converted to a raw Simd128 vector using the `I32x4ReplaceLane`
and `I32x4ExtractLane` operations.

Finally, these tests need Simd128 variables mixed with the CodeStubAssembler
which is not a use-case officially supported. And as a result, the `RecordWrite`
stub does not guarantee to preserve Simd128 registers. To get around this, we
have to be careful to skip write barriers when dealing with Simd128 parameters
inside the "teardown" function, and we've had to move all allocations to the
"setup" function.

Thanks to this, we are able to catch bugs such as this one
https://bugs.chromium.org/p/v8/issues/detail?id=6843."

Change-Id: If867dedf4a2c72cb75c58effda93e3eec432fd67
Reviewed-on: https://chromium-review.googlesource.com/906469Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Ivica Bogosavljevic <ivica.bogosavljevic@mips.com>
Cr-Commit-Position: refs/heads/master@{#51142}
parent 756c8c4e
...@@ -1677,9 +1677,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -1677,9 +1677,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
LocationOperand* op = LocationOperand::cast(instr->InputAt(0)); LocationOperand* op = LocationOperand::cast(instr->InputAt(0));
if (op->representation() == MachineRepresentation::kFloat64) { if (op->representation() == MachineRepresentation::kFloat64) {
__ Sdc1(i.InputDoubleRegister(0), MemOperand(sp, i.InputInt32(1))); __ Sdc1(i.InputDoubleRegister(0), MemOperand(sp, i.InputInt32(1)));
} else { } else if (op->representation() == MachineRepresentation::kFloat32) {
DCHECK_EQ(MachineRepresentation::kFloat32, op->representation());
__ swc1(i.InputSingleRegister(0), MemOperand(sp, i.InputInt32(1))); __ swc1(i.InputSingleRegister(0), MemOperand(sp, i.InputInt32(1)));
} else {
DCHECK_EQ(MachineRepresentation::kSimd128, op->representation());
CpuFeatureScope msa_scope(tasm(), MIPS_SIMD);
__ st_b(i.InputSimd128Register(0), MemOperand(sp, i.InputInt32(1)));
} }
} else { } else {
__ sw(i.InputRegister(0), MemOperand(sp, i.InputInt32(1))); __ sw(i.InputRegister(0), MemOperand(sp, i.InputInt32(1)));
...@@ -3498,21 +3501,33 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, ...@@ -3498,21 +3501,33 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
} }
} }
} else if (source->IsFPRegister()) { } else if (source->IsFPRegister()) {
FPURegister src = g.ToDoubleRegister(source); MachineRepresentation rep = LocationOperand::cast(source)->representation();
if (destination->IsFPRegister()) { if (rep == MachineRepresentation::kSimd128) {
FPURegister dst = g.ToDoubleRegister(destination); CpuFeatureScope msa_scope(tasm(), MIPS_SIMD);
__ Move(dst, src); MSARegister src = g.ToSimd128Register(source);
if (destination->IsSimd128Register()) {
MSARegister dst = g.ToSimd128Register(destination);
__ move_v(dst, src);
} else {
DCHECK(destination->IsSimd128StackSlot());
__ st_b(src, g.ToMemOperand(destination));
}
} else { } else {
DCHECK(destination->IsFPStackSlot()); FPURegister src = g.ToDoubleRegister(source);
MachineRepresentation rep = if (destination->IsFPRegister()) {
LocationOperand::cast(source)->representation(); FPURegister dst = g.ToDoubleRegister(destination);
if (rep == MachineRepresentation::kFloat64) { __ Move(dst, src);
__ Sdc1(src, g.ToMemOperand(destination));
} else if (rep == MachineRepresentation::kFloat32) {
__ swc1(src, g.ToMemOperand(destination));
} else { } else {
DCHECK_EQ(MachineRepresentation::kSimd128, rep); DCHECK(destination->IsFPStackSlot());
UNREACHABLE(); MachineRepresentation rep =
LocationOperand::cast(source)->representation();
if (rep == MachineRepresentation::kFloat64) {
__ Sdc1(src, g.ToMemOperand(destination));
} else if (rep == MachineRepresentation::kFloat32) {
__ swc1(src, g.ToMemOperand(destination));
} else {
UNREACHABLE();
}
} }
} }
} else if (source->IsFPStackSlot()) { } else if (source->IsFPStackSlot()) {
...@@ -3526,7 +3541,8 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, ...@@ -3526,7 +3541,8 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
__ lwc1(g.ToDoubleRegister(destination), src); __ lwc1(g.ToDoubleRegister(destination), src);
} else { } else {
DCHECK_EQ(MachineRepresentation::kSimd128, rep); DCHECK_EQ(MachineRepresentation::kSimd128, rep);
UNREACHABLE(); CpuFeatureScope msa_scope(tasm(), MIPS_SIMD);
__ ld_b(g.ToSimd128Register(destination), src);
} }
} else { } else {
FPURegister temp = kScratchDoubleReg; FPURegister temp = kScratchDoubleReg;
...@@ -3538,7 +3554,10 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, ...@@ -3538,7 +3554,10 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
__ swc1(temp, g.ToMemOperand(destination)); __ swc1(temp, g.ToMemOperand(destination));
} else { } else {
DCHECK_EQ(MachineRepresentation::kSimd128, rep); DCHECK_EQ(MachineRepresentation::kSimd128, rep);
UNREACHABLE(); CpuFeatureScope msa_scope(tasm(), MIPS_SIMD);
MSARegister temp = kSimd128ScratchReg;
__ ld_b(temp, src);
__ st_b(temp, g.ToMemOperand(destination));
} }
} }
} else { } else {
...@@ -3579,29 +3598,50 @@ void CodeGenerator::AssembleSwap(InstructionOperand* source, ...@@ -3579,29 +3598,50 @@ void CodeGenerator::AssembleSwap(InstructionOperand* source,
__ sw(temp_0, dst); __ sw(temp_0, dst);
__ sw(temp_1, src); __ sw(temp_1, src);
} else if (source->IsFPRegister()) { } else if (source->IsFPRegister()) {
FPURegister temp = kScratchDoubleReg;
FPURegister src = g.ToDoubleRegister(source);
if (destination->IsFPRegister()) { if (destination->IsFPRegister()) {
FPURegister dst = g.ToDoubleRegister(destination); MachineRepresentation rep =
__ Move(temp, src); LocationOperand::cast(source)->representation();
__ Move(src, dst); if (rep == MachineRepresentation::kSimd128) {
__ Move(dst, temp); CpuFeatureScope msa_scope(tasm(), MIPS_SIMD);
MSARegister temp = kSimd128ScratchReg;
MSARegister src = g.ToSimd128Register(source);
MSARegister dst = g.ToSimd128Register(destination);
__ move_v(temp, src);
__ move_v(src, dst);
__ move_v(dst, temp);
} else {
FPURegister temp = kScratchDoubleReg;
FPURegister src = g.ToDoubleRegister(source);
FPURegister dst = g.ToDoubleRegister(destination);
__ Move(temp, src);
__ Move(src, dst);
__ Move(dst, temp);
}
} else { } else {
DCHECK(destination->IsFPStackSlot()); DCHECK(destination->IsFPStackSlot());
MemOperand dst = g.ToMemOperand(destination); MemOperand dst = g.ToMemOperand(destination);
MachineRepresentation rep = MachineRepresentation rep =
LocationOperand::cast(source)->representation(); LocationOperand::cast(source)->representation();
if (rep == MachineRepresentation::kFloat64) { if (rep == MachineRepresentation::kFloat64) {
FPURegister temp = kScratchDoubleReg;
FPURegister src = g.ToDoubleRegister(source);
__ Move(temp, src); __ Move(temp, src);
__ Ldc1(src, dst); __ Ldc1(src, dst);
__ Sdc1(temp, dst); __ Sdc1(temp, dst);
} else if (rep == MachineRepresentation::kFloat32) { } else if (rep == MachineRepresentation::kFloat32) {
FPURegister temp = kScratchDoubleReg;
FPURegister src = g.ToFloatRegister(source);
__ Move(temp, src); __ Move(temp, src);
__ lwc1(src, dst); __ lwc1(src, dst);
__ swc1(temp, dst); __ swc1(temp, dst);
} else { } else {
DCHECK_EQ(MachineRepresentation::kSimd128, rep); DCHECK_EQ(MachineRepresentation::kSimd128, rep);
UNREACHABLE(); CpuFeatureScope msa_scope(tasm(), MIPS_SIMD);
MSARegister temp = kSimd128ScratchReg;
MSARegister src = g.ToSimd128Register(source);
__ move_v(temp, src);
__ ld_b(src, dst);
__ st_b(temp, dst);
} }
} }
} else if (source->IsFPStackSlot()) { } else if (source->IsFPStackSlot()) {
...@@ -3627,7 +3667,24 @@ void CodeGenerator::AssembleSwap(InstructionOperand* source, ...@@ -3627,7 +3667,24 @@ void CodeGenerator::AssembleSwap(InstructionOperand* source,
__ swc1(temp_1, src0); __ swc1(temp_1, src0);
} else { } else {
DCHECK_EQ(MachineRepresentation::kSimd128, rep); DCHECK_EQ(MachineRepresentation::kSimd128, rep);
UNREACHABLE(); MemOperand src1(src0.rm(), src0.offset() + kIntSize);
MemOperand dst1(dst0.rm(), dst0.offset() + kIntSize);
MemOperand src2(src0.rm(), src0.offset() + 2 * kIntSize);
MemOperand dst2(dst0.rm(), dst0.offset() + 2 * kIntSize);
MemOperand src3(src0.rm(), src0.offset() + 3 * kIntSize);
MemOperand dst3(dst0.rm(), dst0.offset() + 3 * kIntSize);
CpuFeatureScope msa_scope(tasm(), MIPS_SIMD);
MSARegister temp_1 = kSimd128ScratchReg;
__ ld_b(temp_1, dst0); // Save destination in temp_1.
__ lw(temp_0, src0); // Then use temp_0 to copy source to destination.
__ sw(temp_0, dst0);
__ lw(temp_0, src1);
__ sw(temp_0, dst1);
__ lw(temp_0, src2);
__ sw(temp_0, dst2);
__ lw(temp_0, src3);
__ sw(temp_0, dst3);
__ st_b(temp_1, src0);
} }
} else { } else {
// No other combinations are possible. // No other combinations are possible.
......
...@@ -1924,7 +1924,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -1924,7 +1924,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} }
case kMips64StoreToStackSlot: { case kMips64StoreToStackSlot: {
if (instr->InputAt(0)->IsFPRegister()) { if (instr->InputAt(0)->IsFPRegister()) {
__ Sdc1(i.InputDoubleRegister(0), MemOperand(sp, i.InputInt32(1))); if (instr->InputAt(0)->IsSimd128Register()) {
CpuFeatureScope msa_scope(tasm(), MIPS_SIMD);
__ st_b(i.InputSimd128Register(0), MemOperand(sp, i.InputInt32(1)));
} else {
__ Sdc1(i.InputDoubleRegister(0), MemOperand(sp, i.InputInt32(1)));
}
} else { } else {
__ Sd(i.InputRegister(0), MemOperand(sp, i.InputInt32(1))); __ Sd(i.InputRegister(0), MemOperand(sp, i.InputInt32(1)));
} }
...@@ -3769,23 +3774,50 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, ...@@ -3769,23 +3774,50 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
} }
} }
} else if (source->IsFPRegister()) { } else if (source->IsFPRegister()) {
FPURegister src = g.ToDoubleRegister(source); MachineRepresentation rep = LocationOperand::cast(source)->representation();
if (destination->IsFPRegister()) { if (rep == MachineRepresentation::kSimd128) {
FPURegister dst = g.ToDoubleRegister(destination); CpuFeatureScope msa_scope(tasm(), MIPS_SIMD);
__ Move(dst, src); MSARegister src = g.ToSimd128Register(source);
if (destination->IsSimd128Register()) {
MSARegister dst = g.ToSimd128Register(destination);
__ move_v(dst, src);
} else {
DCHECK(destination->IsSimd128StackSlot());
__ st_b(src, g.ToMemOperand(destination));
}
} else { } else {
DCHECK(destination->IsFPStackSlot()); FPURegister src = g.ToDoubleRegister(source);
__ Sdc1(src, g.ToMemOperand(destination)); if (destination->IsFPRegister()) {
FPURegister dst = g.ToDoubleRegister(destination);
__ Move(dst, src);
} else {
DCHECK(destination->IsFPStackSlot());
__ Sdc1(src, g.ToMemOperand(destination));
}
} }
} else if (source->IsFPStackSlot()) { } else if (source->IsFPStackSlot()) {
DCHECK(destination->IsFPRegister() || destination->IsFPStackSlot()); DCHECK(destination->IsFPRegister() || destination->IsFPStackSlot());
MemOperand src = g.ToMemOperand(source); MemOperand src = g.ToMemOperand(source);
if (destination->IsFPRegister()) { MachineRepresentation rep = LocationOperand::cast(source)->representation();
__ Ldc1(g.ToDoubleRegister(destination), src); if (rep == MachineRepresentation::kSimd128) {
CpuFeatureScope msa_scope(tasm(), MIPS_SIMD);
if (destination->IsSimd128Register()) {
__ ld_b(g.ToSimd128Register(destination), src);
} else {
DCHECK(destination->IsSimd128StackSlot());
MSARegister temp = kSimd128ScratchReg;
__ ld_b(temp, src);
__ st_b(temp, g.ToMemOperand(destination));
}
} else { } else {
FPURegister temp = kScratchDoubleReg; if (destination->IsFPRegister()) {
__ Ldc1(temp, src); __ Ldc1(g.ToDoubleRegister(destination), src);
__ Sdc1(temp, g.ToMemOperand(destination)); } else {
DCHECK(destination->IsFPStackSlot());
FPURegister temp = kScratchDoubleReg;
__ Ldc1(temp, src);
__ Sdc1(temp, g.ToMemOperand(destination));
}
} }
} else { } else {
UNREACHABLE(); UNREACHABLE();
...@@ -3825,34 +3857,73 @@ void CodeGenerator::AssembleSwap(InstructionOperand* source, ...@@ -3825,34 +3857,73 @@ void CodeGenerator::AssembleSwap(InstructionOperand* source,
__ Sd(temp_0, dst); __ Sd(temp_0, dst);
__ Sd(temp_1, src); __ Sd(temp_1, src);
} else if (source->IsFPRegister()) { } else if (source->IsFPRegister()) {
FPURegister temp = kScratchDoubleReg; MachineRepresentation rep = LocationOperand::cast(source)->representation();
FPURegister src = g.ToDoubleRegister(source); if (rep == MachineRepresentation::kSimd128) {
if (destination->IsFPRegister()) { CpuFeatureScope msa_scope(tasm(), MIPS_SIMD);
FPURegister dst = g.ToDoubleRegister(destination); MSARegister temp = kSimd128ScratchReg;
__ Move(temp, src); MSARegister src = g.ToSimd128Register(source);
__ Move(src, dst); if (destination->IsSimd128Register()) {
__ Move(dst, temp); MSARegister dst = g.ToSimd128Register(destination);
__ move_v(temp, src);
__ move_v(src, dst);
__ move_v(dst, temp);
} else {
DCHECK(destination->IsSimd128StackSlot());
MemOperand dst = g.ToMemOperand(destination);
__ move_v(temp, src);
__ ld_b(src, dst);
__ st_b(temp, dst);
}
} else { } else {
DCHECK(destination->IsFPStackSlot()); FPURegister temp = kScratchDoubleReg;
MemOperand dst = g.ToMemOperand(destination); FPURegister src = g.ToDoubleRegister(source);
__ Move(temp, src); if (destination->IsFPRegister()) {
__ Ldc1(src, dst); FPURegister dst = g.ToDoubleRegister(destination);
__ Sdc1(temp, dst); __ Move(temp, src);
__ Move(src, dst);
__ Move(dst, temp);
} else {
DCHECK(destination->IsFPStackSlot());
MemOperand dst = g.ToMemOperand(destination);
__ Move(temp, src);
__ Ldc1(src, dst);
__ Sdc1(temp, dst);
}
} }
} else if (source->IsFPStackSlot()) { } else if (source->IsFPStackSlot()) {
DCHECK(destination->IsFPStackSlot()); DCHECK(destination->IsFPStackSlot());
Register temp_0 = kScratchReg; Register temp_0 = kScratchReg;
FPURegister temp_1 = kScratchDoubleReg;
MemOperand src0 = g.ToMemOperand(source); MemOperand src0 = g.ToMemOperand(source);
MemOperand src1(src0.rm(), src0.offset() + kIntSize); MemOperand src1(src0.rm(), src0.offset() + kIntSize);
MemOperand dst0 = g.ToMemOperand(destination); MemOperand dst0 = g.ToMemOperand(destination);
MemOperand dst1(dst0.rm(), dst0.offset() + kIntSize); MemOperand dst1(dst0.rm(), dst0.offset() + kIntSize);
__ Ldc1(temp_1, dst0); // Save destination in temp_1. MachineRepresentation rep = LocationOperand::cast(source)->representation();
__ Lw(temp_0, src0); // Then use temp_0 to copy source to destination. if (rep == MachineRepresentation::kSimd128) {
__ Sw(temp_0, dst0); MemOperand src2(src0.rm(), src0.offset() + 2 * kIntSize);
__ Lw(temp_0, src1); MemOperand src3(src0.rm(), src0.offset() + 3 * kIntSize);
__ Sw(temp_0, dst1); MemOperand dst2(dst0.rm(), dst0.offset() + 2 * kIntSize);
__ Sdc1(temp_1, src0); MemOperand dst3(dst0.rm(), dst0.offset() + 3 * kIntSize);
CpuFeatureScope msa_scope(tasm(), MIPS_SIMD);
MSARegister temp_1 = kSimd128ScratchReg;
__ ld_b(temp_1, dst0); // Save destination in temp_1.
__ Lw(temp_0, src0); // Then use temp_0 to copy source to destination.
__ Sw(temp_0, dst0);
__ Lw(temp_0, src1);
__ Sw(temp_0, dst1);
__ Lw(temp_0, src2);
__ Sw(temp_0, dst2);
__ Lw(temp_0, src3);
__ Sw(temp_0, dst3);
__ st_b(temp_1, src0);
} else {
FPURegister temp_1 = kScratchDoubleReg;
__ Ldc1(temp_1, dst0); // Save destination in temp_1.
__ Lw(temp_0, src0); // Then use temp_0 to copy source to destination.
__ Sw(temp_0, dst0);
__ Lw(temp_0, src1);
__ Sw(temp_0, dst1);
__ Sdc1(temp_1, src0);
}
} else { } else {
// No other combinations are possible. // No other combinations are possible.
UNREACHABLE(); UNREACHABLE();
......
...@@ -1670,8 +1670,15 @@ void InstructionSelector::EmitPrepareArguments( ...@@ -1670,8 +1670,15 @@ void InstructionSelector::EmitPrepareArguments(
} else { } else {
int push_count = static_cast<int>(descriptor->StackParameterCount()); int push_count = static_cast<int>(descriptor->StackParameterCount());
if (push_count > 0) { if (push_count > 0) {
// Calculate needed space
int stack_size = 0;
for (PushParameter input : (*arguments)) {
if (input.node) {
stack_size += input.location.GetSizeInPointers();
}
}
Emit(kMips64StackClaim, g.NoOutput(), Emit(kMips64StackClaim, g.NoOutput(),
g.TempImmediate(push_count << kPointerSizeLog2)); g.TempImmediate(stack_size << kPointerSizeLog2));
} }
for (size_t n = 0; n < arguments->size(); ++n) { for (size_t n = 0; n < arguments->size(); ++n) {
PushParameter input = (*arguments)[n]; PushParameter input = (*arguments)[n];
......
...@@ -275,13 +275,7 @@ void PrintStateValue(std::ostream& os, Isolate* isolate, Handle<Object> value, ...@@ -275,13 +275,7 @@ void PrintStateValue(std::ostream& os, Isolate* isolate, Handle<Object> value,
} }
bool TestSimd128Moves() { bool TestSimd128Moves() {
#if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)
// TODO(mips): Implement support for the kSimd128 representation in
// AssembleMove and AssembleSwap on MIPS.
return false;
#else
return CpuFeatures::SupportsWasmSimd128(); return CpuFeatures::SupportsWasmSimd128();
#endif
} }
} // namespace } // namespace
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment