Skip to content

Commit

Permalink
Move remaining HIR SIMDIntrinsics to SimdAsHWIntrinsic (#79720)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
tannergooding committed Dec 28, 2022
1 parent 6742b97 commit 7aba441
Show file tree
Hide file tree
Showing 36 changed files with 875 additions and 1,906 deletions.
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);
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);

// 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 @@ -8574,16 +8574,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 @@ -8593,18 +8583,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

0 comments on commit 7aba441

Please sign in to comment.