From 96150f2d489a6d8f5eb235ec30453b0232a57fdb Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Thu, 25 Nov 2021 23:07:20 +0300 Subject: [PATCH 1/4] Delete GT_SIMD_CHK and GT_HW_INTRINSIC_CHK The former was unused, the latter - barely used. Overall, there is no need for these to be separate opers, it just leads to unnecessary `#ifdef`s. --- src/coreclr/jit/assertionprop.cpp | 17 +-- src/coreclr/jit/codegenarmarch.cpp | 12 +-- src/coreclr/jit/codegenxarch.cpp | 10 +- src/coreclr/jit/earlyprop.cpp | 4 +- src/coreclr/jit/flowgraph.cpp | 12 +-- src/coreclr/jit/gentree.cpp | 109 +++++++------------- src/coreclr/jit/gentree.h | 56 ++++------ src/coreclr/jit/gtlist.h | 17 +-- src/coreclr/jit/gtstructs.h | 8 +- src/coreclr/jit/hwintrinsic.cpp | 12 +-- src/coreclr/jit/hwintrinsiccodegenxarch.cpp | 2 +- src/coreclr/jit/importer.cpp | 4 +- src/coreclr/jit/liveness.cpp | 8 +- src/coreclr/jit/loopcloning.cpp | 8 +- src/coreclr/jit/lower.cpp | 8 +- src/coreclr/jit/lowerarmarch.cpp | 10 +- src/coreclr/jit/lowerxarch.cpp | 2 +- src/coreclr/jit/lsraarm.cpp | 9 +- src/coreclr/jit/lsraarm64.cpp | 8 +- src/coreclr/jit/lsraxarch.cpp | 9 +- src/coreclr/jit/morph.cpp | 21 ++-- src/coreclr/jit/optcse.cpp | 2 +- src/coreclr/jit/optimizer.cpp | 6 +- src/coreclr/jit/rangecheck.cpp | 11 +- src/coreclr/jit/simd.cpp | 11 +- src/coreclr/jit/stacklevelsetter.cpp | 8 +- src/coreclr/jit/valuenum.cpp | 24 +---- src/coreclr/jit/valuenum.h | 4 +- 28 files changed, 127 insertions(+), 285 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 1ae2176674a7d8..12634c97814c26 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -1261,7 +1261,7 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, AssertionDsc assertion = {OAK_INVALID}; assert(assertion.assertionKind == OAK_INVALID); - if (op1->gtOper == GT_ARR_BOUNDS_CHECK) + if (op1->OperIs(GT_BOUNDS_CHECK) && op1->AsBoundsChk()->IsArrayBoundsCheck()) { if (assertionKind == OAK_NO_THROW) { @@ -2583,8 +2583,8 @@ void Compiler::optAssertionGen(GenTree* tree) assertionInfo = optCreateAssertion(tree->AsArrLen()->ArrRef(), nullptr, OAK_NOT_EQUAL); break; - case GT_ARR_BOUNDS_CHECK: - if (!optLocalAssertionProp) + case GT_BOUNDS_CHECK: + if (!optLocalAssertionProp && tree->AsBoundsChk()->IsArrayBoundsCheck()) { assertionInfo = optCreateAssertion(tree, nullptr, OAK_NO_THROW); } @@ -4053,7 +4053,7 @@ GenTree* Compiler::optAssertionProp_Comma(ASSERT_VALARG_TP assertions, GenTree* { // Remove the bounds check as part of the GT_COMMA node since we need parent pointer to remove nodes. // When processing visits the bounds check, it sets the throw kind to None if the check is redundant. - if ((tree->gtGetOp1()->OperGet() == GT_ARR_BOUNDS_CHECK) && + if (tree->gtGetOp1()->OperIs(GT_BOUNDS_CHECK) && tree->gtGetOp1()->AsBoundsChk()->IsArrayBoundsCheck() && ((tree->gtGetOp1()->gtFlags & GTF_ARR_BOUND_INBND) != 0)) { optRemoveCommaBasedRangeCheck(tree, stmt); @@ -4391,7 +4391,12 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree return nullptr; } - assert(tree->gtOper == GT_ARR_BOUNDS_CHECK); + assert(tree->OperIs(GT_BOUNDS_CHECK)); + + if (!tree->AsBoundsChk()->IsArrayBoundsCheck()) + { + return nullptr; + } #ifdef FEATURE_ENABLE_NO_RANGE_CHECKS if (JitConfig.JitNoRangeChks()) @@ -4610,7 +4615,7 @@ GenTree* Compiler::optAssertionProp(ASSERT_VALARG_TP assertions, GenTree* tree, case GT_NULLCHECK: return optAssertionProp_Ind(assertions, tree, stmt); - case GT_ARR_BOUNDS_CHECK: + case GT_BOUNDS_CHECK: return optAssertionProp_BndsChk(assertions, tree, stmt); case GT_COMMA: diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index 19a24869146225..791fed1f1ab7fb 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -462,13 +462,7 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) instGen(INS_nop); break; - case GT_ARR_BOUNDS_CHECK: -#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_BOUNDS_CHECK: genRangeCheck(treeNode); break; @@ -1418,11 +1412,11 @@ void CodeGen::genMultiRegStoreToSIMDLocal(GenTreeLclVar* lclNode) #endif // FEATURE_SIMD //------------------------------------------------------------------------ -// genRangeCheck: generate code for GT_ARR_BOUNDS_CHECK node. +// genRangeCheck: generate code for GT_BOUNDS_CHECK node. // void CodeGen::genRangeCheck(GenTree* oper) { - noway_assert(oper->OperIsBoundsCheck()); + noway_assert(oper->OperIs(GT_BOUNDS_CHECK)); GenTreeBoundsChk* bndsChk = oper->AsBoundsChk(); GenTree* arrLen = bndsChk->GetArrayLength(); diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 7b50388ad3138b..7da0bd72856251 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -1742,13 +1742,7 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) GetEmitter()->emitIns_Nop(1); break; - case GT_ARR_BOUNDS_CHECK: -#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_BOUNDS_CHECK: genRangeCheck(treeNode); break; @@ -3864,7 +3858,7 @@ void CodeGen::genCodeForCmpXchg(GenTreeCmpXchg* tree) // generate code for BoundsCheck nodes void CodeGen::genRangeCheck(GenTree* oper) { - noway_assert(oper->OperIsBoundsCheck()); + noway_assert(oper->OperIs(GT_BOUNDS_CHECK)); GenTreeBoundsChk* bndsChk = oper->AsBoundsChk(); GenTree* arrIndex = bndsChk->GetIndex(); diff --git a/src/coreclr/jit/earlyprop.cpp b/src/coreclr/jit/earlyprop.cpp index e4b29df2166dd9..f00b3f6e3ad6e6 100644 --- a/src/coreclr/jit/earlyprop.cpp +++ b/src/coreclr/jit/earlyprop.cpp @@ -288,13 +288,13 @@ GenTree* Compiler::optEarlyPropRewriteTree(GenTree* tree, LocalNumberToNullCheck return nullptr; } - // When replacing GT_ARR_LENGTH nodes with constants we can end up with GT_ARR_BOUNDS_CHECK + // When replacing GT_ARR_LENGTH nodes with constants we can end up with GT_BOUNDS_CHECK // nodes that have constant operands and thus can be trivially proved to be useless. It's // better to remove these range checks here, otherwise they'll pass through assertion prop // (creating useless (c1 < c2)-like assertions) and reach RangeCheck where they are finally // removed. Common patterns like new int[] { x, y, z } benefit from this. - if ((tree->gtNext != nullptr) && tree->gtNext->OperIs(GT_ARR_BOUNDS_CHECK)) + if ((tree->gtNext != nullptr) && tree->gtNext->OperIs(GT_BOUNDS_CHECK)) { GenTreeBoundsChk* check = tree->gtNext->AsBoundsChk(); diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index 859ea08aed822e..841cc6bdea853c 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -2940,7 +2940,7 @@ void Compiler::fgFindOperOrder() // and computing lvaOutgoingArgSpaceSize. // // Notes: -// Lowers GT_ARR_LENGTH, GT_ARR_BOUNDS_CHECK, and GT_SIMD_CHK. +// Lowers GT_ARR_LENGTH, GT_BOUNDS_CHECK. // // For target ABIs with fixed out args area, computes upper bound on // the size of this area from the calls in the IR. @@ -3003,13 +3003,7 @@ void Compiler::fgSimpleLowering() break; } - case GT_ARR_BOUNDS_CHECK: -#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_BOUNDS_CHECK: { // Add in a call to an error routine. fgSetRngChkTarget(tree, false); @@ -4479,7 +4473,7 @@ void Compiler::fgSetBlockOrder(BasicBlock* block) } break; - case GT_ARR_BOUNDS_CHECK: + case GT_BOUNDS_CHECK: return Compiler::WALK_ABORT; default: diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 7c0f79288f5226..9e559c683ed466 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -244,43 +244,36 @@ void GenTree::InitNodeSize() GenTree::s_gtNodeSizes[GT_RETURN] = TREE_NODE_SZ_LARGE; } - GenTree::s_gtNodeSizes[GT_CALL] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_CAST] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_FTN_ADDR] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_BOX] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_INDEX] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_INDEX_ADDR] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_ARR_BOUNDS_CHECK] = TREE_NODE_SZ_SMALL; -#ifdef FEATURE_SIMD - GenTree::s_gtNodeSizes[GT_SIMD_CHK] = TREE_NODE_SZ_SMALL; -#endif // FEATURE_SIMD -#ifdef FEATURE_HW_INTRINSICS - GenTree::s_gtNodeSizes[GT_HW_INTRINSIC_CHK] = TREE_NODE_SZ_SMALL; -#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; - GenTree::s_gtNodeSizes[GT_RET_EXPR] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_FIELD] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_CMPXCHG] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_QMARK] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_DYN_BLK] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_STORE_DYN_BLK] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_INTRINSIC] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_ALLOCOBJ] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_CALL] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_CAST] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_FTN_ADDR] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_BOX] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_INDEX] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_INDEX_ADDR] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_BOUNDS_CHECK] = TREE_NODE_SZ_SMALL; + 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; + GenTree::s_gtNodeSizes[GT_RET_EXPR] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_FIELD] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_CMPXCHG] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_QMARK] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_DYN_BLK] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_STORE_DYN_BLK] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_INTRINSIC] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_ALLOCOBJ] = TREE_NODE_SZ_LARGE; #if USE_HELPERS_FOR_INT_DIV - GenTree::s_gtNodeSizes[GT_DIV] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_UDIV] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_MOD] = TREE_NODE_SZ_LARGE; - GenTree::s_gtNodeSizes[GT_UMOD] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_DIV] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_UDIV] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_MOD] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_UMOD] = TREE_NODE_SZ_LARGE; #endif #ifdef FEATURE_PUT_STRUCT_ARG_STK // TODO-Throughput: This should not need to be a large node. The object info should be // obtained from the child node. - GenTree::s_gtNodeSizes[GT_PUTARG_STK] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_PUTARG_STK] = TREE_NODE_SZ_LARGE; #if FEATURE_ARG_SPLIT - GenTree::s_gtNodeSizes[GT_PUTARG_SPLIT] = TREE_NODE_SZ_LARGE; + GenTree::s_gtNodeSizes[GT_PUTARG_SPLIT] = TREE_NODE_SZ_LARGE; #endif // FEATURE_ARG_SPLIT #endif // FEATURE_PUT_STRUCT_ARG_STK @@ -1483,13 +1476,7 @@ bool GenTree::Compare(GenTree* op1, GenTree* op2, bool swapOK) return false; } break; - case GT_ARR_BOUNDS_CHECK: -#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_BOUNDS_CHECK: if (op1->AsBoundsChk()->gtThrowKind != op2->AsBoundsChk()->gtThrowKind) { return false; @@ -1930,13 +1917,7 @@ unsigned Compiler::gtHashValue(GenTree* tree) hash += static_cast(tree->AsAddrMode()->Offset() << 3) + tree->AsAddrMode()->gtScale; break; - case GT_ARR_BOUNDS_CHECK: -#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_BOUNDS_CHECK: hash = genTreeHashAdd(hash, tree->AsBoundsChk()->gtThrowKind); break; @@ -4060,13 +4041,7 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) } break; - case GT_ARR_BOUNDS_CHECK: -#ifdef FEATURE_SIMD - case GT_SIMD_CHK: -#endif -#ifdef FEATURE_HW_INTRINSICS - case GT_HW_INTRINSIC_CHK: -#endif + case GT_BOUNDS_CHECK: costEx = 4; // cmp reg,reg and jae throw (not taken) costSz = 7; // jump to cold section break; @@ -4331,7 +4306,7 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) // because of trickiness around ensuring the execution order does not change during rationalization. tryToSwap = false; } - else if (GenTree::OperIsBoundsCheck(oper)) + else if (oper == GT_BOUNDS_CHECK) { // Bounds check nodes used to not be binary, thus GTF_REVERSE_OPS was // not enabled for them. This condition preserves that behavior. @@ -5404,17 +5379,11 @@ bool GenTree::OperMayThrow(Compiler* comp) return false; } - case GT_ARR_BOUNDS_CHECK: + case GT_BOUNDS_CHECK: case GT_ARR_INDEX: case GT_ARR_OFFSET: case GT_LCLHEAP: case GT_CKFINITE: -#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; @@ -7501,16 +7470,10 @@ GenTree* Compiler::gtCloneExpr( #endif break; - case GT_ARR_BOUNDS_CHECK: -#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(), tree->AsBoundsChk()->GetIndex(), - tree->AsBoundsChk()->GetArrayLength(), tree->AsBoundsChk()->gtThrowKind); + case GT_BOUNDS_CHECK: + copy = new (this, GT_BOUNDS_CHECK) + GenTreeBoundsChk(tree->AsBoundsChk()->GetIndex(), tree->AsBoundsChk()->GetArrayLength(), + tree->AsBoundsChk()->gtThrowKind); copy->AsBoundsChk()->gtIndRngFailBB = tree->AsBoundsChk()->gtIndRngFailBB; break; @@ -9096,7 +9059,7 @@ void Compiler::gtDispNodeName(GenTree* tree) } bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), "%d)", lea->Offset()); } - else if (tree->gtOper == GT_ARR_BOUNDS_CHECK) + else if (tree->gtOper == GT_BOUNDS_CHECK) { switch (tree->AsBoundsChk()->gtThrowKind) { @@ -13134,7 +13097,7 @@ GenTree* Compiler::gtFoldExprConst(GenTree* tree) // This condition exists to preserve previous behavior. // TODO-CQ: enable folding for bounds checks nodes. - if (tree->OperIsBoundsCheck()) + if (tree->OperIs(GT_BOUNDS_CHECK)) { return tree; } @@ -17355,7 +17318,7 @@ void GenTree::ParseArrayAddressWork(Compiler* comp, case GT_COMMA: // We don't care about exceptions for this purpose. - if ((AsOp()->gtOp1->OperGet() == GT_ARR_BOUNDS_CHECK) || AsOp()->gtOp1->IsNothingNode()) + if (AsOp()->gtOp1->OperIs(GT_BOUNDS_CHECK) || AsOp()->gtOp1->IsNothingNode()) { AsOp()->gtOp2->ParseArrayAddressWork(comp, inputMul, pArr, pInxVN, pOffset, pFldSeq); return; diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index 1cad150ac5e35c..cb6fa0c4064c7f 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -579,7 +579,7 @@ enum GenTreeFlags : unsigned int GTF_DIV_BY_CNS_OPT = 0x80000000, // GT_DIV -- Uses the division by constant optimization to compute this division - GTF_ARR_BOUND_INBND = 0x80000000, // GT_ARR_BOUNDS_CHECK -- have proved this check is always in-bounds + GTF_ARR_BOUND_INBND = 0x80000000, // GT_BOUNDS_CHECK -- have proved this check is always in-bounds GTF_ARRLEN_ARR_IDX = 0x80000000, // GT_ARR_LENGTH -- Length which feeds into an array index expression GTF_ARRLEN_NONFAULTING = 0x20000000, // GT_ARR_LENGTH -- An array length operation that cannot fault. Same as GT_IND_NONFAULTING. @@ -1685,32 +1685,6 @@ struct GenTree return (gtOper == GT_JTRUE) || (gtOper == GT_JCMP) || (gtOper == GT_JCC); } - static bool OperIsBoundsCheck(genTreeOps op) - { - if (op == GT_ARR_BOUNDS_CHECK) - { - return true; - } -#ifdef FEATURE_SIMD - if (op == GT_SIMD_CHK) - { - return true; - } -#endif // FEATURE_SIMD -#ifdef FEATURE_HW_INTRINSICS - if (op == GT_HW_INTRINSIC_CHK) - { - return true; - } -#endif // FEATURE_HW_INTRINSICS - return false; - } - - bool OperIsBoundsCheck() const - { - return OperIsBoundsCheck(OperGet()); - } - #ifdef DEBUG bool NullOp1Legal() const { @@ -5754,19 +5728,23 @@ struct GenTreeArrLen : public GenTreeUnOp }; // This takes: -// - a comparison value (generally an array length), +// - a length value // - an index value, and // - the label to jump to if the index is out of range. // - the "kind" of the throw block to branch to on failure // It generates no result. - +// struct GenTreeBoundsChk : public GenTreeOp { - BasicBlock* gtIndRngFailBB; // Basic block to jump to for array-index-out-of-range + BasicBlock* gtIndRngFailBB; // Basic block to jump to for index-out-of-range SpecialCodeKind gtThrowKind; // Kind of throw block to branch to on failure + bool gtIsArrayBoundsCheck; - GenTreeBoundsChk(genTreeOps oper, var_types type, GenTree* index, GenTree* arrLen, SpecialCodeKind kind) - : GenTreeOp(oper, type, index, arrLen), gtIndRngFailBB(nullptr), gtThrowKind(kind) + GenTreeBoundsChk(GenTree* index, GenTree* length, SpecialCodeKind kind, bool isArrayBoundsCheck = true) + : GenTreeOp(GT_BOUNDS_CHECK, TYP_VOID, index, length) + , gtIndRngFailBB(nullptr) + , gtThrowKind(kind) + , gtIsArrayBoundsCheck(isArrayBoundsCheck) { gtFlags |= GTF_EXCEPT; } @@ -5777,22 +5755,28 @@ struct GenTreeBoundsChk : public GenTreeOp #endif // If this check is against GT_ARR_LENGTH, returns array reference, else "NULL". - GenTree* GetArray() + GenTree* GetArray() const { return GetArrayLength()->OperIs(GT_ARR_LENGTH) ? GetArrayLength()->AsArrLen()->ArrRef() : nullptr; } // The index expression. - GenTree* GetIndex() + GenTree* GetIndex() const { return gtOp1; } - // An expression for the length of the array being indexed. - GenTree* GetArrayLength() + // An expression for the length. + GenTree* GetArrayLength() const { return gtOp2; } + + // Is this a check originating from an array/span/SIMD, as opposed to HWINTRINSIC? + bool IsArrayBoundsCheck() const + { + return gtIsArrayBoundsCheck; + } }; // GenTreeArrElem - bounds checked address (byref) of a general array element, diff --git a/src/coreclr/jit/gtlist.h b/src/coreclr/jit/gtlist.h index 6f6462d6743bd0..0fec37b70b2a7c 100644 --- a/src/coreclr/jit/gtlist.h +++ b/src/coreclr/jit/gtlist.h @@ -77,7 +77,7 @@ GTNODE(ADDR , GenTreeOp ,0,GTK_UNOP) // addre GTNODE(IND , GenTreeIndir ,0,GTK_UNOP) // load indirection GTNODE(STOREIND , GenTreeStoreInd ,0,(GTK_BINOP|GTK_NOVALUE)) // store indirection -GTNODE(ARR_BOUNDS_CHECK , GenTreeBoundsChk ,0,(GTK_BINOP|GTK_EXOP|GTK_NOVALUE))// array bounds check +GTNODE(BOUNDS_CHECK , GenTreeBoundsChk ,0,(GTK_BINOP|GTK_EXOP|GTK_NOVALUE)) // a bounds check - for arrays/spans/SIMDs/HWINTRINSICs GTNODE(OBJ , GenTreeObj ,0,(GTK_UNOP|GTK_EXOP)) // Object that MAY have gc pointers, and thus includes the relevant gc layout info. GTNODE(STORE_OBJ , GenTreeObj ,0,(GTK_BINOP|GTK_EXOP|GTK_NOVALUE)) // Object that MAY have gc pointers, and thus includes the relevant gc layout info. @@ -88,20 +88,7 @@ GTNODE(STORE_DYN_BLK , GenTreeDynBlk ,0,(GTK_SPECIAL|GTK_NOVALUE)) // Dy GTNODE(BOX , GenTreeBox ,0,(GTK_UNOP|GTK_EXOP|GTK_NOTLIR)) GTNODE(FIELD , GenTreeField ,0,(GTK_UNOP|GTK_EXOP)) // Member-field - -#ifdef FEATURE_SIMD -GTNODE(SIMD_CHK , GenTreeBoundsChk ,0,(GTK_BINOP|GTK_EXOP|GTK_NOVALUE))// Compare whether an index is less than the given SIMD vector length, and call CORINFO_HELP_RNGCHKFAIL if not. - // TODO-CQ: In future may want to add a field that specifies different exceptions but we'll - // need VM assistance for that. - // TODO-CQ: It would actually be very nice to make this an unconditional throw, and expose the control flow that - // does the compare, so that it can be more easily optimized. But that involves generating qmarks at import time... -#endif // FEATURE_SIMD - -#ifdef FEATURE_HW_INTRINSICS -GTNODE(HW_INTRINSIC_CHK , GenTreeBoundsChk ,0,(GTK_BINOP|GTK_EXOP|GTK_NOVALUE))// Compare whether an imm8 argument is in the valid range, and throw ArgumentOutOfRangeException if not. -#endif - -GTNODE(ALLOCOBJ , GenTreeAllocObj ,0,(GTK_UNOP|GTK_EXOP)) // object allocator +GTNODE(ALLOCOBJ , GenTreeAllocObj ,0,(GTK_UNOP|GTK_EXOP)) // object allocator GTNODE(INIT_VAL , GenTreeOp ,0,GTK_UNOP) // Initialization value for an initBlk diff --git a/src/coreclr/jit/gtstructs.h b/src/coreclr/jit/gtstructs.h index 70a7901b7aca2a..591753837fe892 100644 --- a/src/coreclr/jit/gtstructs.h +++ b/src/coreclr/jit/gtstructs.h @@ -74,17 +74,13 @@ GTSTRUCT_1(Intrinsic , GT_INTRINSIC) GTSTRUCT_1(Index , GT_INDEX) GTSTRUCT_1(IndexAddr , GT_INDEX_ADDR) #if defined(FEATURE_HW_INTRINSICS) && defined(FEATURE_SIMD) -GTSTRUCT_3(BoundsChk , GT_ARR_BOUNDS_CHECK, GT_SIMD_CHK, GT_HW_INTRINSIC_CHK) GTSTRUCT_N(MultiOp , GT_SIMD, GT_HWINTRINSIC) #elif defined(FEATURE_SIMD) -GTSTRUCT_2(BoundsChk , GT_ARR_BOUNDS_CHECK, GT_SIMD_CHK) GTSTRUCT_N(MultiOp , GT_SIMD) #elif defined(FEATURE_HW_INTRINSICS) -GTSTRUCT_2(BoundsChk , GT_ARR_BOUNDS_CHECK, GT_HW_INTRINSIC_CHK) GTSTRUCT_N(MultiOp , GT_HWINTRINSIC) -#else // !FEATURE_SIMD && !FEATURE_HW_INTRINSICS -GTSTRUCT_1(BoundsChk , GT_ARR_BOUNDS_CHECK) -#endif // !FEATURE_SIMD && !FEATURE_HW_INTRINSICS +#endif +GTSTRUCT_1(BoundsChk , GT_BOUNDS_CHECK) GTSTRUCT_1(ArrLen , GT_ARR_LENGTH) GTSTRUCT_1(ArrElem , GT_ARR_ELEM) GTSTRUCT_1(ArrOffs , GT_ARR_OFFSET) diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index f4ce9bd171ee1b..0e33683cf15dfc 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -462,7 +462,7 @@ GenTree* Compiler::getArgForHWIntrinsic(var_types argType, } //------------------------------------------------------------------------ -// addRangeCheckIfNeeded: add a GT_HW_INTRINSIC_CHK node for non-full-range imm-intrinsic +// addRangeCheckIfNeeded: add a GT_BOUNDS_CHECK node for non-full-range imm-intrinsic // // Arguments: // intrinsic -- intrinsic ID @@ -472,7 +472,7 @@ GenTree* Compiler::getArgForHWIntrinsic(var_types argType, // immUpperBound -- upper incl. bound for a value of the immediate operand (for a non-full-range imm-intrinsic) // // Return Value: -// add a GT_HW_INTRINSIC_CHK node for non-full-range imm-intrinsic, which would throw ArgumentOutOfRangeException +// add a GT_BOUNDS_CHECK node for non-full-range imm-intrinsic, which would throw ArgumentOutOfRangeException // when the imm-argument is not in the valid range // GenTree* Compiler::addRangeCheckIfNeeded( @@ -501,7 +501,7 @@ GenTree* Compiler::addRangeCheckIfNeeded( } //------------------------------------------------------------------------ -// addRangeCheckForHWIntrinsic: add a GT_HW_INTRINSIC_CHK node for an intrinsic +// addRangeCheckForHWIntrinsic: add a GT_BOUNDS_CHECK node for an intrinsic // // Arguments: // immOp -- the immediate operand of the intrinsic @@ -509,7 +509,7 @@ GenTree* Compiler::addRangeCheckIfNeeded( // immUpperBound -- upper incl. bound for a value of the immediate operand (for a non-full-range imm-intrinsic) // // Return Value: -// add a GT_HW_INTRINSIC_CHK node for non-full-range imm-intrinsic, which would throw ArgumentOutOfRangeException +// add a GT_BOUNDS_CHECK node for non-full-range imm-intrinsic, which would throw ArgumentOutOfRangeException // when the imm-argument is not in the valid range // GenTree* Compiler::addRangeCheckForHWIntrinsic(GenTree* immOp, int immLowerBound, int immUpperBound) @@ -539,8 +539,8 @@ GenTree* Compiler::addRangeCheckForHWIntrinsic(GenTree* immOp, int immLowerBound immOpDup = gtNewOperNode(GT_SUB, TYP_INT, immOpDup, gtNewIconNode(immLowerBound, TYP_INT)); } - GenTreeBoundsChk* hwIntrinsicChk = new (this, GT_HW_INTRINSIC_CHK) - GenTreeBoundsChk(GT_HW_INTRINSIC_CHK, TYP_VOID, immOpDup, adjustedUpperBoundNode, SCK_ARG_RNG_EXCPN); + GenTreeBoundsChk* hwIntrinsicChk = new (this, GT_BOUNDS_CHECK) + GenTreeBoundsChk(immOpDup, adjustedUpperBoundNode, SCK_ARG_RNG_EXCPN, /* isArrayBoundsCheck */ false); return gtNewOperNode(GT_COMMA, immOp->TypeGet(), hwIntrinsicChk, immOp); } diff --git a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp index 2bbe2835816fcf..cd9e0f8f8fc3d5 100644 --- a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp @@ -1047,7 +1047,7 @@ void CodeGen::genHWIntrinsic_R_R_R_RM( // Note: // This function can be used for all imm-intrinsics (whether full-range or not), // The compiler front-end (i.e. importer) is responsible to insert a range-check IR -// (GT_HW_INTRINSIC_CHK) for imm8 argument, so this function does not need to do range-check. +// (GT_BOUNDS_CHECK) for imm8 argument, so this function does not need to do range-check. // template void CodeGen::genHWIntrinsicJumpTableFallback(NamedIntrinsic intrinsic, diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index dc4f56eb4b469f..c390b1d8924168 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -4145,8 +4145,8 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, CORINFO_FIELD_HANDLE lengthHnd = info.compCompHnd->getFieldInClass(clsHnd, 1); const unsigned lengthOffset = info.compCompHnd->getFieldOffset(lengthHnd); GenTree* length = gtNewFieldRef(TYP_INT, lengthHnd, ptrToSpan, lengthOffset); - GenTree* boundsCheck = new (this, GT_ARR_BOUNDS_CHECK) - GenTreeBoundsChk(GT_ARR_BOUNDS_CHECK, TYP_VOID, index, length, SCK_RNGCHK_FAIL); + GenTree* boundsCheck = + new (this, GT_BOUNDS_CHECK) GenTreeBoundsChk(index, length, SCK_RNGCHK_FAIL); // Element access index = indexClone; diff --git a/src/coreclr/jit/liveness.cpp b/src/coreclr/jit/liveness.cpp index a0134f214f0f35..4f8d9334249cf0 100644 --- a/src/coreclr/jit/liveness.cpp +++ b/src/coreclr/jit/liveness.cpp @@ -2042,16 +2042,10 @@ void Compiler::fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALAR case GT_MEMORYBARRIER: case GT_JMP: case GT_STOREIND: - case GT_ARR_BOUNDS_CHECK: + case GT_BOUNDS_CHECK: case GT_STORE_OBJ: case GT_STORE_BLK: case GT_STORE_DYN_BLK: -#if defined(FEATURE_SIMD) - case GT_SIMD_CHK: -#endif // FEATURE_SIMD -#ifdef FEATURE_HW_INTRINSICS - case GT_HW_INTRINSIC_CHK: -#endif // FEATURE_HW_INTRINSICS case GT_JCMP: case GT_CMP: case GT_JCC: diff --git a/src/coreclr/jit/loopcloning.cpp b/src/coreclr/jit/loopcloning.cpp index 09f42b6e6f6659..71765d52edea9b 100644 --- a/src/coreclr/jit/loopcloning.cpp +++ b/src/coreclr/jit/loopcloning.cpp @@ -1447,7 +1447,7 @@ void Compiler::optPerformStaticOptimizations(unsigned loopNum, LoopCloneContext* } #endif // DEBUG - if (bndsChkNode->gtGetOp1()->OperIsBoundsCheck()) + if (bndsChkNode->gtGetOp1()->OperIs(GT_BOUNDS_CHECK)) { // This COMMA node will only represent a bounds check if we've haven't already removed this // bounds check in some other nesting cloned loop. For example, consider: @@ -2175,7 +2175,7 @@ bool Compiler::optIsStackLocalInvariant(unsigned loopNum, unsigned lclNum) // Example tree to pattern match: // // * COMMA int -// +--* ARR_BOUNDS_CHECK_Rng void +// +--* BOUNDS_CHECK_Rng void // | +--* LCL_VAR int V02 loc1 // | \--* ARR_LENGTH int // | \--* LCL_VAR ref V00 arg0 @@ -2192,7 +2192,7 @@ bool Compiler::optIsStackLocalInvariant(unsigned loopNum, unsigned lclNum) // Note that byte arrays don't require the LSH to scale the index, so look like this: // // * COMMA ubyte -// +--* ARR_BOUNDS_CHECK_Rng void +// +--* BOUNDS_CHECK_Rng void // | +--* LCL_VAR int V03 loc2 // | \--* ARR_LENGTH int // | \--* LCL_VAR ref V00 arg0 @@ -2217,7 +2217,7 @@ bool Compiler::optExtractArrIndex(GenTree* tree, ArrIndex* result, unsigned lhsN return false; } GenTree* before = tree->gtGetOp1(); - if (before->gtOper != GT_ARR_BOUNDS_CHECK) + if (!before->OperIs(GT_BOUNDS_CHECK) || !before->AsBoundsChk()->IsArrayBoundsCheck()) { return false; } diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 2467a00accdaa7..ae5a41c52e6827 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -198,13 +198,7 @@ GenTree* Lowering::LowerNode(GenTree* node) break; #if defined(TARGET_XARCH) || defined(TARGET_ARM64) - case GT_ARR_BOUNDS_CHECK: -#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_BOUNDS_CHECK: ContainCheckBoundsChk(node->AsBoundsChk()); break; #endif // TARGET_XARCH diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 279a20e7a36213..ae02e5e3a9928b 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -104,13 +104,7 @@ bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode) const case GT_LE: case GT_GE: case GT_GT: - case GT_ARR_BOUNDS_CHECK: -#ifdef FEATURE_SIMD - case GT_SIMD_CHK: -#endif -#ifdef FEATURE_HW_INTRINSICS - case GT_HW_INTRINSIC_CHK: -#endif + case GT_BOUNDS_CHECK: return emitter::emitIns_valid_imm_for_cmp(immVal, size); case GT_AND: case GT_OR: @@ -1722,7 +1716,7 @@ void Lowering::ContainCheckCompare(GenTreeOp* cmp) // void Lowering::ContainCheckBoundsChk(GenTreeBoundsChk* node) { - assert(node->OperIsBoundsCheck()); + assert(node->OperIs(GT_BOUNDS_CHECK)); if (!CheckImmedAndMakeContained(node, node->GetIndex())) { CheckImmedAndMakeContained(node, node->GetArrayLength()); diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index 548a6033d872ba..8f10a5c6460a23 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -5030,7 +5030,7 @@ void Lowering::ContainCheckBinary(GenTreeOp* node) // void Lowering::ContainCheckBoundsChk(GenTreeBoundsChk* node) { - assert(node->OperIsBoundsCheck()); + assert(node->OperIs(GT_BOUNDS_CHECK)); GenTree* other; if (CheckImmedAndMakeContained(node, node->GetIndex())) { diff --git a/src/coreclr/jit/lsraarm.cpp b/src/coreclr/jit/lsraarm.cpp index fb5ad16006dad7..9050f1f5ac7d2d 100644 --- a/src/coreclr/jit/lsraarm.cpp +++ b/src/coreclr/jit/lsraarm.cpp @@ -509,18 +509,13 @@ int LinearScan::BuildNode(GenTree* tree) } break; - case GT_ARR_BOUNDS_CHECK: -#ifdef FEATURE_SIMD - case GT_SIMD_CHK: -#endif // FEATURE_SIMD - { + case GT_BOUNDS_CHECK: // Consumes arrLen & index - has no result srcCount = 2; assert(dstCount == 0); BuildUse(tree->AsBoundsChk()->GetIndex()); BuildUse(tree->AsBoundsChk()->GetArrayLength()); - } - break; + break; case GT_ARR_ELEM: // These must have been lowered to GT_ARR_INDEX diff --git a/src/coreclr/jit/lsraarm64.cpp b/src/coreclr/jit/lsraarm64.cpp index 1b201603f95a1b..0f4ad4cdb04dd3 100644 --- a/src/coreclr/jit/lsraarm64.cpp +++ b/src/coreclr/jit/lsraarm64.cpp @@ -614,13 +614,7 @@ int LinearScan::BuildNode(GenTree* tree) } break; - case GT_ARR_BOUNDS_CHECK: -#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_BOUNDS_CHECK: { GenTreeBoundsChk* node = tree->AsBoundsChk(); // Consumes arrLen & index - has no result diff --git a/src/coreclr/jit/lsraxarch.cpp b/src/coreclr/jit/lsraxarch.cpp index 4705ee6798595e..ea4c86639d5ec5 100644 --- a/src/coreclr/jit/lsraxarch.cpp +++ b/src/coreclr/jit/lsraxarch.cpp @@ -524,14 +524,7 @@ int LinearScan::BuildNode(GenTree* tree) srcCount = BuildLclHeap(tree); break; - case GT_ARR_BOUNDS_CHECK: -#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_BOUNDS_CHECK: // Consumes arrLen & index - has no result assert(dstCount == 0); srcCount = BuildOperandUses(tree->AsBoundsChk()->GetIndex()); diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 288f7c16f4d9b6..d4982d211794a2 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -5103,7 +5103,7 @@ void Compiler::fgMoveOpsLeft(GenTree* tree) void Compiler::fgSetRngChkTarget(GenTree* tree, bool delay) { - if (tree->OperIsBoundsCheck()) + if (tree->OperIs(GT_BOUNDS_CHECK)) { GenTreeBoundsChk* const boundsChk = tree->AsBoundsChk(); BasicBlock* const failBlock = fgSetRngChkTargetInner(boundsChk->gtThrowKind, delay); @@ -5154,7 +5154,7 @@ BasicBlock* Compiler::fgSetRngChkTargetInner(SpecialCodeKind kind, bool delay) * The orginal GT_INDEX node is bashed into the GT_IND node that accesses * the array element. We expand the GT_INDEX node into a larger tree that * evaluates the array base and index. The simplest expansion is a GT_COMMA - * with a GT_ARR_BOUNDS_CHECK and a GT_IND with a GTF_INX_RNGCHK flag. + * with a GT_BOUNDS_CHECK and a GT_IND with a GTF_INX_RNGCHK flag. * For complex array or index expressions one or more GT_COMMA assignments * are inserted so that we only evaluate the array or index expressions once. * @@ -5244,7 +5244,7 @@ GenTree* Compiler::fgMorphArrayIndex(GenTree* tree) // side-effecting. // 2. Evaluate the array index expression and store the result in a temp if the expression is complex or // side-effecting. - // 3. Perform an explicit bounds check: GT_ARR_BOUNDS_CHECK(index, GT_ARR_LENGTH(array)) + // 3. Perform an explicit bounds check: GT_BOUNDS_CHECK(index, GT_ARR_LENGTH(array)) // 4. Compute the address of the element that will be accessed: // GT_ADD(GT_ADD(array, firstElementOffset), GT_MUL(index, elementSize)) // 5. Dereference the address with a GT_IND. @@ -5303,7 +5303,7 @@ GenTree* Compiler::fgMorphArrayIndex(GenTree* tree) GenTree* indexDefn = nullptr; // non-NULL if we need to allocate a temp for the index expression GenTree* bndsChk = nullptr; - // If we're doing range checking, introduce a GT_ARR_BOUNDS_CHECK node for the address. + // If we're doing range checking, introduce a GT_BOUNDS_CHECK node for the address. if (chkd) { GenTree* arrRef2 = nullptr; // The second copy will be used in array address expression @@ -5352,7 +5352,7 @@ GenTree* Compiler::fgMorphArrayIndex(GenTree* tree) noway_assert(index2 != nullptr); } - // Next introduce a GT_ARR_BOUNDS_CHECK node + // Next introduce a GT_BOUNDS_CHECK node var_types bndsChkType = TYP_INT; // By default, try to use 32-bit comparison for array bounds check. #ifdef TARGET_64BIT @@ -5372,8 +5372,7 @@ GenTree* Compiler::fgMorphArrayIndex(GenTree* tree) arrLen = gtNewCastNode(bndsChkType, arrLen, true, bndsChkType); } - GenTreeBoundsChk* arrBndsChk = new (this, GT_ARR_BOUNDS_CHECK) - GenTreeBoundsChk(GT_ARR_BOUNDS_CHECK, TYP_VOID, index, arrLen, SCK_RNGCHK_FAIL); + GenTreeBoundsChk* arrBndsChk = new (this, GT_BOUNDS_CHECK) GenTreeBoundsChk(index, arrLen, SCK_RNGCHK_FAIL); bndsChk = arrBndsChk; @@ -12638,13 +12637,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) fgAddCodeRef(compCurBB, bbThrowIndex(compCurBB), SCK_ARITH_EXCPN); break; - case GT_ARR_BOUNDS_CHECK: -#ifdef FEATURE_SIMD - case GT_SIMD_CHK: -#endif -#ifdef FEATURE_HW_INTRINSICS - case GT_HW_INTRINSIC_CHK: -#endif + case GT_BOUNDS_CHECK: fgSetRngChkTarget(tree); break; diff --git a/src/coreclr/jit/optcse.cpp b/src/coreclr/jit/optcse.cpp index b6dadaac185771..b39b2bd1425c45 100644 --- a/src/coreclr/jit/optcse.cpp +++ b/src/coreclr/jit/optcse.cpp @@ -456,7 +456,7 @@ unsigned Compiler::optValnumCSE_Index(GenTree* tree, Statement* stmt) // If the value number for op2 and tree are different, then some new // exceptions were produced by op1. For that case we will NOT use the // normal value. This allows us to CSE commas with an op1 that is - // an ARR_BOUNDS_CHECK. + // an BOUNDS_CHECK. // if (vnOp2Lib != vnLib) { diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index 43e9616b2192fc..0141645c5cbb56 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -7846,8 +7846,8 @@ GenTree* Compiler::optRemoveRangeCheck(GenTreeBoundsChk* check, GenTree* comma, noway_assert(stmt != nullptr); noway_assert((comma != nullptr && comma->OperIs(GT_COMMA) && comma->gtGetOp1() == check) || - (check != nullptr && check->OperIsBoundsCheck() && comma == nullptr)); - noway_assert(check->OperIsBoundsCheck()); + (check != nullptr && check->OperIs(GT_BOUNDS_CHECK) && comma == nullptr)); + noway_assert(check->OperIs(GT_BOUNDS_CHECK)); GenTree* tree = comma != nullptr ? comma : check; @@ -7944,7 +7944,7 @@ void Compiler::optRemoveCommaBasedRangeCheck(GenTree* comma, Statement* stmt) { assert(comma != nullptr && comma->OperIs(GT_COMMA)); assert(stmt != nullptr); - assert(comma->gtGetOp1()->OperIsBoundsCheck()); + assert(comma->gtGetOp1()->OperIs(GT_BOUNDS_CHECK)); optRemoveRangeCheck(comma->gtGetOp1()->AsBoundsChk(), comma, stmt); } diff --git a/src/coreclr/jit/rangecheck.cpp b/src/coreclr/jit/rangecheck.cpp index 8590ecdd81c9f1..3ec04fc2decc2a 100644 --- a/src/coreclr/jit/rangecheck.cpp +++ b/src/coreclr/jit/rangecheck.cpp @@ -196,7 +196,7 @@ void RangeCheck::OptimizeRangeCheck(BasicBlock* block, Statement* stmt, GenTree* // If we are not looking at array bounds check, bail. GenTree* tree = isComma ? treeParent->AsOp()->gtOp1 : treeParent; - if (!tree->OperIsBoundsCheck()) + if (!tree->OperIs(GT_BOUNDS_CHECK)) { return; } @@ -221,14 +221,7 @@ void RangeCheck::OptimizeRangeCheck(BasicBlock* block, Statement* stmt, GenTree* arrSize = (int)constVal; } } - else -#ifdef FEATURE_SIMD - if (tree->gtOper != GT_SIMD_CHK -#ifdef FEATURE_HW_INTRINSICS - && tree->gtOper != GT_HW_INTRINSIC_CHK -#endif // FEATURE_HW_INTRINSICS - ) -#endif // FEATURE_SIMD + else if (bndsChk->IsArrayBoundsCheck()) { arrSize = GetArrLength(arrLenVn); diff --git a/src/coreclr/jit/simd.cpp b/src/coreclr/jit/simd.cpp index cfcc8f0285624b..6ca931c13fdf83 100644 --- a/src/coreclr/jit/simd.cpp +++ b/src/coreclr/jit/simd.cpp @@ -1777,8 +1777,8 @@ GenTree* Compiler::createAddressNodeForSIMDInit(GenTree* tree, unsigned simdSize unsigned arrayElementsCount = simdSize / genTypeSize(baseType); checkIndexExpr = new (this, GT_CNS_INT) GenTreeIntCon(TYP_INT, indexVal + arrayElementsCount - 1); GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, arrayRef, (int)OFFSETOF__CORINFO_Array__length, compCurBB); - GenTreeBoundsChk* arrBndsChk = new (this, GT_ARR_BOUNDS_CHECK) - GenTreeBoundsChk(GT_ARR_BOUNDS_CHECK, TYP_VOID, checkIndexExpr, arrLen, SCK_ARG_RNG_EXCPN); + GenTreeBoundsChk* arrBndsChk = new (this, GT_BOUNDS_CHECK) + GenTreeBoundsChk(checkIndexExpr, arrLen, SCK_ARG_RNG_EXCPN); offset += OFFSETOF__CORINFO_Array__data; byrefNode = gtNewOperNode(GT_COMMA, arrayRef->TypeGet(), arrBndsChk, gtCloneExpr(arrayRef)); @@ -2189,8 +2189,7 @@ GenTree* Compiler::impSIMDIntrinsic(OPCODE opcode, GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, arrayRefForArgRngChk, (int)OFFSETOF__CORINFO_Array__length, compCurBB); - argRngChk = new (this, GT_ARR_BOUNDS_CHECK) - GenTreeBoundsChk(GT_ARR_BOUNDS_CHECK, TYP_VOID, index, arrLen, SCK_ARG_RNG_EXCPN); + argRngChk = new (this, GT_BOUNDS_CHECK) GenTreeBoundsChk(index, arrLen, SCK_ARG_RNG_EXCPN); // Now, clone op3 to create another node for the argChk GenTree* index2 = gtCloneExpr(op3); assert(index != nullptr); @@ -2210,8 +2209,8 @@ GenTree* Compiler::impSIMDIntrinsic(OPCODE opcode, } GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, arrayRefForArgChk, (int)OFFSETOF__CORINFO_Array__length, compCurBB); - GenTreeBoundsChk* argChk = new (this, GT_ARR_BOUNDS_CHECK) - GenTreeBoundsChk(GT_ARR_BOUNDS_CHECK, TYP_VOID, checkIndexExpr, arrLen, op2CheckKind); + GenTreeBoundsChk* argChk = new (this, GT_BOUNDS_CHECK) + GenTreeBoundsChk(checkIndexExpr, arrLen, op2CheckKind); // Create a GT_COMMA tree for the bounds check(s). op2 = gtNewOperNode(GT_COMMA, op2->TypeGet(), argChk, op2); diff --git a/src/coreclr/jit/stacklevelsetter.cpp b/src/coreclr/jit/stacklevelsetter.cpp index da20ff6fe22574..54d5d48d4cf2ca 100644 --- a/src/coreclr/jit/stacklevelsetter.cpp +++ b/src/coreclr/jit/stacklevelsetter.cpp @@ -131,13 +131,7 @@ void StackLevelSetter::SetThrowHelperBlocks(GenTree* node, BasicBlock* block) // Check that it uses throw block, find its kind, find the block, set level. switch (node->OperGet()) { - case GT_ARR_BOUNDS_CHECK: -#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_BOUNDS_CHECK: { GenTreeBoundsChk* bndsChk = node->AsBoundsChk(); SetThrowHelperBlock(bndsChk->gtThrowKind, block); diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index af8d3752199176..95817ebb84ad25 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -6159,13 +6159,7 @@ static genTreeOps genTreeOpsIllegalAsVNFunc[] = {GT_IND, // When we do heap memo // These need special semantics: GT_COMMA, // == second argument (but with exception(s) from first). - GT_ADDR, GT_ARR_BOUNDS_CHECK, -#ifdef FEATURE_SIMD - GT_SIMD_CHK, -#endif -#ifdef FEATURE_HW_INTRINSICS - GT_HW_INTRINSIC_CHK, -#endif + GT_ADDR, GT_BOUNDS_CHECK, GT_OBJ, // May reference heap memory. GT_BLK, // May reference heap memory. GT_INIT_VAL, // Not strictly a pass-through. @@ -9224,13 +9218,7 @@ void Compiler::fgValueNumberTree(GenTree* tree) } break; - case GT_ARR_BOUNDS_CHECK: -#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_BOUNDS_CHECK: { ValueNumPair vnpIndex = tree->AsBoundsChk()->GetIndex()->gtVNPair; ValueNumPair vnpArrLen = tree->AsBoundsChk()->GetArrayLength()->gtVNPair; @@ -10974,13 +10962,7 @@ void Compiler::fgValueNumberAddExceptionSet(GenTree* tree) fgValueNumberAddExceptionSetForDivision(tree); break; -#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_ARR_BOUNDS_CHECK: + case GT_BOUNDS_CHECK: fgValueNumberAddExceptionSetForBoundsCheck(tree); break; diff --git a/src/coreclr/jit/valuenum.h b/src/coreclr/jit/valuenum.h index a45044b6620357..289e09fb688b13 100644 --- a/src/coreclr/jit/valuenum.h +++ b/src/coreclr/jit/valuenum.h @@ -712,11 +712,11 @@ class ValueNumStore typedef SmallHashTable CheckedBoundVNSet; // Returns true if the VN is known or likely to appear as the conservative value number - // of the length argument to a GT_ARR_BOUNDS_CHECK node. + // of the length argument to a GT_BOUNDS_CHECK node. bool IsVNCheckedBound(ValueNum vn); // Record that a VN is known to appear as the conservative value number of the length - // argument to a GT_ARR_BOUNDS_CHECK node. + // argument to a GT_BOUNDS_CHECK node. void SetVNIsCheckedBound(ValueNum vn); // Information about the individual components of a value number representing an unsigned From 86d41612f950c85e86ef78a81d0bde7c765832c3 Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Fri, 26 Nov 2021 18:03:41 +0300 Subject: [PATCH 2/4] Remove IsArrayBoundsCheck In loop cloning: redundant with the check for constant lengths below. In assertion propagation: needless pessimization. In range check: not needed. While it is not useful to search for the array lengths from "new int[] { ... }" expressions, it is still useful to look for assertions related to them. --- src/coreclr/jit/assertionprop.cpp | 12 +++--------- src/coreclr/jit/gentree.h | 10 +--------- src/coreclr/jit/hwintrinsic.cpp | 2 +- src/coreclr/jit/loopcloning.cpp | 2 +- src/coreclr/jit/rangecheck.cpp | 2 +- 5 files changed, 7 insertions(+), 21 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 12634c97814c26..e9cb9dd2067ca3 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -1261,7 +1261,7 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, AssertionDsc assertion = {OAK_INVALID}; assert(assertion.assertionKind == OAK_INVALID); - if (op1->OperIs(GT_BOUNDS_CHECK) && op1->AsBoundsChk()->IsArrayBoundsCheck()) + if (op1->OperIs(GT_BOUNDS_CHECK)) { if (assertionKind == OAK_NO_THROW) { @@ -2584,7 +2584,7 @@ void Compiler::optAssertionGen(GenTree* tree) break; case GT_BOUNDS_CHECK: - if (!optLocalAssertionProp && tree->AsBoundsChk()->IsArrayBoundsCheck()) + if (!optLocalAssertionProp) { assertionInfo = optCreateAssertion(tree, nullptr, OAK_NO_THROW); } @@ -4053,8 +4053,7 @@ GenTree* Compiler::optAssertionProp_Comma(ASSERT_VALARG_TP assertions, GenTree* { // Remove the bounds check as part of the GT_COMMA node since we need parent pointer to remove nodes. // When processing visits the bounds check, it sets the throw kind to None if the check is redundant. - if (tree->gtGetOp1()->OperIs(GT_BOUNDS_CHECK) && tree->gtGetOp1()->AsBoundsChk()->IsArrayBoundsCheck() && - ((tree->gtGetOp1()->gtFlags & GTF_ARR_BOUND_INBND) != 0)) + if (tree->gtGetOp1()->OperIs(GT_BOUNDS_CHECK) && ((tree->gtGetOp1()->gtFlags & GTF_ARR_BOUND_INBND) != 0)) { optRemoveCommaBasedRangeCheck(tree, stmt); return optAssertionProp_Update(tree, tree, stmt); @@ -4393,11 +4392,6 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree assert(tree->OperIs(GT_BOUNDS_CHECK)); - if (!tree->AsBoundsChk()->IsArrayBoundsCheck()) - { - return nullptr; - } - #ifdef FEATURE_ENABLE_NO_RANGE_CHECKS if (JitConfig.JitNoRangeChks()) { diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index cb6fa0c4064c7f..a48eaffca1d1b1 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -5738,13 +5738,11 @@ struct GenTreeBoundsChk : public GenTreeOp { BasicBlock* gtIndRngFailBB; // Basic block to jump to for index-out-of-range SpecialCodeKind gtThrowKind; // Kind of throw block to branch to on failure - bool gtIsArrayBoundsCheck; - GenTreeBoundsChk(GenTree* index, GenTree* length, SpecialCodeKind kind, bool isArrayBoundsCheck = true) + GenTreeBoundsChk(GenTree* index, GenTree* length, SpecialCodeKind kind) : GenTreeOp(GT_BOUNDS_CHECK, TYP_VOID, index, length) , gtIndRngFailBB(nullptr) , gtThrowKind(kind) - , gtIsArrayBoundsCheck(isArrayBoundsCheck) { gtFlags |= GTF_EXCEPT; } @@ -5771,12 +5769,6 @@ struct GenTreeBoundsChk : public GenTreeOp { return gtOp2; } - - // Is this a check originating from an array/span/SIMD, as opposed to HWINTRINSIC? - bool IsArrayBoundsCheck() const - { - return gtIsArrayBoundsCheck; - } }; // GenTreeArrElem - bounds checked address (byref) of a general array element, diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index 0e33683cf15dfc..7f32756b83d13a 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -540,7 +540,7 @@ GenTree* Compiler::addRangeCheckForHWIntrinsic(GenTree* immOp, int immLowerBound } GenTreeBoundsChk* hwIntrinsicChk = new (this, GT_BOUNDS_CHECK) - GenTreeBoundsChk(immOpDup, adjustedUpperBoundNode, SCK_ARG_RNG_EXCPN, /* isArrayBoundsCheck */ false); + GenTreeBoundsChk(immOpDup, adjustedUpperBoundNode, SCK_ARG_RNG_EXCPN); return gtNewOperNode(GT_COMMA, immOp->TypeGet(), hwIntrinsicChk, immOp); } diff --git a/src/coreclr/jit/loopcloning.cpp b/src/coreclr/jit/loopcloning.cpp index 71765d52edea9b..888bc934981fb3 100644 --- a/src/coreclr/jit/loopcloning.cpp +++ b/src/coreclr/jit/loopcloning.cpp @@ -2217,7 +2217,7 @@ bool Compiler::optExtractArrIndex(GenTree* tree, ArrIndex* result, unsigned lhsN return false; } GenTree* before = tree->gtGetOp1(); - if (!before->OperIs(GT_BOUNDS_CHECK) || !before->AsBoundsChk()->IsArrayBoundsCheck()) + if (!before->OperIs(GT_BOUNDS_CHECK)) { return false; } diff --git a/src/coreclr/jit/rangecheck.cpp b/src/coreclr/jit/rangecheck.cpp index 3ec04fc2decc2a..a0a76a6c4cd924 100644 --- a/src/coreclr/jit/rangecheck.cpp +++ b/src/coreclr/jit/rangecheck.cpp @@ -221,7 +221,7 @@ void RangeCheck::OptimizeRangeCheck(BasicBlock* block, Statement* stmt, GenTree* arrSize = (int)constVal; } } - else if (bndsChk->IsArrayBoundsCheck()) + else { arrSize = GetArrLength(arrLenVn); From 30540b9b01bec0291627050f5b947f2ba021267e Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Fri, 26 Nov 2021 23:39:17 +0300 Subject: [PATCH 3/4] GTF_ARR_BOUND_INBND -> GTF_CHK_INDEX_INBND --- src/coreclr/jit/assertionprop.cpp | 6 +++--- src/coreclr/jit/gentree.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index e9cb9dd2067ca3..b842e1363fed62 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -4053,7 +4053,7 @@ GenTree* Compiler::optAssertionProp_Comma(ASSERT_VALARG_TP assertions, GenTree* { // Remove the bounds check as part of the GT_COMMA node since we need parent pointer to remove nodes. // When processing visits the bounds check, it sets the throw kind to None if the check is redundant. - if (tree->gtGetOp1()->OperIs(GT_BOUNDS_CHECK) && ((tree->gtGetOp1()->gtFlags & GTF_ARR_BOUND_INBND) != 0)) + if (tree->gtGetOp1()->OperIs(GT_BOUNDS_CHECK) && ((tree->gtGetOp1()->gtFlags & GTF_CHK_INDEX_INBND) != 0)) { optRemoveCommaBasedRangeCheck(tree, stmt); return optAssertionProp_Update(tree, tree, stmt); @@ -4402,7 +4402,7 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree gtDispTree(tree, nullptr, nullptr, true); } #endif // DEBUG - tree->gtFlags |= GTF_ARR_BOUND_INBND; + tree->gtFlags |= GTF_CHK_INDEX_INBND; return nullptr; } #endif // FEATURE_ENABLE_NO_RANGE_CHECKS @@ -4513,7 +4513,7 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree // Defer actually removing the tree until processing reaches its parent comma, since // optRemoveCommaBasedRangeCheck needs to rewrite the whole comma tree. - arrBndsChk->gtFlags |= GTF_ARR_BOUND_INBND; + arrBndsChk->gtFlags |= GTF_CHK_INDEX_INBND; return nullptr; } diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index a48eaffca1d1b1..f6b3ca6f7c1fbd 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -579,7 +579,7 @@ enum GenTreeFlags : unsigned int GTF_DIV_BY_CNS_OPT = 0x80000000, // GT_DIV -- Uses the division by constant optimization to compute this division - GTF_ARR_BOUND_INBND = 0x80000000, // GT_BOUNDS_CHECK -- have proved this check is always in-bounds + GTF_CHK_INDEX_INBND = 0x80000000, // GT_BOUNDS_CHECK -- have proved this check is always in-bounds GTF_ARRLEN_ARR_IDX = 0x80000000, // GT_ARR_LENGTH -- Length which feeds into an array index expression GTF_ARRLEN_NONFAULTING = 0x20000000, // GT_ARR_LENGTH -- An array length operation that cannot fault. Same as GT_IND_NONFAULTING. From 866b4878dfabd80993709eee2071b6362bdccdd6 Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Sat, 27 Nov 2021 20:37:22 +0300 Subject: [PATCH 4/4] Fix formating --- src/coreclr/jit/gentree.h | 4 +--- src/coreclr/jit/hwintrinsic.cpp | 4 ++-- src/coreclr/jit/importer.cpp | 3 +-- src/coreclr/jit/simd.cpp | 14 +++++++------- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index f6b3ca6f7c1fbd..a53d8452c5ad58 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -5740,9 +5740,7 @@ struct GenTreeBoundsChk : public GenTreeOp SpecialCodeKind gtThrowKind; // Kind of throw block to branch to on failure GenTreeBoundsChk(GenTree* index, GenTree* length, SpecialCodeKind kind) - : GenTreeOp(GT_BOUNDS_CHECK, TYP_VOID, index, length) - , gtIndRngFailBB(nullptr) - , gtThrowKind(kind) + : GenTreeOp(GT_BOUNDS_CHECK, TYP_VOID, index, length), gtIndRngFailBB(nullptr), gtThrowKind(kind) { gtFlags |= GTF_EXCEPT; } diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index 7f32756b83d13a..ad86d58613dcd3 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -539,8 +539,8 @@ GenTree* Compiler::addRangeCheckForHWIntrinsic(GenTree* immOp, int immLowerBound immOpDup = gtNewOperNode(GT_SUB, TYP_INT, immOpDup, gtNewIconNode(immLowerBound, TYP_INT)); } - GenTreeBoundsChk* hwIntrinsicChk = new (this, GT_BOUNDS_CHECK) - GenTreeBoundsChk(immOpDup, adjustedUpperBoundNode, SCK_ARG_RNG_EXCPN); + GenTreeBoundsChk* hwIntrinsicChk = + new (this, GT_BOUNDS_CHECK) GenTreeBoundsChk(immOpDup, adjustedUpperBoundNode, SCK_ARG_RNG_EXCPN); return gtNewOperNode(GT_COMMA, immOp->TypeGet(), hwIntrinsicChk, immOp); } diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index c390b1d8924168..0f21ff0ed2814a 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -4145,8 +4145,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, CORINFO_FIELD_HANDLE lengthHnd = info.compCompHnd->getFieldInClass(clsHnd, 1); const unsigned lengthOffset = info.compCompHnd->getFieldOffset(lengthHnd); GenTree* length = gtNewFieldRef(TYP_INT, lengthHnd, ptrToSpan, lengthOffset); - GenTree* boundsCheck = - new (this, GT_BOUNDS_CHECK) GenTreeBoundsChk(index, length, SCK_RNGCHK_FAIL); + GenTree* boundsCheck = new (this, GT_BOUNDS_CHECK) GenTreeBoundsChk(index, length, SCK_RNGCHK_FAIL); // Element access index = indexClone; diff --git a/src/coreclr/jit/simd.cpp b/src/coreclr/jit/simd.cpp index 6ca931c13fdf83..248fba2d320724 100644 --- a/src/coreclr/jit/simd.cpp +++ b/src/coreclr/jit/simd.cpp @@ -1774,11 +1774,11 @@ GenTree* Compiler::createAddressNodeForSIMDInit(GenTree* tree, unsigned simdSize // The length for boundary check should be the maximum index number which should be // (first argument's index number) + (how many array arguments we have) - 1 // = indexVal + arrayElementsCount - 1 - unsigned arrayElementsCount = simdSize / genTypeSize(baseType); - checkIndexExpr = new (this, GT_CNS_INT) GenTreeIntCon(TYP_INT, indexVal + arrayElementsCount - 1); - GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, arrayRef, (int)OFFSETOF__CORINFO_Array__length, compCurBB); - GenTreeBoundsChk* arrBndsChk = new (this, GT_BOUNDS_CHECK) - GenTreeBoundsChk(checkIndexExpr, arrLen, SCK_ARG_RNG_EXCPN); + unsigned arrayElementsCount = simdSize / genTypeSize(baseType); + checkIndexExpr = new (this, GT_CNS_INT) GenTreeIntCon(TYP_INT, indexVal + arrayElementsCount - 1); + GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, arrayRef, (int)OFFSETOF__CORINFO_Array__length, compCurBB); + GenTreeBoundsChk* arrBndsChk = + new (this, GT_BOUNDS_CHECK) GenTreeBoundsChk(checkIndexExpr, arrLen, SCK_ARG_RNG_EXCPN); offset += OFFSETOF__CORINFO_Array__data; byrefNode = gtNewOperNode(GT_COMMA, arrayRef->TypeGet(), arrBndsChk, gtCloneExpr(arrayRef)); @@ -2209,8 +2209,8 @@ GenTree* Compiler::impSIMDIntrinsic(OPCODE opcode, } GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, arrayRefForArgChk, (int)OFFSETOF__CORINFO_Array__length, compCurBB); - GenTreeBoundsChk* argChk = new (this, GT_BOUNDS_CHECK) - GenTreeBoundsChk(checkIndexExpr, arrLen, op2CheckKind); + GenTreeBoundsChk* argChk = + new (this, GT_BOUNDS_CHECK) GenTreeBoundsChk(checkIndexExpr, arrLen, op2CheckKind); // Create a GT_COMMA tree for the bounds check(s). op2 = gtNewOperNode(GT_COMMA, op2->TypeGet(), argChk, op2);