[wasm][revec] Add instruction selection for simd256

Bug: v8:12716
Change-Id: Ib94e3e99b29d6715b1465f50d0a5bdb15bcbd29b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3849644
Commit-Queue: Jie Pan <jie.pan@intel.com>
Reviewed-by: Maya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/main@{#85380}
This commit is contained in:
jiepan 2022-12-20 16:59:00 +08:00 committed by V8 LUCI CQ
parent 263493add5
commit 0c2608724e
9 changed files with 99 additions and 4 deletions

View File

@ -1473,7 +1473,13 @@ void InstructionSelector::VisitNode(Node* node) {
return VisitLoad(node);
}
case IrOpcode::kLoadTransform: {
MarkAsRepresentation(MachineRepresentation::kSimd128, node);
LoadTransformParameters params = LoadTransformParametersOf(node->op());
if (params.transformation == LoadTransformation::kS256Load32Splat ||
params.transformation == LoadTransformation::kS256Load64Splat) {
MarkAsRepresentation(MachineRepresentation::kSimd256, node);
} else {
MarkAsRepresentation(MachineRepresentation::kSimd128, node);
}
return VisitLoadTransform(node);
}
case IrOpcode::kLoadLane: {
@ -2378,6 +2384,14 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsSimd128(node), VisitI16x8DotI8x16I7x16S(node);
case IrOpcode::kI32x4DotI8x16I7x16AddS:
return MarkAsSimd128(node), VisitI32x4DotI8x16I7x16AddS(node);
// SIMD256
#if V8_TARGET_ARCH_X64
case IrOpcode::kF32x8Add:
return MarkAsSimd256(node), VisitF32x8Add(node);
case IrOpcode::kF32x8Sub:
return MarkAsSimd256(node), VisitF32x8Sub(node);
#endif // V8_TARGET_ARCH_X64
default:
FATAL("Unexpected operator #%d:%s @ node #%d", node->opcode(),
node->op()->mnemonic(), node->id());

View File

@ -518,6 +518,9 @@ class V8_EXPORT_PRIVATE InstructionSelector final {
void MarkAsSimd128(Node* node) {
MarkAsRepresentation(MachineRepresentation::kSimd128, node);
}
void MarkAsSimd256(Node* node) {
MarkAsRepresentation(MachineRepresentation::kSimd256, node);
}
void MarkAsTagged(Node* node) {
MarkAsRepresentation(MachineRepresentation::kTagged, node);
}

View File

@ -224,6 +224,11 @@ std::ostream& operator<<(std::ostream& os, const InstructionOperand& op) {
} else if (op.IsFloatRegister()) {
os << "[" << FloatRegister::from_code(allocated.register_code())
<< "|R";
#if V8_TARGET_ARCH_X64
} else if (op.IsSimd256Register()) {
os << "[" << Simd256Register::from_code(allocated.register_code())
<< "|R";
#endif // V8_TARGET_ARCH_X64
} else {
DCHECK(op.IsSimd128Register());
os << "[" << Simd128Register::from_code(allocated.register_code())

View File

@ -93,12 +93,14 @@ class V8_EXPORT_PRIVATE INSTRUCTION_OPERAND_ALIGN InstructionOperand {
inline bool IsFloatRegister() const;
inline bool IsDoubleRegister() const;
inline bool IsSimd128Register() const;
inline bool IsSimd256Register() const;
inline bool IsAnyStackSlot() const;
inline bool IsStackSlot() const;
inline bool IsFPStackSlot() const;
inline bool IsFloatStackSlot() const;
inline bool IsDoubleStackSlot() const;
inline bool IsSimd128StackSlot() const;
inline bool IsSimd256StackSlot() const;
template <typename SubKindOperand>
static SubKindOperand* New(Zone* zone, const SubKindOperand& op) {
@ -536,6 +538,13 @@ class LocationOperand : public InstructionOperand {
return Simd128Register::from_code(register_code());
}
#if defined(V8_TARGET_ARCH_X64)
Simd256Register GetSimd256Register() const {
DCHECK(IsSimd256Register());
return Simd256Register::from_code(register_code());
}
#endif
LocationKind location_kind() const {
return LocationKindField::decode(value_);
}
@ -654,6 +663,11 @@ bool InstructionOperand::IsSimd128Register() const {
MachineRepresentation::kSimd128;
}
bool InstructionOperand::IsSimd256Register() const {
return IsAnyRegister() && LocationOperand::cast(this)->representation() ==
MachineRepresentation::kSimd256;
}
bool InstructionOperand::IsAnyStackSlot() const {
return IsAnyLocationOperand() &&
LocationOperand::cast(this)->location_kind() ==
@ -694,6 +708,14 @@ bool InstructionOperand::IsSimd128StackSlot() const {
MachineRepresentation::kSimd128;
}
bool InstructionOperand::IsSimd256StackSlot() const {
return IsAnyLocationOperand() &&
LocationOperand::cast(this)->location_kind() ==
LocationOperand::STACK_SLOT &&
LocationOperand::cast(this)->representation() ==
MachineRepresentation::kSimd256;
}
uint64_t InstructionOperand::GetCanonicalizedValue() const {
if (IsAnyLocationOperand()) {
MachineRepresentation canonical = MachineRepresentation::kNone;
@ -1712,7 +1734,8 @@ class V8_EXPORT_PRIVATE InstructionSequence final
constexpr int kFPRepMask =
RepresentationBit(MachineRepresentation::kFloat32) |
RepresentationBit(MachineRepresentation::kFloat64) |
RepresentationBit(MachineRepresentation::kSimd128);
RepresentationBit(MachineRepresentation::kSimd128) |
RepresentationBit(MachineRepresentation::kSimd256);
return (representation_mask() & kFPRepMask) != 0;
}

View File

@ -4577,6 +4577,14 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kAtomicLoadUint16:
case kAtomicLoadWord32:
UNREACHABLE(); // Won't be generated by instruction selector.
// SIMD256
case kX64F32x8Add:
case kX64F32x8Sub:
case kX64S256Load32Splat:
case kX64S256Load64Splat:
case kX64Movdqu256:
UNIMPLEMENTED();
}
return kSuccess;
} // NOLadability/fn_size)

View File

@ -56,7 +56,10 @@ namespace compiler {
V(X64Word64AtomicOrUint64) \
V(X64Word64AtomicXorUint64) \
V(X64Word64AtomicExchangeUint64) \
V(X64Word64AtomicCompareExchangeUint64)
V(X64Word64AtomicCompareExchangeUint64) \
V(X64Movdqu256) \
V(X64S256Load32Splat) \
V(X64S256Load64Splat)
#define TARGET_ARCH_OPCODE_LIST(V) \
TARGET_ARCH_OPCODE_WITH_MEMORY_ACCESS_MODE_LIST(V) \
@ -413,7 +416,9 @@ namespace compiler {
V(X64Blendvpd) \
V(X64Blendvps) \
V(X64Pblendvb) \
V(X64TraceInstruction)
V(X64TraceInstruction) \
V(X64F32x8Add) \
V(X64F32x8Sub)
// Addressing modes represent the "shape" of inputs to an instruction.
// Many instructions support multiple addressing modes. Addressing modes

View File

@ -167,7 +167,9 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kX64F32x4Neg:
case kX64F32x4Sqrt:
case kX64F32x4Add:
case kX64F32x8Add:
case kX64F32x4Sub:
case kX64F32x8Sub:
case kX64F32x4Mul:
case kX64F32x4Div:
case kX64F32x4Min:
@ -410,10 +412,13 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kX64Movsd:
case kX64Movss:
case kX64Movdqu:
case kX64Movdqu256:
case kX64S128Load8Splat:
case kX64S128Load16Splat:
case kX64S128Load32Splat:
case kX64S256Load32Splat:
case kX64S128Load64Splat:
case kX64S256Load64Splat:
case kX64S128Load8x8S:
case kX64S128Load8x8U:
case kX64S128Load16x4S:

View File

@ -338,6 +338,8 @@ ArchOpcode GetLoadOpcode(LoadRepresentation load_rep) {
opcode = kX64Movdqu;
break;
case MachineRepresentation::kSimd256: // Fall through.
opcode = kX64Movdqu256;
break;
case MachineRepresentation::kNone: // Fall through.
case MachineRepresentation::kMapWord: // Fall through.
UNREACHABLE();
@ -376,6 +378,7 @@ ArchOpcode GetStoreOpcode(StoreRepresentation store_rep) {
case MachineRepresentation::kSimd128:
return kX64Movdqu;
case MachineRepresentation::kSimd256: // Fall through.
return kX64Movdqu256;
case MachineRepresentation::kNone: // Fall through.
case MachineRepresentation::kMapWord: // Fall through.
UNREACHABLE();
@ -509,6 +512,13 @@ void InstructionSelector::VisitLoadTransform(Node* node) {
case LoadTransformation::kS128Load64Zero:
opcode = kX64Movsd;
break;
// Simd256
case LoadTransformation::kS256Load32Splat:
opcode = kX64S256Load32Splat;
break;
case LoadTransformation::kS256Load64Splat:
opcode = kX64S256Load64Splat;
break;
default:
UNREACHABLE();
}
@ -3357,6 +3367,10 @@ VISIT_ATOMIC_BINOP(Xor)
V(S128Or) \
V(S128Xor)
#define SIMD256_BINOP_SSE_AVX_LIST(V) \
V(F32x8Add) \
V(F32x8Sub)
#define SIMD_BINOP_LIST(V) \
V(F64x2Min) \
V(F64x2Max) \
@ -3603,9 +3617,19 @@ SIMD_BINOP_LIST(VISIT_SIMD_BINOP)
g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); \
} \
}
#define VISIT_SIMD256_BINOP(Opcode) \
void InstructionSelector::Visit##Opcode(Node* node) { \
X64OperandGenerator g(this); \
Emit(kX64##Opcode, g.DefineAsRegister(node), \
g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); \
}
SIMD_BINOP_SSE_AVX_LIST(VISIT_SIMD_BINOP)
SIMD256_BINOP_SSE_AVX_LIST(VISIT_SIMD256_BINOP)
#undef VISIT_SIMD_BINOP
#undef VISIT_SIMD256_BINOP
#undef SIMD_BINOP_SSE_AVX_LIST
#undef SIMD256_BINOP_SSE_AVX_LIST
void InstructionSelector::VisitV128AnyTrue(Node* node) {
X64OperandGenerator g(this);

View File

@ -770,6 +770,10 @@ void GraphC1Visualizer::PrintLiveRange(const LiveRange* range, const char* type,
os_ << " \"" << DoubleRegister::from_code(op.register_code()) << "\"";
} else if (op.IsFloatRegister()) {
os_ << " \"" << FloatRegister::from_code(op.register_code()) << "\"";
#if defined(V8_TARGET_ARCH_X64)
} else if (op.IsSimd256Register()) {
os_ << " \"" << Simd256Register::from_code(op.register_code()) << "\"";
#endif
} else {
DCHECK(op.IsSimd128Register());
os_ << " \"" << Simd128Register::from_code(op.register_code()) << "\"";
@ -1235,6 +1239,10 @@ std::ostream& operator<<(std::ostream& os, const InstructionOperandAsJSON& o) {
os << DoubleRegister::from_code(allocated->register_code());
} else if (op->IsFloatRegister()) {
os << FloatRegister::from_code(allocated->register_code());
#if defined(V8_TARGET_ARCH_X64)
} else if (op->IsSimd256Register()) {
os << Simd256Register::from_code(allocated->register_code());
#endif
} else {
DCHECK(op->IsSimd128Register());
os << Simd128Register::from_code(allocated->register_code());