Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
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
9 changes: 6 additions & 3 deletions src/jit/codegenlinear.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,10 @@ void genPutArgStkSIMD12(GenTree* treeNode);
#ifdef FEATURE_HW_INTRINSICS
void genHWIntrinsic(GenTreeHWIntrinsic* node);
#if defined(_TARGET_XARCH_)
void genHWIntrinsic_FullRangeImm8(GenTreeHWIntrinsic* node, instruction ins);
void genHWIntrinsic_R_R_RM(GenTreeHWIntrinsic* node, instruction ins);
void genHWIntrinsic_R_R_RM_I(GenTreeHWIntrinsic* node, instruction ins);
void genSSEIntrinsic(GenTreeHWIntrinsic* node);
void genSSE2Intrinsic(GenTreeHWIntrinsic* node);
void genSSE3Intrinsic(GenTreeHWIntrinsic* node);
void genSSSE3Intrinsic(GenTreeHWIntrinsic* node);
void genSSE41Intrinsic(GenTreeHWIntrinsic* node);
void genSSE42Intrinsic(GenTreeHWIntrinsic* node);
void genAVXIntrinsic(GenTreeHWIntrinsic* node);
Expand All @@ -135,6 +132,12 @@ void genFMAIntrinsic(GenTreeHWIntrinsic* node);
void genLZCNTIntrinsic(GenTreeHWIntrinsic* node);
void genPCLMULQDQIntrinsic(GenTreeHWIntrinsic* node);
void genPOPCNTIntrinsic(GenTreeHWIntrinsic* node);
template <typename HWIntrinsicSwitchCaseBody>
void genHWIntrinsicJumpTableFallback(NamedIntrinsic intrinsic,
regNumber nonConstImmReg,
regNumber baseReg,
regNumber offsReg,
HWIntrinsicSwitchCaseBody emitSwCase);
#endif // defined(_TARGET_XARCH_)
#if defined(_TARGET_ARM64_)
instruction getOpForHWIntrinsic(GenTreeHWIntrinsic* node, var_types instrType);
Expand Down
10 changes: 4 additions & 6 deletions src/jit/codegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1967,6 +1967,9 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
genRangeCheck(treeNode);
break;

Expand Down Expand Up @@ -3756,12 +3759,7 @@ void CodeGen::genCodeForCmpXchg(GenTreeCmpXchg* tree)
// generate code for BoundsCheck nodes
void CodeGen::genRangeCheck(GenTree* oper)
{
#ifdef FEATURE_SIMD
noway_assert(oper->OperGet() == GT_ARR_BOUNDS_CHECK || oper->OperGet() == GT_SIMD_CHK);
#else // !FEATURE_SIMD
noway_assert(oper->OperGet() == GT_ARR_BOUNDS_CHECK);
#endif // !FEATURE_SIMD

noway_assert(oper->OperIsBoundsCheck());
GenTreeBoundsChk* bndsChk = oper->AsBoundsChk();

GenTree* arrIndex = bndsChk->gtIndex;
Expand Down
3 changes: 3 additions & 0 deletions src/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7271,6 +7271,9 @@ void Compiler::CopyTestDataToCloneTree(GenTree* from, GenTree* to)
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
CopyTestDataToCloneTree(from->gtBoundsChk.gtIndex, to->gtBoundsChk.gtIndex);
CopyTestDataToCloneTree(from->gtBoundsChk.gtArrLen, to->gtBoundsChk.gtArrLen);
return;
Expand Down
10 changes: 9 additions & 1 deletion src/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -3114,12 +3114,17 @@ class Compiler
bool compSupportsHWIntrinsic(InstructionSet isa);
bool isScalarISA(InstructionSet isa);
static int ivalOfHWIntrinsic(NamedIntrinsic intrinsic);
unsigned simdSizeOfHWIntrinsic(NamedIntrinsic intrinsic, CORINFO_SIG_INFO* sig);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can this one not be static anymore?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

No, it is calling getSIMDTypeSizeInBytes.

static int numArgsOfHWIntrinsic(NamedIntrinsic intrinsic);
static GenTree* lastOpOfHWIntrinsic(GenTreeHWIntrinsic* node, int numArgs);
static instruction insOfHWIntrinsic(NamedIntrinsic intrinsic, var_types type);
static HWIntrinsicCategory categoryOfHWIntrinsic(NamedIntrinsic intrinsic);
static HWIntrinsicFlag flagsOfHWIntrinsic(NamedIntrinsic intrinsic);
GenTree* getArgForHWIntrinsic(var_types argType, CORINFO_CLASS_HANDLE argClass);
GenTreeArgList* buildArgList(CORINFO_SIG_INFO* sig);
static int immUpperBoundOfHWIntrinsic(NamedIntrinsic intrinsic);
GenTree* impNonConstFallback(NamedIntrinsic intrinsic, var_types simdType, var_types baseType);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: It might be good to reorganize this code later. We have table lookup methods mixed in with importer methods.

static bool isImmHWIntrinsic(NamedIntrinsic intrinsic, GenTree* lastOp);
GenTree* addRangeCheckIfNeeded(NamedIntrinsic intrinsic, GenTree* lastOp, bool mustExpand);
#endif // _TARGET_XARCH_
#ifdef _TARGET_ARM64_
InstructionSet lookupHWIntrinsicISA(const char* className);
Expand Down Expand Up @@ -10039,6 +10044,9 @@ class GenTreeVisitor
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
{
GenTreeBoundsChk* const boundsChk = node->AsBoundsChk();

Expand Down
3 changes: 3 additions & 0 deletions src/jit/compiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4929,6 +4929,9 @@ void GenTree::VisitOperands(TVisitor visitor)
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
{
GenTreeBoundsChk* const boundsChk = this->AsBoundsChk();
if (visitor(boundsChk->gtIndex) == VisitResult::Abort)
Expand Down
60 changes: 59 additions & 1 deletion src/jit/emitxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,14 @@ bool emitter::IsDstDstSrcAVXInstruction(instruction ins)
case INS_psubusb:
case INS_psubusw:
case INS_psubw:
case INS_pslld:
case INS_psllq:
case INS_psllw:
case INS_psrld:
case INS_psrlq:
case INS_psrlw:
case INS_psrad:
case INS_psraw:
case INS_punpckhbw:
case INS_punpckhdq:
case INS_punpckhqdq:
Expand All @@ -209,6 +217,11 @@ bool emitter::IsDstDstSrcAVXInstruction(instruction ins)
case INS_vinsertf128:
case INS_vinserti128:
case INS_vperm2i128:
case INS_vpsrlvd:
case INS_vpsrlvq:
case INS_vpsravd:
case INS_vpsllvd:
case INS_vpsllvq:
case INS_xorpd:
case INS_xorps:
return IsAVXInstruction(ins);
Expand Down Expand Up @@ -366,7 +379,7 @@ bool TakesRexWPrefix(instruction ins, emitAttr attr)
// size specification (128 vs. 256 bits) and the operand size specification (32 vs. 64 bits), where both are
// required, the instruction must be created with the register size attribute (EA_16BYTE or EA_32BYTE),
// and here we must special case these by the opcode.
if (ins == INS_vpermq)
if (ins == INS_vpermq || ins == INS_vpsrlvq || ins == INS_vpsllvq)
{
return true;
}
Expand Down Expand Up @@ -5479,6 +5492,50 @@ void emitter::emitIns_SIMD_R_R_R(instruction ins, emitAttr attr, regNumber reg,
}
}

static bool isSseShift(instruction ins)
{
switch (ins)
{
case INS_psrldq:
case INS_pslldq:
case INS_psrld:
case INS_psrlw:
case INS_psrlq:
case INS_pslld:
case INS_psllw:
case INS_psllq:
case INS_psrad:
case INS_psraw:
return true;
default:
return false;
}
}

void emitter::emitIns_SIMD_R_R_I(instruction ins, emitAttr attr, regNumber reg, regNumber reg1, int ival)
{
// TODO-XARCH refactoring emitIns_R_R_I to handle SSE2/AVX2 shift as well as emitIns_R_I
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What about this isn't working today?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

SSE2 shift instructions require special encoding, we need to improve emitIns_R_R_I to handle https://github.com/dotnet/coreclr/blob/master/src/jit/emitxarch.cpp#L3688-L3700 as well.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could we log an actual bug, as well as this TODO?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

bool isShift = isSseShift(ins);
if (UseVEXEncoding() && !isShift)
{
emitIns_R_R_I(ins, attr, reg, reg1, ival);
}
else
{
if (reg1 != reg)
{
emitIns_R_R(INS_movaps, attr, reg, reg1);
}
// TODO-XARCH-BUG emitOutputRI cannot work with SSE2 shift instruction on imm8 > 127, so we replace it by the
// semantic alternatives. https://github.com/dotnet/coreclr/issues/16543
if (isShift && ival > 127)
{
ival = 127;
}
emitIns_R_I(ins, attr, reg, ival);
}
}

void emitter::emitIns_SIMD_R_R_R_R(
instruction ins, emitAttr attr, regNumber reg, regNumber reg1, regNumber reg2, regNumber reg3)
{
Expand Down Expand Up @@ -10746,6 +10803,7 @@ BYTE* emitter::emitOutputRI(BYTE* dst, instrDesc* id)
regOpcode = (regNumber)6;
break;
case INS_psrad:
case INS_psraw:
regOpcode = (regNumber)4;
break;
default:
Expand Down
1 change: 1 addition & 0 deletions src/jit/emitxarch.h
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,7 @@ void emitIns_SIMD_R_R_C(
instruction ins, emitAttr attr, regNumber reg, regNumber reg1, CORINFO_FIELD_HANDLE fldHnd, int offs);
void emitIns_SIMD_R_R_S(instruction ins, emitAttr attr, regNumber reg, regNumber reg1, int varx, int offs);
void emitIns_SIMD_R_R_R(instruction ins, emitAttr attr, regNumber reg, regNumber reg1, regNumber reg2);
void emitIns_SIMD_R_R_I(instruction ins, emitAttr attr, regNumber reg, regNumber reg1, int ival);
void emitIns_SIMD_R_R_R_R(
instruction ins, emitAttr attr, regNumber reg, regNumber reg1, regNumber reg2, regNumber reg3);
#endif // FEATURE_HW_INTRINSICS
Expand Down
9 changes: 9 additions & 0 deletions src/jit/flowgraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9583,6 +9583,9 @@ void Compiler::fgSimpleLowering()
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
{
// Add in a call to an error routine.
fgSetRngChkTarget(tree, false);
Expand Down Expand Up @@ -18796,6 +18799,9 @@ void Compiler::fgSetTreeSeqHelper(GenTree* tree, bool isLIR)
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
// Evaluate the trees left to right
fgSetTreeSeqHelper(tree->gtBoundsChk.gtIndex, isLIR);
fgSetTreeSeqHelper(tree->gtBoundsChk.gtArrLen, isLIR);
Expand Down Expand Up @@ -21426,6 +21432,9 @@ void Compiler::fgDebugCheckFlags(GenTree* tree)
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS

GenTreeBoundsChk* bndsChk;
bndsChk = tree->AsBoundsChk();
Expand Down
49 changes: 48 additions & 1 deletion src/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,10 @@ void GenTree::InitNodeSize()
#ifdef FEATURE_SIMD
GenTree::s_gtNodeSizes[GT_SIMD_CHK] = TREE_NODE_SZ_LARGE;
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
GenTree::s_gtNodeSizes[GT_HW_INTRINSIC_CHK] = TREE_NODE_SZ_LARGE;
#endif // FEATURE_HW_INTRINSICS

GenTree::s_gtNodeSizes[GT_ARR_ELEM] = TREE_NODE_SZ_LARGE;
GenTree::s_gtNodeSizes[GT_ARR_INDEX] = TREE_NODE_SZ_LARGE;
GenTree::s_gtNodeSizes[GT_ARR_OFFSET] = TREE_NODE_SZ_LARGE;
Expand Down Expand Up @@ -1592,6 +1596,9 @@ bool GenTree::Compare(GenTree* op1, GenTree* op2, bool swapOK)
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
return Compare(op1->gtBoundsChk.gtIndex, op2->gtBoundsChk.gtIndex) &&
Compare(op1->gtBoundsChk.gtArrLen, op2->gtBoundsChk.gtArrLen) &&
(op1->gtBoundsChk.gtThrowKind == op2->gtBoundsChk.gtThrowKind);
Expand Down Expand Up @@ -1818,6 +1825,9 @@ bool Compiler::gtHasRef(GenTree* tree, ssize_t lclNum, bool defOnly)
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
if (gtHasRef(tree->gtBoundsChk.gtIndex, lclNum, defOnly))
{
return true;
Expand Down Expand Up @@ -2236,6 +2246,9 @@ unsigned Compiler::gtHashValue(GenTree* tree)
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
hash = genTreeHashAdd(hash, gtHashValue(tree->gtBoundsChk.gtIndex));
hash = genTreeHashAdd(hash, gtHashValue(tree->gtBoundsChk.gtArrLen));
hash = genTreeHashAdd(hash, tree->gtBoundsChk.gtThrowKind);
Expand Down Expand Up @@ -2501,6 +2514,9 @@ bool Compiler::lvaLclVarRefs(GenTree* tree, GenTree** findPtr, varRefKinds* refs
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
{
if (!lvaLclVarRefsAccum(tree->gtBoundsChk.gtIndex, findPtr, refsPtr, &allVars, &trkdVars))
{
Expand Down Expand Up @@ -4911,7 +4927,11 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree)
case GT_ARR_BOUNDS_CHECK:
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS

costEx = 4; // cmp reg,reg and jae throw (not taken)
costSz = 7; // jump to cold section

Expand Down Expand Up @@ -5444,6 +5464,9 @@ GenTree** GenTree::gtGetChildPointer(GenTree* parent) const
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
if (this == parent->gtBoundsChk.gtIndex)
{
return &(parent->gtBoundsChk.gtIndex);
Expand Down Expand Up @@ -5709,6 +5732,9 @@ bool GenTree::TryGetUse(GenTree* def, GenTree*** use)
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
{
GenTreeBoundsChk* const boundsChk = this->AsBoundsChk();
if (def == boundsChk->gtIndex)
Expand Down Expand Up @@ -6048,6 +6074,9 @@ bool GenTree::OperMayThrow(Compiler* comp)
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
case GT_INDEX_ADDR:
return true;
default:
Expand Down Expand Up @@ -8192,6 +8221,9 @@ GenTree* Compiler::gtCloneExpr(
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
copy = new (this, oper)
GenTreeBoundsChk(oper, tree->TypeGet(),
gtCloneExpr(tree->gtBoundsChk.gtIndex, addFlags, deepVarNum, deepVarVal),
Expand Down Expand Up @@ -8877,6 +8909,9 @@ unsigned GenTree::NumChildren()
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
return 2;

case GT_FIELD:
Expand Down Expand Up @@ -9007,6 +9042,9 @@ GenTree* GenTree::GetChild(unsigned childNum)
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
switch (childNum)
{
case 0:
Expand Down Expand Up @@ -9306,6 +9344,9 @@ GenTreeUseEdgeIterator::GenTreeUseEdgeIterator(GenTree* node)
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
m_edge = &m_node->AsBoundsChk()->gtIndex;
assert(*m_edge != nullptr);
m_advance = &GenTreeUseEdgeIterator::AdvanceBoundsChk;
Expand Down Expand Up @@ -11855,6 +11896,9 @@ void Compiler::gtDispTree(GenTree* tree,
#ifdef FEATURE_SIMD
case GT_SIMD_CHK:
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
case GT_HW_INTRINSIC_CHK:
#endif // FEATURE_HW_INTRINSICS
gtDispVN(tree);
printf("\n");
if (!topOnly)
Expand Down Expand Up @@ -15804,6 +15848,9 @@ void Compiler::gtExtractSideEffList(GenTree* expr,
#ifdef FEATURE_SIMD
|| expr->OperGet() == GT_SIMD_CHK
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
|| expr->OperGet() == GT_HW_INTRINSIC_CHK
#endif // FEATURE_HW_INTRINSICS
)
{
gtExtractSideEffList(expr->AsBoundsChk()->gtIndex, pList, flags);
Expand Down
6 changes: 6 additions & 0 deletions src/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -1661,6 +1661,12 @@ struct GenTree
return true;
}
#endif // FEATURE_SIMD
#ifdef FEATURE_HW_INTRINSICS
if (op == GT_HW_INTRINSIC_CHK)
{
return true;
}
#endif // FEATURE_HW_INTRINSICS
return false;
}

Expand Down
Loading