Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move remaining HIR SIMDIntrinsics to SimdAsHWIntrinsic #79720

Merged
merged 22 commits into from
Dec 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e89c0ab
Updating SimdAsHWIntrinsic to handle the InitN methods
tannergooding Dec 15, 2022
3826f05
Remove SIMDIntrinsicInitN as it is dead
tannergooding Dec 15, 2022
664b347
Remove SIMDIntrinsicShiftLeftInternal and SIMDIntrinsicShiftRightInte…
tannergooding Dec 15, 2022
3302452
Remove some other dead functions from the legacy SIMD support
tannergooding Dec 15, 2022
09b4b3c
Improve the codegen for float Sse41.Insert when zero is involved
tannergooding Dec 15, 2022
471d67e
Preserve the handling around InitN for Vector2/3/4 and operands that …
tannergooding Dec 15, 2022
40e2499
Extend the contiguous argument handling to Vector64/128/256
tannergooding Dec 15, 2022
257a7a7
Fixing how `this` is spilled for the SimdAsHWIntrinsic constructors
tannergooding Dec 15, 2022
064832c
Remove SIMDIntrinsicInitArray* and SIMDIntrinsicCopyToArray*, they ar…
tannergooding Dec 15, 2022
e689ad2
Move SIMDIntrinsicInitFixed to be implemented via SimdAsHWIntrinsic a…
tannergooding Dec 15, 2022
1c68011
Apply formatting patch
tannergooding Dec 15, 2022
e27fb6d
Ensure the Unsafe.Add occurs in the right position
tannergooding Dec 16, 2022
e9fe0e1
Ensure the Vector<T> APIs that take Span<byte> and ROSpan<byte> use s…
tannergooding Dec 16, 2022
2299bd7
Ensure the Vector<T> APIs that take Span<byte>/ROSpan<byte> check for…
tannergooding Dec 16, 2022
14203ab
Wokaround an aliasing bug in GetArrayDataReference
tannergooding Dec 16, 2022
ca171fc
Ensure the right size/type is used for Vector###_Create contiguous ar…
tannergooding Dec 16, 2022
095666f
Merge remote-tracking branch 'dotnet/main'
tannergooding Dec 17, 2022
24e9525
Ensure that jitdiff --diff --pmi doesn't assert
tannergooding Dec 17, 2022
28e2366
Applying formatting patch
tannergooding Dec 17, 2022
38149d5
Ensure we don't return nullptr for a lowered node
tannergooding Dec 17, 2022
4af700e
Merge remote-tracking branch 'dotnet/main'
tannergooding Dec 21, 2022
1332a01
Ensure TYP_SIMD8 bitcast is handled in VN
tannergooding Dec 28, 2022
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
22 changes: 0 additions & 22 deletions src/coreclr/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -1075,33 +1075,11 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
void genCompareInt(GenTree* treeNode);

#ifdef FEATURE_SIMD
enum SIMDScalarMoveType{
SMT_ZeroInitUpper, // zero initlaize target upper bits
SMT_ZeroInitUpper_SrcHasUpperZeros, // zero initialize target upper bits; source upper bits are known to be zero
SMT_PreserveUpper // preserve target upper bits
};

#ifdef TARGET_ARM64
insOpts genGetSimdInsOpt(emitAttr size, var_types elementType);
#endif
#ifdef TARGET_XARCH
instruction getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_types baseType, unsigned* ival = nullptr);
#endif
void genSIMDScalarMove(
var_types targetType, var_types type, regNumber target, regNumber src, SIMDScalarMoveType moveType);
void genSIMDZero(var_types targetType, var_types baseType, regNumber targetReg);
void genSIMDIntrinsicInitN(GenTreeSIMD* simdNode);
void genSIMDIntrinsicUpperSave(GenTreeSIMD* simdNode);
void genSIMDIntrinsicUpperRestore(GenTreeSIMD* simdNode);
Copy link
Member Author

Choose a reason for hiding this comment

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

These two only exist in LIR and are created by LSRA

void genSIMDLo64BitConvert(SIMDIntrinsicID intrinsicID,
var_types simdType,
var_types baseType,
regNumber tmpReg,
regNumber tmpIntReg,
regNumber targetReg);
void genSIMDIntrinsic32BitConvert(GenTreeSIMD* simdNode);
void genSIMDIntrinsic64BitConvert(GenTreeSIMD* simdNode);
void genSIMDExtractUpperHalf(GenTreeSIMD* simdNode, regNumber srcReg, regNumber tgtReg);
void genSIMDIntrinsic(GenTreeSIMD* simdNode);
Copy link
Member Author

Choose a reason for hiding this comment

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

This can go away once we handle UpperSave/UpperRestore in a follow up PR.


// TYP_SIMD12 (i.e Vector3 of size 12 bytes) is not a hardware supported size and requires
Expand Down
74 changes: 0 additions & 74 deletions src/coreclr/jit/codegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5044,10 +5044,6 @@ void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode)

switch (simdNode->GetSIMDIntrinsicId())
{
case SIMDIntrinsicInitN:
genSIMDIntrinsicInitN(simdNode);
break;

case SIMDIntrinsicUpperSave:
genSIMDIntrinsicUpperSave(simdNode);
break;
Expand Down Expand Up @@ -5095,76 +5091,6 @@ insOpts CodeGen::genGetSimdInsOpt(emitAttr size, var_types elementType)
return result;
}

//-------------------------------------------------------------------------------------------
// genSIMDIntrinsicInitN: Generate code for SIMD Intrinsic Initialize for the form that takes
// a number of arguments equal to the length of the Vector.
//
// Arguments:
// simdNode - The GT_SIMD node
//
// Return Value:
// None.
//
void CodeGen::genSIMDIntrinsicInitN(GenTreeSIMD* simdNode)
{
assert(simdNode->GetSIMDIntrinsicId() == SIMDIntrinsicInitN);

regNumber targetReg = simdNode->GetRegNum();
assert(targetReg != REG_NA);

var_types targetType = simdNode->TypeGet();
var_types baseType = simdNode->GetSimdBaseType();
emitAttr baseTypeSize = emitTypeSize(baseType);
regNumber vectorReg = targetReg;
size_t initCount = simdNode->GetOperandCount();

assert((initCount * baseTypeSize) <= simdNode->GetSimdSize());

if (varTypeIsFloating(baseType))
{
// Note that we cannot use targetReg before consuming all float source operands.
// Therefore use an internal temp register
vectorReg = simdNode->GetSingleTempReg(RBM_ALLFLOAT);
}

// We will first consume the list items in execution (left to right) order,
// and record the registers.
regNumber operandRegs[FP_REGSIZE_BYTES];
for (size_t i = 1; i <= initCount; i++)
{
GenTree* operand = simdNode->Op(i);
assert(operand->TypeIs(baseType));
assert(!operand->isContained());

operandRegs[i - 1] = genConsumeReg(operand);
}

if (initCount * baseTypeSize < EA_16BYTE)
{
GetEmitter()->emitIns_R_I(INS_movi, EA_16BYTE, vectorReg, 0x00, INS_OPTS_16B);
}

if (varTypeIsIntegral(baseType))
{
for (unsigned i = 0; i < initCount; i++)
{
GetEmitter()->emitIns_R_R_I(INS_ins, baseTypeSize, vectorReg, operandRegs[i], i);
}
}
else
{
for (unsigned i = 0; i < initCount; i++)
{
GetEmitter()->emitIns_R_R_I_I(INS_ins, baseTypeSize, vectorReg, operandRegs[i], i, 0);
}
}

// Load the initialized value.
GetEmitter()->emitIns_Mov(INS_mov, EA_16BYTE, targetReg, vectorReg, /* canSkip */ true);

genProduceReg(simdNode);
}

//-----------------------------------------------------------------------------
// genSIMDIntrinsicUpperSave: save the upper half of a TYP_SIMD16 vector to
// the given register, if any, or to memory.
Expand Down
161 changes: 0 additions & 161 deletions src/coreclr/jit/codegenloongarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4882,167 +4882,6 @@ insOpts CodeGen::genGetSimdInsOpt(emitAttr size, var_types elementType)
return INS_OPTS_NONE;
}

// getOpForSIMDIntrinsic: return the opcode for the given SIMD Intrinsic
//
// Arguments:
// intrinsicId - SIMD intrinsic Id
// baseType - Base type of the SIMD vector
// immed - Out param. Any immediate byte operand that needs to be passed to SSE2 opcode
//
//
// Return Value:
// Instruction (op) to be used, and immed is set if instruction requires an immediate operand.
//
instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_types baseType, unsigned* ival /*=nullptr*/)
{
NYI("unimplemented on LOONGARCH64 yet");
return INS_invalid;
}

//------------------------------------------------------------------------
// genSIMDIntrinsicInit: Generate code for SIMD Intrinsic Initialize.
//
// Arguments:
// simdNode - The GT_SIMD node
//
// Return Value:
// None.
//
void CodeGen::genSIMDIntrinsicInit(GenTreeSIMD* simdNode)
{
NYI("unimplemented on LOONGARCH64 yet");
}

//-------------------------------------------------------------------------------------------
// genSIMDIntrinsicInitN: Generate code for SIMD Intrinsic Initialize for the form that takes
// a number of arguments equal to the length of the Vector.
//
// Arguments:
// simdNode - The GT_SIMD node
//
// Return Value:
// None.
//
void CodeGen::genSIMDIntrinsicInitN(GenTreeSIMD* simdNode)
{
NYI("unimplemented on LOONGARCH64 yet");
}

//----------------------------------------------------------------------------------
// genSIMDIntrinsicUnOp: Generate code for SIMD Intrinsic unary operations like sqrt.
//
// Arguments:
// simdNode - The GT_SIMD node
//
// Return Value:
// None.
//
void CodeGen::genSIMDIntrinsicUnOp(GenTreeSIMD* simdNode)
{
NYI("unimplemented on LOONGARCH64 yet");
}

//--------------------------------------------------------------------------------
// genSIMDIntrinsicWiden: Generate code for SIMD Intrinsic Widen operations
//
// Arguments:
// simdNode - The GT_SIMD node
//
// Notes:
// The Widen intrinsics are broken into separate intrinsics for the two results.
//
void CodeGen::genSIMDIntrinsicWiden(GenTreeSIMD* simdNode)
{
NYI("unimplemented on LOONGARCH64 yet");
}

//--------------------------------------------------------------------------------
// genSIMDIntrinsicNarrow: Generate code for SIMD Intrinsic Narrow operations
//
// Arguments:
// simdNode - The GT_SIMD node
//
// Notes:
// This intrinsic takes two arguments. The first operand is narrowed to produce the
// lower elements of the results, and the second operand produces the high elements.
//
void CodeGen::genSIMDIntrinsicNarrow(GenTreeSIMD* simdNode)
{
NYI("unimplemented on LOONGARCH64 yet");
}

//--------------------------------------------------------------------------------
// genSIMDIntrinsicBinOp: Generate code for SIMD Intrinsic binary operations
// add, sub, mul, bit-wise And, AndNot and Or.
//
// Arguments:
// simdNode - The GT_SIMD node
//
// Return Value:
// None.
//
void CodeGen::genSIMDIntrinsicBinOp(GenTreeSIMD* simdNode)
{
NYI("unimplemented on LOONGARCH64 yet");
}

//--------------------------------------------------------------------------------
// genSIMDIntrinsicRelOp: Generate code for a SIMD Intrinsic relational operator
// == and !=
//
// Arguments:
// simdNode - The GT_SIMD node
//
// Return Value:
// None.
//
void CodeGen::genSIMDIntrinsicRelOp(GenTreeSIMD* simdNode)
{
NYI("unimplemented on LOONGARCH64 yet");
}

//--------------------------------------------------------------------------------
// genSIMDIntrinsicDotProduct: Generate code for SIMD Intrinsic Dot Product.
//
// Arguments:
// simdNode - The GT_SIMD node
//
// Return Value:
// None.
//
void CodeGen::genSIMDIntrinsicDotProduct(GenTreeSIMD* simdNode)
{
NYI("unimplemented on LOONGARCH64 yet");
}

//------------------------------------------------------------------------------------
// genSIMDIntrinsicGetItem: Generate code for SIMD Intrinsic get element at index i.
//
// Arguments:
// simdNode - The GT_SIMD node
//
// Return Value:
// None.
//
void CodeGen::genSIMDIntrinsicGetItem(GenTreeSIMD* simdNode)
{
NYI("unimplemented on LOONGARCH64 yet");
}

//------------------------------------------------------------------------------------
// genSIMDIntrinsicSetItem: Generate code for SIMD Intrinsic set element at index i.
//
// Arguments:
// simdNode - The GT_SIMD node
//
// Return Value:
// None.
//
void CodeGen::genSIMDIntrinsicSetItem(GenTreeSIMD* simdNode)
{
NYI("unimplemented on LOONGARCH64 yet");
}

//-----------------------------------------------------------------------------
// genSIMDIntrinsicUpperSave: save the upper half of a TYP_SIMD16 vector to
// the given register, if any, or to memory.
Expand Down
23 changes: 1 addition & 22 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -8578,16 +8578,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
return getBaseJitTypeAndSizeOfSIMDType(typeHnd, nullptr);
}

// Get SIMD Intrinsic info given the method handle.
// Also sets typeHnd, argCount, baseType and sizeBytes out params.
const SIMDIntrinsicInfo* getSIMDIntrinsicInfo(CORINFO_CLASS_HANDLE* typeHnd,
CORINFO_METHOD_HANDLE methodHnd,
CORINFO_SIG_INFO* sig,
bool isNewObj,
unsigned* argCount,
CorInfoType* simdBaseJitType,
unsigned* sizeBytes);

// Pops and returns GenTree node from importers type stack.
// Normalizes TYP_STRUCT value in case of GT_CALL, GT_RET_EXPR and arg nodes.
GenTree* impSIMDPopStack(var_types type, bool expectAddr = false, CORINFO_CLASS_HANDLE structType = nullptr);
Expand All @@ -8597,18 +8587,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
bool areLocalFieldsContiguous(GenTreeLclFld* first, GenTreeLclFld* second);
bool areArrayElementsContiguous(GenTree* op1, GenTree* op2);
bool areArgumentsContiguous(GenTree* op1, GenTree* op2);
GenTree* createAddressNodeForSIMDInit(GenTree* tree, unsigned simdSize);

// check methodHnd to see if it is a SIMD method that is expanded as an intrinsic in the JIT.
GenTree* impSIMDIntrinsic(OPCODE opcode,
GenTree* newobjThis,
CORINFO_CLASS_HANDLE clsHnd,
CORINFO_METHOD_HANDLE method,
CORINFO_SIG_INFO* sig,
unsigned methodFlags,
int memberRef);

GenTree* getOp1ForConstructor(OPCODE opcode, GenTree* newobjThis, CORINFO_CLASS_HANDLE clsHnd);
GenTree* CreateAddressNodeForSimdHWIntrinsicCreate(GenTree* tree, var_types simdBaseType, unsigned simdSize);

// Whether SIMD vector occupies part of SIMD register.
// SSE2: vector2f/3f are considered sub register SIMD types.
Expand Down
18 changes: 0 additions & 18 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6457,12 +6457,6 @@ bool GenTree::OperIsImplicitIndir() const
return true;
case GT_INTRINSIC:
return AsIntrinsic()->gtIntrinsicName == NI_System_Object_GetType;
#ifdef FEATURE_SIMD
case GT_SIMD:
{
return AsSIMD()->OperIsMemoryLoad();
}
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HWINTRINSIC:
{
Expand Down Expand Up @@ -18753,18 +18747,6 @@ var_types GenTreeJitIntrinsic::GetSimdBaseType() const
return JitType2PreciseVarType(simdBaseJitType);
}

//------------------------------------------------------------------------
// OperIsMemoryLoad: Does this SIMD intrinsic have memory load semantics?
//
// Return Value:
// Whether this intrinsic may throw NullReferenceException if the
// address is "null".
//
bool GenTreeSIMD::OperIsMemoryLoad() const
{
return GetSIMDIntrinsicId() == SIMDIntrinsicInitArray;
}

/* static */ bool GenTreeSIMD::Equals(GenTreeSIMD* op1, GenTreeSIMD* op2)
{
return (op1->TypeGet() == op2->TypeGet()) && (op1->GetSIMDIntrinsicId() == op2->GetSIMDIntrinsicId()) &&
Expand Down
16 changes: 0 additions & 16 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -6330,8 +6330,6 @@ struct GenTreeSIMD : public GenTreeJitIntrinsic
}
#endif

bool OperIsMemoryLoad() const;

SIMDIntrinsicID GetSIMDIntrinsicId() const
{
return gtSIMDIntrinsicID;
Expand Down Expand Up @@ -8701,20 +8699,6 @@ inline bool GenTree::IsVectorCreate() const
}
#endif // FEATURE_HW_INTRINSICS

#ifdef FEATURE_SIMD
if (OperIs(GT_SIMD))
{
switch (AsSIMD()->GetSIMDIntrinsicId())
{
case SIMDIntrinsicInitN:
return true;

default:
return false;
}
}
#endif // FEATURE_SIMD

return false;
}

Expand Down
Loading