Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions src/coreclr/jit/hwintrinsiccodegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2285,12 +2285,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)

case NI_Sve_Scatter:
case NI_Sve_Scatter16BitNarrowing:
case NI_Sve_Scatter16BitWithByteOffsetsNarrowing:
case NI_Sve_Scatter32BitNarrowing:
case NI_Sve_Scatter32BitWithByteOffsetsNarrowing:
case NI_Sve_Scatter8BitNarrowing:
case NI_Sve_Scatter8BitWithByteOffsetsNarrowing:
case NI_Sve_ScatterWithByteOffsets:
{
if (!varTypeIsSIMD(intrin.op2->gtType))
{
Expand Down Expand Up @@ -2325,6 +2321,23 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
break;
}

case NI_Sve_Scatter16BitWithByteOffsetsNarrowing:
case NI_Sve_Scatter32BitWithByteOffsetsNarrowing:
case NI_Sve_Scatter8BitWithByteOffsetsNarrowing:
case NI_Sve_ScatterWithByteOffsets:
Comment on lines +2324 to +2327
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Were there any other instructions (such as gather) which differed between indices vs offsets like these ones?

I know we've reviewed/approved a few groups, but I don't know which are actually implemented today.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found the following APIs that are incorrectly treating offsets as indices and would need a similar fix.

GatherVectorInt16WithByteOffsetsSignExtend (long/ulong combinations)
GatherVectorInt32WithByteOffsetsSignExtend (long/ulong)
GatherVectorInt16WithByteOffsetsSignExtendFirstFaulting (long/ulong)
GatherVectorInt32WithByteOffsetsSignExtendFirstFaulting (long/ulong)
GatherVectorUInt16WithByteOffsetsZeroExtend (long/ulong)
GatherVectorUInt16WithByteOffsetsZeroExtendFirstFaulting (long/ulong)
GatherVectorUInt32WithByteOffsetsZeroExtend(long/ulong)

Do you recommend a separate PR for the above or should put in the current one?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since its the same general issue and we're looking at backporting, I'd put them in the same PR

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should make sure these ones still get a fix done and also included in the backport

{
emitAttr baseSize = emitActualTypeSize(intrin.baseType);

if (baseSize == EA_4BYTE)
{
opt = varTypeIsUnsigned(node->GetAuxiliaryType()) ? INS_OPTS_SCALABLE_S_UXTW
: INS_OPTS_SCALABLE_S_SXTW;
}

GetEmitter()->emitIns_R_R_R_R(ins, emitSize, op4Reg, op1Reg, op2Reg, op3Reg, opt);
break;
}

case NI_Sve_StoreNarrowing:
opt = emitter::optGetSveInsOpt(emitTypeSize(intrin.baseType));
GetEmitter()->emitIns_R_R_R_I(ins, emitSize, op3Reg, op1Reg, op2Reg, 0, opt);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9074,73 +9074,73 @@ internal Arm64() { }
/// void svst1_scatter_[s64]offset[_f64](svbool_t pg, float64_t *base, svint64_t offsets, svfloat64_t data)
/// ST1D Zdata.D, Pg, [Xbase, Zoffsets.D]
/// </summary>
public static unsafe void ScatterWithByteOffsets(Vector<double> mask, double* address, Vector<long> offsets, Vector<double> data) => Scatter(mask, address, offsets, data);
public static unsafe void ScatterWithByteOffsets(Vector<double> mask, double* address, Vector<long> offsets, Vector<double> data) => ScatterWithByteOffsets(mask, address, offsets, data);

/// <summary>
/// void svst1_scatter_[u64]offset[_f64](svbool_t pg, float64_t *base, svuint64_t offsets, svfloat64_t data)
/// ST1D Zdata.D, Pg, [Xbase, Zoffsets.D]
/// </summary>
public static unsafe void ScatterWithByteOffsets(Vector<double> mask, double* address, Vector<ulong> offsets, Vector<double> data) => Scatter(mask, address, offsets, data);
public static unsafe void ScatterWithByteOffsets(Vector<double> mask, double* address, Vector<ulong> offsets, Vector<double> data) => ScatterWithByteOffsets(mask, address, offsets, data);

/// <summary>
/// void svst1_scatter_[s32]offset[_s32](svbool_t pg, int32_t *base, svint32_t offsets, svint32_t data)
/// ST1W Zdata.S, Pg, [Xbase, Zoffsets.S, SXTW]
/// </summary>
public static unsafe void ScatterWithByteOffsets(Vector<int> mask, int* address, Vector<int> offsets, Vector<int> data) => Scatter(mask, address, offsets, data);
public static unsafe void ScatterWithByteOffsets(Vector<int> mask, int* address, Vector<int> offsets, Vector<int> data) => ScatterWithByteOffsets(mask, address, offsets, data);

/// <summary>
/// void svst1_scatter_[u32]offset[_s32](svbool_t pg, int32_t *base, svuint32_t offsets, svint32_t data)
/// ST1W Zdata.S, Pg, [Xbase, Zoffsets.S, UXTW]
/// </summary>
public static unsafe void ScatterWithByteOffsets(Vector<int> mask, int* address, Vector<uint> offsets, Vector<int> data) => Scatter(mask, address, offsets, data);
public static unsafe void ScatterWithByteOffsets(Vector<int> mask, int* address, Vector<uint> offsets, Vector<int> data) => ScatterWithByteOffsets(mask, address, offsets, data);

/// <summary>
/// void svst1_scatter_[s64]offset[_s64](svbool_t pg, int64_t *base, svint64_t offsets, svint64_t data)
/// ST1D Zdata.D, Pg, [Xbase, Zoffsets.D]
/// </summary>
public static unsafe void ScatterWithByteOffsets(Vector<long> mask, long* address, Vector<long> offsets, Vector<long> data) => Scatter(mask, address, offsets, data);
public static unsafe void ScatterWithByteOffsets(Vector<long> mask, long* address, Vector<long> offsets, Vector<long> data) => ScatterWithByteOffsets(mask, address, offsets, data);

/// <summary>
/// void svst1_scatter_[u64]offset[_s64](svbool_t pg, int64_t *base, svuint64_t offsets, svint64_t data)
/// ST1D Zdata.D, Pg, [Xbase, Zoffsets.D]
/// </summary>
public static unsafe void ScatterWithByteOffsets(Vector<long> mask, long* address, Vector<ulong> offsets, Vector<long> data) => Scatter(mask, address, offsets, data);
public static unsafe void ScatterWithByteOffsets(Vector<long> mask, long* address, Vector<ulong> offsets, Vector<long> data) => ScatterWithByteOffsets(mask, address, offsets, data);

/// <summary>
/// void svst1_scatter_[s32]offset[_f32](svbool_t pg, float32_t *base, svint32_t offsets, svfloat32_t data)
/// ST1W Zdata.S, Pg, [Xbase, Zoffsets.S, SXTW]
/// </summary>
public static unsafe void ScatterWithByteOffsets(Vector<float> mask, float* address, Vector<int> offsets, Vector<float> data) => Scatter(mask, address, offsets, data);
public static unsafe void ScatterWithByteOffsets(Vector<float> mask, float* address, Vector<int> offsets, Vector<float> data) => ScatterWithByteOffsets(mask, address, offsets, data);

/// <summary>
/// void svst1_scatter_[u32]offset[_f32](svbool_t pg, float32_t *base, svuint32_t offsets, svfloat32_t data)
/// ST1W Zdata.S, Pg, [Xbase, Zoffsets.S, UXTW]
/// </summary>
public static unsafe void ScatterWithByteOffsets(Vector<float> mask, float* address, Vector<uint> offsets, Vector<float> data) => Scatter(mask, address, offsets, data);
public static unsafe void ScatterWithByteOffsets(Vector<float> mask, float* address, Vector<uint> offsets, Vector<float> data) => ScatterWithByteOffsets(mask, address, offsets, data);

/// <summary>
/// void svst1_scatter_[s32]offset[_u32](svbool_t pg, uint32_t *base, svint32_t offsets, svuint32_t data)
/// ST1W Zdata.S, Pg, [Xbase, Zoffsets.S, SXTW]
/// </summary>
public static unsafe void ScatterWithByteOffsets(Vector<uint> mask, uint* address, Vector<int> offsets, Vector<uint> data) => Scatter(mask, address, offsets, data);
public static unsafe void ScatterWithByteOffsets(Vector<uint> mask, uint* address, Vector<int> offsets, Vector<uint> data) => ScatterWithByteOffsets(mask, address, offsets, data);

/// <summary>
/// void svst1_scatter_[u32]offset[_u32](svbool_t pg, uint32_t *base, svuint32_t offsets, svuint32_t data)
/// ST1W Zdata.S, Pg, [Xbase, Zoffsets.S, UXTW]
/// </summary>
public static unsafe void ScatterWithByteOffsets(Vector<uint> mask, uint* address, Vector<uint> offsets, Vector<uint> data) => Scatter(mask, address, offsets, data);
public static unsafe void ScatterWithByteOffsets(Vector<uint> mask, uint* address, Vector<uint> offsets, Vector<uint> data) => ScatterWithByteOffsets(mask, address, offsets, data);

/// <summary>
/// void svst1_scatter_[s64]offset[_u64](svbool_t pg, uint64_t *base, svint64_t offsets, svuint64_t data)
/// ST1D Zdata.D, Pg, [Xbase, Zoffsets.D]
/// </summary>
public static unsafe void ScatterWithByteOffsets(Vector<ulong> mask, ulong* address, Vector<long> offsets, Vector<ulong> data) => Scatter(mask, address, offsets, data);
public static unsafe void ScatterWithByteOffsets(Vector<ulong> mask, ulong* address, Vector<long> offsets, Vector<ulong> data) => ScatterWithByteOffsets(mask, address, offsets, data);

/// <summary>
/// void svst1_scatter_[u64]offset[_u64](svbool_t pg, uint64_t *base, svuint64_t offsets, svuint64_t data)
/// ST1D Zdata.D, Pg, [Xbase, Zoffsets.D]
/// </summary>
public static unsafe void ScatterWithByteOffsets(Vector<ulong> mask, ulong* address, Vector<ulong> offsets, Vector<ulong> data) => Scatter(mask, address, offsets, data);
public static unsafe void ScatterWithByteOffsets(Vector<ulong> mask, ulong* address, Vector<ulong> offsets, Vector<ulong> data) => ScatterWithByteOffsets(mask, address, offsets, data);


// Write to the first-fault register
Expand Down
Loading
Loading