Skip to content

Commit 7aba441

Browse files
Move remaining HIR SIMDIntrinsics to SimdAsHWIntrinsic (#79720)
* Updating SimdAsHWIntrinsic to handle the InitN methods * Remove SIMDIntrinsicInitN as it is dead * Remove SIMDIntrinsicShiftLeftInternal and SIMDIntrinsicShiftRightInternal as they are dead * Remove some other dead functions from the legacy SIMD support * Improve the codegen for float Sse41.Insert when zero is involved * Preserve the handling around InitN for Vector2/3/4 and operands that are contiguous in memory * Extend the contiguous argument handling to Vector64/128/256 * Fixing how `this` is spilled for the SimdAsHWIntrinsic constructors * Remove SIMDIntrinsicInitArray* and SIMDIntrinsicCopyToArray*, they are handled in managed code exclusively * Move SIMDIntrinsicInitFixed to be implemented via SimdAsHWIntrinsic and remove impSIMDIntrinsic * Apply formatting patch * Ensure the Unsafe.Add occurs in the right position * Ensure the Vector<T> APIs that take Span<byte> and ROSpan<byte> use sizeof(Vector<T>) * Ensure the Vector<T> APIs that take Span<byte>/ROSpan<byte> check for unsupported types * Wokaround an aliasing bug in GetArrayDataReference * Ensure the right size/type is used for Vector###_Create contiguous args handling * Ensure that jitdiff --diff --pmi doesn't assert * Applying formatting patch * Ensure we don't return nullptr for a lowered node * Ensure TYP_SIMD8 bitcast is handled in VN
1 parent 6742b97 commit 7aba441

36 files changed

+875
-1906
lines changed

src/coreclr/jit/codegen.h

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,33 +1075,11 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10751075
void genCompareInt(GenTree* treeNode);
10761076

10771077
#ifdef FEATURE_SIMD
1078-
enum SIMDScalarMoveType{
1079-
SMT_ZeroInitUpper, // zero initlaize target upper bits
1080-
SMT_ZeroInitUpper_SrcHasUpperZeros, // zero initialize target upper bits; source upper bits are known to be zero
1081-
SMT_PreserveUpper // preserve target upper bits
1082-
};
1083-
10841078
#ifdef TARGET_ARM64
10851079
insOpts genGetSimdInsOpt(emitAttr size, var_types elementType);
10861080
#endif
1087-
#ifdef TARGET_XARCH
1088-
instruction getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_types baseType, unsigned* ival = nullptr);
1089-
#endif
1090-
void genSIMDScalarMove(
1091-
var_types targetType, var_types type, regNumber target, regNumber src, SIMDScalarMoveType moveType);
1092-
void genSIMDZero(var_types targetType, var_types baseType, regNumber targetReg);
1093-
void genSIMDIntrinsicInitN(GenTreeSIMD* simdNode);
10941081
void genSIMDIntrinsicUpperSave(GenTreeSIMD* simdNode);
10951082
void genSIMDIntrinsicUpperRestore(GenTreeSIMD* simdNode);
1096-
void genSIMDLo64BitConvert(SIMDIntrinsicID intrinsicID,
1097-
var_types simdType,
1098-
var_types baseType,
1099-
regNumber tmpReg,
1100-
regNumber tmpIntReg,
1101-
regNumber targetReg);
1102-
void genSIMDIntrinsic32BitConvert(GenTreeSIMD* simdNode);
1103-
void genSIMDIntrinsic64BitConvert(GenTreeSIMD* simdNode);
1104-
void genSIMDExtractUpperHalf(GenTreeSIMD* simdNode, regNumber srcReg, regNumber tgtReg);
11051083
void genSIMDIntrinsic(GenTreeSIMD* simdNode);
11061084

11071085
// TYP_SIMD12 (i.e Vector3 of size 12 bytes) is not a hardware supported size and requires

src/coreclr/jit/codegenarm64.cpp

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -5044,10 +5044,6 @@ void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode)
50445044

50455045
switch (simdNode->GetSIMDIntrinsicId())
50465046
{
5047-
case SIMDIntrinsicInitN:
5048-
genSIMDIntrinsicInitN(simdNode);
5049-
break;
5050-
50515047
case SIMDIntrinsicUpperSave:
50525048
genSIMDIntrinsicUpperSave(simdNode);
50535049
break;
@@ -5095,76 +5091,6 @@ insOpts CodeGen::genGetSimdInsOpt(emitAttr size, var_types elementType)
50955091
return result;
50965092
}
50975093

5098-
//-------------------------------------------------------------------------------------------
5099-
// genSIMDIntrinsicInitN: Generate code for SIMD Intrinsic Initialize for the form that takes
5100-
// a number of arguments equal to the length of the Vector.
5101-
//
5102-
// Arguments:
5103-
// simdNode - The GT_SIMD node
5104-
//
5105-
// Return Value:
5106-
// None.
5107-
//
5108-
void CodeGen::genSIMDIntrinsicInitN(GenTreeSIMD* simdNode)
5109-
{
5110-
assert(simdNode->GetSIMDIntrinsicId() == SIMDIntrinsicInitN);
5111-
5112-
regNumber targetReg = simdNode->GetRegNum();
5113-
assert(targetReg != REG_NA);
5114-
5115-
var_types targetType = simdNode->TypeGet();
5116-
var_types baseType = simdNode->GetSimdBaseType();
5117-
emitAttr baseTypeSize = emitTypeSize(baseType);
5118-
regNumber vectorReg = targetReg;
5119-
size_t initCount = simdNode->GetOperandCount();
5120-
5121-
assert((initCount * baseTypeSize) <= simdNode->GetSimdSize());
5122-
5123-
if (varTypeIsFloating(baseType))
5124-
{
5125-
// Note that we cannot use targetReg before consuming all float source operands.
5126-
// Therefore use an internal temp register
5127-
vectorReg = simdNode->GetSingleTempReg(RBM_ALLFLOAT);
5128-
}
5129-
5130-
// We will first consume the list items in execution (left to right) order,
5131-
// and record the registers.
5132-
regNumber operandRegs[FP_REGSIZE_BYTES];
5133-
for (size_t i = 1; i <= initCount; i++)
5134-
{
5135-
GenTree* operand = simdNode->Op(i);
5136-
assert(operand->TypeIs(baseType));
5137-
assert(!operand->isContained());
5138-
5139-
operandRegs[i - 1] = genConsumeReg(operand);
5140-
}
5141-
5142-
if (initCount * baseTypeSize < EA_16BYTE)
5143-
{
5144-
GetEmitter()->emitIns_R_I(INS_movi, EA_16BYTE, vectorReg, 0x00, INS_OPTS_16B);
5145-
}
5146-
5147-
if (varTypeIsIntegral(baseType))
5148-
{
5149-
for (unsigned i = 0; i < initCount; i++)
5150-
{
5151-
GetEmitter()->emitIns_R_R_I(INS_ins, baseTypeSize, vectorReg, operandRegs[i], i);
5152-
}
5153-
}
5154-
else
5155-
{
5156-
for (unsigned i = 0; i < initCount; i++)
5157-
{
5158-
GetEmitter()->emitIns_R_R_I_I(INS_ins, baseTypeSize, vectorReg, operandRegs[i], i, 0);
5159-
}
5160-
}
5161-
5162-
// Load the initialized value.
5163-
GetEmitter()->emitIns_Mov(INS_mov, EA_16BYTE, targetReg, vectorReg, /* canSkip */ true);
5164-
5165-
genProduceReg(simdNode);
5166-
}
5167-
51685094
//-----------------------------------------------------------------------------
51695095
// genSIMDIntrinsicUpperSave: save the upper half of a TYP_SIMD16 vector to
51705096
// the given register, if any, or to memory.

src/coreclr/jit/codegenloongarch64.cpp

Lines changed: 0 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -4882,167 +4882,6 @@ insOpts CodeGen::genGetSimdInsOpt(emitAttr size, var_types elementType)
48824882
return INS_OPTS_NONE;
48834883
}
48844884

4885-
// getOpForSIMDIntrinsic: return the opcode for the given SIMD Intrinsic
4886-
//
4887-
// Arguments:
4888-
// intrinsicId - SIMD intrinsic Id
4889-
// baseType - Base type of the SIMD vector
4890-
// immed - Out param. Any immediate byte operand that needs to be passed to SSE2 opcode
4891-
//
4892-
//
4893-
// Return Value:
4894-
// Instruction (op) to be used, and immed is set if instruction requires an immediate operand.
4895-
//
4896-
instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_types baseType, unsigned* ival /*=nullptr*/)
4897-
{
4898-
NYI("unimplemented on LOONGARCH64 yet");
4899-
return INS_invalid;
4900-
}
4901-
4902-
//------------------------------------------------------------------------
4903-
// genSIMDIntrinsicInit: Generate code for SIMD Intrinsic Initialize.
4904-
//
4905-
// Arguments:
4906-
// simdNode - The GT_SIMD node
4907-
//
4908-
// Return Value:
4909-
// None.
4910-
//
4911-
void CodeGen::genSIMDIntrinsicInit(GenTreeSIMD* simdNode)
4912-
{
4913-
NYI("unimplemented on LOONGARCH64 yet");
4914-
}
4915-
4916-
//-------------------------------------------------------------------------------------------
4917-
// genSIMDIntrinsicInitN: Generate code for SIMD Intrinsic Initialize for the form that takes
4918-
// a number of arguments equal to the length of the Vector.
4919-
//
4920-
// Arguments:
4921-
// simdNode - The GT_SIMD node
4922-
//
4923-
// Return Value:
4924-
// None.
4925-
//
4926-
void CodeGen::genSIMDIntrinsicInitN(GenTreeSIMD* simdNode)
4927-
{
4928-
NYI("unimplemented on LOONGARCH64 yet");
4929-
}
4930-
4931-
//----------------------------------------------------------------------------------
4932-
// genSIMDIntrinsicUnOp: Generate code for SIMD Intrinsic unary operations like sqrt.
4933-
//
4934-
// Arguments:
4935-
// simdNode - The GT_SIMD node
4936-
//
4937-
// Return Value:
4938-
// None.
4939-
//
4940-
void CodeGen::genSIMDIntrinsicUnOp(GenTreeSIMD* simdNode)
4941-
{
4942-
NYI("unimplemented on LOONGARCH64 yet");
4943-
}
4944-
4945-
//--------------------------------------------------------------------------------
4946-
// genSIMDIntrinsicWiden: Generate code for SIMD Intrinsic Widen operations
4947-
//
4948-
// Arguments:
4949-
// simdNode - The GT_SIMD node
4950-
//
4951-
// Notes:
4952-
// The Widen intrinsics are broken into separate intrinsics for the two results.
4953-
//
4954-
void CodeGen::genSIMDIntrinsicWiden(GenTreeSIMD* simdNode)
4955-
{
4956-
NYI("unimplemented on LOONGARCH64 yet");
4957-
}
4958-
4959-
//--------------------------------------------------------------------------------
4960-
// genSIMDIntrinsicNarrow: Generate code for SIMD Intrinsic Narrow operations
4961-
//
4962-
// Arguments:
4963-
// simdNode - The GT_SIMD node
4964-
//
4965-
// Notes:
4966-
// This intrinsic takes two arguments. The first operand is narrowed to produce the
4967-
// lower elements of the results, and the second operand produces the high elements.
4968-
//
4969-
void CodeGen::genSIMDIntrinsicNarrow(GenTreeSIMD* simdNode)
4970-
{
4971-
NYI("unimplemented on LOONGARCH64 yet");
4972-
}
4973-
4974-
//--------------------------------------------------------------------------------
4975-
// genSIMDIntrinsicBinOp: Generate code for SIMD Intrinsic binary operations
4976-
// add, sub, mul, bit-wise And, AndNot and Or.
4977-
//
4978-
// Arguments:
4979-
// simdNode - The GT_SIMD node
4980-
//
4981-
// Return Value:
4982-
// None.
4983-
//
4984-
void CodeGen::genSIMDIntrinsicBinOp(GenTreeSIMD* simdNode)
4985-
{
4986-
NYI("unimplemented on LOONGARCH64 yet");
4987-
}
4988-
4989-
//--------------------------------------------------------------------------------
4990-
// genSIMDIntrinsicRelOp: Generate code for a SIMD Intrinsic relational operator
4991-
// == and !=
4992-
//
4993-
// Arguments:
4994-
// simdNode - The GT_SIMD node
4995-
//
4996-
// Return Value:
4997-
// None.
4998-
//
4999-
void CodeGen::genSIMDIntrinsicRelOp(GenTreeSIMD* simdNode)
5000-
{
5001-
NYI("unimplemented on LOONGARCH64 yet");
5002-
}
5003-
5004-
//--------------------------------------------------------------------------------
5005-
// genSIMDIntrinsicDotProduct: Generate code for SIMD Intrinsic Dot Product.
5006-
//
5007-
// Arguments:
5008-
// simdNode - The GT_SIMD node
5009-
//
5010-
// Return Value:
5011-
// None.
5012-
//
5013-
void CodeGen::genSIMDIntrinsicDotProduct(GenTreeSIMD* simdNode)
5014-
{
5015-
NYI("unimplemented on LOONGARCH64 yet");
5016-
}
5017-
5018-
//------------------------------------------------------------------------------------
5019-
// genSIMDIntrinsicGetItem: Generate code for SIMD Intrinsic get element at index i.
5020-
//
5021-
// Arguments:
5022-
// simdNode - The GT_SIMD node
5023-
//
5024-
// Return Value:
5025-
// None.
5026-
//
5027-
void CodeGen::genSIMDIntrinsicGetItem(GenTreeSIMD* simdNode)
5028-
{
5029-
NYI("unimplemented on LOONGARCH64 yet");
5030-
}
5031-
5032-
//------------------------------------------------------------------------------------
5033-
// genSIMDIntrinsicSetItem: Generate code for SIMD Intrinsic set element at index i.
5034-
//
5035-
// Arguments:
5036-
// simdNode - The GT_SIMD node
5037-
//
5038-
// Return Value:
5039-
// None.
5040-
//
5041-
void CodeGen::genSIMDIntrinsicSetItem(GenTreeSIMD* simdNode)
5042-
{
5043-
NYI("unimplemented on LOONGARCH64 yet");
5044-
}
5045-
50464885
//-----------------------------------------------------------------------------
50474886
// genSIMDIntrinsicUpperSave: save the upper half of a TYP_SIMD16 vector to
50484887
// the given register, if any, or to memory.

src/coreclr/jit/compiler.h

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8574,16 +8574,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
85748574
return getBaseJitTypeAndSizeOfSIMDType(typeHnd, nullptr);
85758575
}
85768576

8577-
// Get SIMD Intrinsic info given the method handle.
8578-
// Also sets typeHnd, argCount, baseType and sizeBytes out params.
8579-
const SIMDIntrinsicInfo* getSIMDIntrinsicInfo(CORINFO_CLASS_HANDLE* typeHnd,
8580-
CORINFO_METHOD_HANDLE methodHnd,
8581-
CORINFO_SIG_INFO* sig,
8582-
bool isNewObj,
8583-
unsigned* argCount,
8584-
CorInfoType* simdBaseJitType,
8585-
unsigned* sizeBytes);
8586-
85878577
// Pops and returns GenTree node from importers type stack.
85888578
// Normalizes TYP_STRUCT value in case of GT_CALL, GT_RET_EXPR and arg nodes.
85898579
GenTree* impSIMDPopStack(var_types type, bool expectAddr = false, CORINFO_CLASS_HANDLE structType = nullptr);
@@ -8593,18 +8583,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
85938583
bool areLocalFieldsContiguous(GenTreeLclFld* first, GenTreeLclFld* second);
85948584
bool areArrayElementsContiguous(GenTree* op1, GenTree* op2);
85958585
bool areArgumentsContiguous(GenTree* op1, GenTree* op2);
8596-
GenTree* createAddressNodeForSIMDInit(GenTree* tree, unsigned simdSize);
8597-
8598-
// check methodHnd to see if it is a SIMD method that is expanded as an intrinsic in the JIT.
8599-
GenTree* impSIMDIntrinsic(OPCODE opcode,
8600-
GenTree* newobjThis,
8601-
CORINFO_CLASS_HANDLE clsHnd,
8602-
CORINFO_METHOD_HANDLE method,
8603-
CORINFO_SIG_INFO* sig,
8604-
unsigned methodFlags,
8605-
int memberRef);
8606-
8607-
GenTree* getOp1ForConstructor(OPCODE opcode, GenTree* newobjThis, CORINFO_CLASS_HANDLE clsHnd);
8586+
GenTree* CreateAddressNodeForSimdHWIntrinsicCreate(GenTree* tree, var_types simdBaseType, unsigned simdSize);
86088587

86098588
// Whether SIMD vector occupies part of SIMD register.
86108589
// SSE2: vector2f/3f are considered sub register SIMD types.

src/coreclr/jit/gentree.cpp

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6457,12 +6457,6 @@ bool GenTree::OperIsImplicitIndir() const
64576457
return true;
64586458
case GT_INTRINSIC:
64596459
return AsIntrinsic()->gtIntrinsicName == NI_System_Object_GetType;
6460-
#ifdef FEATURE_SIMD
6461-
case GT_SIMD:
6462-
{
6463-
return AsSIMD()->OperIsMemoryLoad();
6464-
}
6465-
#endif // FEATURE_SIMD
64666460
#ifdef FEATURE_HW_INTRINSICS
64676461
case GT_HWINTRINSIC:
64686462
{
@@ -18753,18 +18747,6 @@ var_types GenTreeJitIntrinsic::GetSimdBaseType() const
1875318747
return JitType2PreciseVarType(simdBaseJitType);
1875418748
}
1875518749

18756-
//------------------------------------------------------------------------
18757-
// OperIsMemoryLoad: Does this SIMD intrinsic have memory load semantics?
18758-
//
18759-
// Return Value:
18760-
// Whether this intrinsic may throw NullReferenceException if the
18761-
// address is "null".
18762-
//
18763-
bool GenTreeSIMD::OperIsMemoryLoad() const
18764-
{
18765-
return GetSIMDIntrinsicId() == SIMDIntrinsicInitArray;
18766-
}
18767-
1876818750
/* static */ bool GenTreeSIMD::Equals(GenTreeSIMD* op1, GenTreeSIMD* op2)
1876918751
{
1877018752
return (op1->TypeGet() == op2->TypeGet()) && (op1->GetSIMDIntrinsicId() == op2->GetSIMDIntrinsicId()) &&

src/coreclr/jit/gentree.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6330,8 +6330,6 @@ struct GenTreeSIMD : public GenTreeJitIntrinsic
63306330
}
63316331
#endif
63326332

6333-
bool OperIsMemoryLoad() const;
6334-
63356333
SIMDIntrinsicID GetSIMDIntrinsicId() const
63366334
{
63376335
return gtSIMDIntrinsicID;
@@ -8701,20 +8699,6 @@ inline bool GenTree::IsVectorCreate() const
87018699
}
87028700
#endif // FEATURE_HW_INTRINSICS
87038701

8704-
#ifdef FEATURE_SIMD
8705-
if (OperIs(GT_SIMD))
8706-
{
8707-
switch (AsSIMD()->GetSIMDIntrinsicId())
8708-
{
8709-
case SIMDIntrinsicInitN:
8710-
return true;
8711-
8712-
default:
8713-
return false;
8714-
}
8715-
}
8716-
#endif // FEATURE_SIMD
8717-
87188702
return false;
87198703
}
87208704

0 commit comments

Comments
 (0)