diff options
author | Jan Kotas <jkotas@microsoft.com> | 2017-08-30 06:35:44 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-08-30 06:35:44 -0700 |
commit | bec6ac10f3968a8f699aad6233657ac59df37a73 (patch) | |
tree | e15ceba1e2db154612457bee107dd85d627ad81a | |
parent | 4d9f5e3a0bc2b01c99337d68a8c90fc77b3182bd (diff) | |
download | coreclr-bec6ac10f3968a8f699aad6233657ac59df37a73.tar.gz coreclr-bec6ac10f3968a8f699aad6233657ac59df37a73.tar.bz2 coreclr-bec6ac10f3968a8f699aad6233657ac59df37a73.zip |
Revert "Merge pull request #13245 from pgavlin/NoExpandIndex" (#13682)
This reverts commit a7ffdeca6fed927dbd457293d97b07237db95e82, reversing
changes made to f5f622db2a00d7687f256c0d1cdda5e6f6da7ad4.
-rw-r--r-- | src/jit/codegenarmarch.cpp | 89 | ||||
-rw-r--r-- | src/jit/codegenlinear.h | 1 | ||||
-rw-r--r-- | src/jit/codegenxarch.cpp | 85 | ||||
-rw-r--r-- | src/jit/compiler.h | 22 | ||||
-rw-r--r-- | src/jit/flowgraph.cpp | 7 | ||||
-rw-r--r-- | src/jit/gentree.cpp | 54 | ||||
-rw-r--r-- | src/jit/gentree.h | 62 | ||||
-rw-r--r-- | src/jit/gtlist.h | 2 | ||||
-rw-r--r-- | src/jit/gtstructs.h | 1 | ||||
-rw-r--r-- | src/jit/lsraarm.cpp | 6 | ||||
-rw-r--r-- | src/jit/lsraarm64.cpp | 6 | ||||
-rw-r--r-- | src/jit/lsraxarch.cpp | 25 | ||||
-rw-r--r-- | src/jit/morph.cpp | 170 |
13 files changed, 53 insertions, 477 deletions
diff --git a/src/jit/codegenarmarch.cpp b/src/jit/codegenarmarch.cpp index bf83e13a6f..9bc422f305 100644 --- a/src/jit/codegenarmarch.cpp +++ b/src/jit/codegenarmarch.cpp @@ -185,10 +185,6 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) genLeaInstruction(treeNode->AsAddrMode()); break; - case GT_INDEX_ADDR: - genCodeForIndexAddr(treeNode->AsIndexAddr()); - break; - case GT_IND: genCodeForIndir(treeNode->AsIndir()); break; @@ -1544,91 +1540,6 @@ void CodeGen::genCodeForLclFld(GenTreeLclFld* tree) } //------------------------------------------------------------------------ -// genCodeForIndexAddr: Produce code for a GT_INDEX_ADDR node. -// -// Arguments: -// tree - the GT_INDEX_ADDR node -// -void CodeGen::genCodeForIndexAddr(GenTreeIndexAddr* node) -{ - GenTree* const base = node->Arr(); - GenTree* const index = node->Index(); - - genConsumeReg(base); - genConsumeReg(index); - - const regNumber tmpReg = node->GetSingleTempReg(); - - // Generate the bounds check if necessary. - if ((node->gtFlags & GTF_INX_RNGCHK) != 0) - { - // Create a GT_IND(GT_LEA)) tree for the array length access and load the length into a register. - GenTreeAddrMode arrLenAddr(base->TypeGet(), base, nullptr, 0, static_cast<unsigned>(node->gtLenOffset)); - arrLenAddr.gtRegNum = REG_NA; - arrLenAddr.SetContained(); - arrLenAddr.gtNext = (GenTree*)(-1); - - GenTreeIndir arrLen = indirForm(TYP_INT, &arrLenAddr); - arrLen.gtRegNum = tmpReg; - arrLen.ClearContained(); - - getEmitter()->emitInsLoadStoreOp(ins_Load(TYP_INT), emitTypeSize(TYP_INT), arrLen.gtRegNum, &arrLen); - -#ifdef _TARGET_64BIT_ - // The CLI Spec allows an array to be indexed by either an int32 or a native int. In the case that the index - // is a native int on a 64-bit platform, we will need to widen the array length and the compare. - if (index->TypeGet() == TYP_I_IMPL) - { - // Extend the array length as needed. - getEmitter()->emitIns_R_R(ins_Move_Extend(TYP_INT, true), EA_8BYTE, arrLen.gtRegNum, arrLen.gtRegNum); - } -#endif - - // Generate the range check. - getEmitter()->emitInsBinary(INS_cmp, emitTypeSize(TYP_I_IMPL), index, &arrLen); - genJumpToThrowHlpBlk(genJumpKindForOper(GT_GE, CK_UNSIGNED), SCK_RNGCHK_FAIL, node->gtIndRngFailBB); - } - - // Compute the address of the array element. - switch (node->gtElemSize) - { - case 1: - // dest = base + index - getEmitter()->emitIns_R_R_R(INS_add, emitTypeSize(node), node->gtRegNum, base->gtRegNum, index->gtRegNum); - break; - - case 2: - case 4: - case 8: - case 16: - { - DWORD lsl; - BitScanForward(&lsl, node->gtElemSize); - - // dest = base + index * scale - genScaledAdd(emitTypeSize(node), node->gtRegNum, base->gtRegNum, index->gtRegNum, lsl); - break; - } - - default: - { - // tmp = scale - CodeGen::genSetRegToIcon(tmpReg, (ssize_t)node->gtElemSize, TYP_INT); - - // dest = base + index * tmp - getEmitter()->emitIns_R_R_R_R(INS_MULADD, emitTypeSize(node), node->gtRegNum, node->gtRegNum, - index->gtRegNum, tmpReg); - break; - } - } - - // dest = dest + elemOffs - getEmitter()->emitIns_R_R_I(INS_add, emitTypeSize(node), node->gtRegNum, node->gtRegNum, node->gtElemOffset); - - genProduceReg(node); -} - -//------------------------------------------------------------------------ // genCodeForIndir: Produce code for a GT_IND node. // // Arguments: diff --git a/src/jit/codegenlinear.h b/src/jit/codegenlinear.h index 40f61bce93..45927db98e 100644 --- a/src/jit/codegenlinear.h +++ b/src/jit/codegenlinear.h @@ -167,7 +167,6 @@ void genCodeForShiftRMW(GenTreeStoreInd* storeInd); void genCodeForCast(GenTreeOp* tree); void genCodeForLclAddr(GenTree* tree); -void genCodeForIndexAddr(GenTreeIndexAddr* tree); void genCodeForIndir(GenTreeIndir* tree); void genCodeForNegNot(GenTree* tree); void genCodeForLclVar(GenTreeLclVar* tree); diff --git a/src/jit/codegenxarch.cpp b/src/jit/codegenxarch.cpp index effd50e7cb..a591b8a4d0 100644 --- a/src/jit/codegenxarch.cpp +++ b/src/jit/codegenxarch.cpp @@ -1787,10 +1787,6 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode) genLeaInstruction(treeNode->AsAddrMode()); break; - case GT_INDEX_ADDR: - genCodeForIndexAddr(treeNode->AsIndexAddr()); - break; - case GT_IND: genCodeForIndir(treeNode->AsIndir()); break; @@ -4499,87 +4495,6 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* tree) } //------------------------------------------------------------------------ -// genCodeForIndexAddr: Produce code for a GT_INDEX_ADDR node. -// -// Arguments: -// tree - the GT_INDEX_ADDR node -// -void CodeGen::genCodeForIndexAddr(GenTreeIndexAddr* node) -{ - GenTree* const base = node->Arr(); - GenTree* const index = node->Index(); - - genConsumeReg(base); - genConsumeReg(index); - - regNumber tmpReg = REG_NA; - - // Generate the bounds check if necessary. - if ((node->gtFlags & GTF_INX_RNGCHK) != 0) - { - // Create a GT_IND(GT_LEA)) tree for the array length access. - GenTreeAddrMode arrLenAddr(base->TypeGet(), base, nullptr, 0, node->gtLenOffset); - arrLenAddr.gtRegNum = REG_NA; - arrLenAddr.SetContained(); - arrLenAddr.gtNext = (GenTree*)(-1); - - GenTreeIndir arrLen = indirForm(TYP_INT, &arrLenAddr); - -#ifdef _TARGET_64BIT_ - // The CLI Spec allows an array to be indexed by either an int32 or a native int. In the case that the index - // is a native int on a 64-bit platform, we will need to widen the array length and the compare. - if (index->TypeGet() == TYP_I_IMPL) - { - // Load the array length into a register. - tmpReg = node->GetSingleTempReg(); - arrLen.gtRegNum = tmpReg; - arrLen.ClearContained(); - getEmitter()->emitInsLoadInd(ins_Load(TYP_INT), EA_4BYTE, arrLen.gtRegNum, &arrLen); - } - else -#endif - { - assert(varTypeIsIntegral(index->TypeGet())); - - arrLen.gtRegNum = REG_NA; - arrLen.SetContained(); - arrLen.gtNext = (GenTree*)(-1); - } - - // Generate the range check. - getEmitter()->emitInsBinary(INS_cmp, emitTypeSize(TYP_I_IMPL), index, &arrLen); - genJumpToThrowHlpBlk(EJ_jae, SCK_RNGCHK_FAIL, node->gtIndRngFailBB); - } - - // Compute the address of the array element. - switch (node->gtElemSize) - { - case 1: - case 2: - case 4: - case 8: - getEmitter()->emitIns_R_ARX(INS_lea, emitTypeSize(node), node->gtRegNum, base->gtRegNum, index->gtRegNum, - node->gtElemSize, static_cast<int>(node->gtElemOffset)); - break; - - default: - { - // Multiply the index by the element size. - // - // TODO-CQ: this should really just use `imul index, index, #gtElemSize` - tmpReg = (tmpReg == REG_NA) ? node->GetSingleTempReg() : tmpReg; - CodeGen::genSetRegToIcon(tmpReg, (ssize_t)node->gtElemSize, TYP_INT); - inst_RV_RV(INS_imul, tmpReg, index->gtRegNum); - getEmitter()->emitIns_R_ARX(INS_lea, emitTypeSize(node), node->gtRegNum, base->gtRegNum, tmpReg, 1, - static_cast<int>(node->gtElemOffset)); - break; - } - } - - genProduceReg(node); -} - -//------------------------------------------------------------------------ // genCodeForIndir: Produce code for a GT_IND node. // // Arguments: diff --git a/src/jit/compiler.h b/src/jit/compiler.h index 916c96f2ee..78b9635dce 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -4670,8 +4670,6 @@ private: void fgSetRngChkTarget(GenTreePtr tree, bool delay = true); - BasicBlock* fgSetRngChkTargetInner(SpecialCodeKind kind, bool delay, unsigned* stkDepth); - #if REARRANGE_ADDS void fgMoveOpsLeft(GenTreePtr tree); #endif @@ -9331,26 +9329,6 @@ public: return compRoot->m_arrayInfoMap; } - inline bool TryGetArrayInfo(GenTreeIndir* indir, ArrayInfo* arrayInfo) - { - if ((indir->gtFlags & GTF_IND_ARR_INDEX) == 0) - { - return false; - } - - if (indir->gtOp1->OperIs(GT_INDEX_ADDR)) - { - GenTreeIndexAddr* const indexAddr = indir->gtOp1->AsIndexAddr(); - *arrayInfo = ArrayInfo(indexAddr->gtElemType, indexAddr->gtElemSize, indexAddr->gtElemOffset, - indexAddr->gtStructElemClass); - return true; - } - - bool found = GetArrayInfoMap()->Lookup(indir, arrayInfo); - assert(found); - return true; - } - NodeToUnsignedMap* m_memorySsaMap[MemoryKindCount]; // In some cases, we want to assign intermediate SSA #'s to memory states, and know what nodes create those memory diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp index 0f5f3dbe8d..57e5552e09 100644 --- a/src/jit/flowgraph.cpp +++ b/src/jit/flowgraph.cpp @@ -18356,13 +18356,6 @@ void Compiler::fgSetTreeSeqHelper(GenTreePtr tree, bool isLIR) noway_assert(!"DYN_BLK nodes should be sequenced as a special case"); break; - case GT_INDEX_ADDR: - // Evaluate the index first, then the array address - assert((tree->gtFlags & GTF_REVERSE_OPS) != 0); - fgSetTreeSeqHelper(tree->AsIndexAddr()->Index(), isLIR); - fgSetTreeSeqHelper(tree->AsIndexAddr()->Arr(), isLIR); - break; - default: #ifdef DEBUG gtDispTree(tree); diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp index 2284197ebd..97e0453e48 100644 --- a/src/jit/gentree.cpp +++ b/src/jit/gentree.cpp @@ -299,7 +299,6 @@ void GenTree::InitNodeSize() 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_LARGE; #ifdef FEATURE_SIMD GenTree::s_gtNodeSizes[GT_SIMD_CHK] = TREE_NODE_SZ_LARGE; @@ -1302,12 +1301,6 @@ AGAIN: return false; } break; - case GT_INDEX_ADDR: - if (op1->AsIndexAddr()->gtElemSize != op2->AsIndexAddr()->gtElemSize) - { - return false; - } - break; // For the ones below no extra argument matters for comparison. case GT_QMARK: @@ -1883,9 +1876,6 @@ AGAIN: case GT_INDEX: hash += tree->gtIndex.gtIndElemSize; break; - case GT_INDEX_ADDR: - hash += tree->AsIndexAddr()->gtElemSize; - break; case GT_ALLOCOBJ: hash = genTreeHashAdd(hash, static_cast<unsigned>( reinterpret_cast<uintptr_t>(tree->gtAllocObj.gtAllocObjClsHnd))); @@ -1948,7 +1938,6 @@ AGAIN: case GT_ARR_INDEX: case GT_QMARK: case GT_INDEX: - case GT_INDEX_ADDR: break; #ifdef FEATURE_SIMD @@ -4787,23 +4776,6 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) } break; - case GT_INDEX_ADDR: - costEx = 6; // cmp reg,reg; jae throw; mov reg, [addrmode] (not taken) - costSz = 9; // jump to cold section - - level = gtSetEvalOrder(tree->AsIndexAddr()->Index()); - costEx += tree->AsIndexAddr()->Index()->gtCostEx; - costSz += tree->AsIndexAddr()->Index()->gtCostSz; - - lvl2 = gtSetEvalOrder(tree->AsIndexAddr()->Arr()); - if (level < lvl2) - { - level = lvl2; - } - costEx += tree->AsIndexAddr()->Arr()->gtCostEx; - costSz += tree->AsIndexAddr()->Arr()->gtCostSz; - break; - default: #ifdef DEBUG if (verbose) @@ -5836,7 +5808,6 @@ bool GenTree::OperMayThrow() #ifdef FEATURE_SIMD case GT_SIMD_CHK: #endif // FEATURE_SIMD - case GT_INDEX_ADDR: return true; default: break; @@ -7440,19 +7411,6 @@ GenTreePtr Compiler::gtCloneExpr( } break; - case GT_INDEX_ADDR: - { - GenTreeIndexAddr* asIndAddr = tree->AsIndexAddr(); - - copy = new (this, GT_INDEX_ADDR) - GenTreeIndexAddr(asIndAddr->Arr(), asIndAddr->Index(), asIndAddr->gtElemType, - asIndAddr->gtStructElemClass, asIndAddr->gtElemSize, asIndAddr->gtLenOffset, - asIndAddr->gtElemOffset); - copy->AsIndexAddr()->gtIndRngFailBB = asIndAddr->gtIndRngFailBB; - copy->AsIndexAddr()->gtStkDepth = asIndAddr->gtStkDepth; - } - break; - case GT_ALLOCOBJ: { GenTreeAllocObj* asAllocObj = tree->AsAllocObj(); @@ -9621,7 +9579,6 @@ void Compiler::gtDispNode(GenTreePtr tree, IndentStack* indentStack, __in __in_z __fallthrough; case GT_INDEX: - case GT_INDEX_ADDR: if ((tree->gtFlags & (GTF_IND_VOLATILE | GTF_IND_UNALIGNED)) == 0) // We prefer printing V or U over R { @@ -15755,9 +15712,6 @@ CORINFO_CLASS_HANDLE Compiler::gtGetStructHandleIfPresent(GenTree* tree) case GT_INDEX: structHnd = tree->gtIndex.gtStructElemClass; break; - case GT_INDEX_ADDR: - structHnd = tree->AsIndexAddr()->gtStructElemClass; - break; case GT_FIELD: info.compCompHnd->getFieldType(tree->gtField.gtFldHnd, &structHnd); break; @@ -15786,12 +15740,12 @@ CORINFO_CLASS_HANDLE Compiler::gtGetStructHandleIfPresent(GenTree* tree) } else #endif + if (tree->gtFlags & GTF_IND_ARR_INDEX) { ArrayInfo arrInfo; - if (TryGetArrayInfo(tree->AsIndir(), &arrInfo)) - { - structHnd = EncodeElemType(arrInfo.m_elemType, arrInfo.m_elemStructType); - } + bool b = GetArrayInfoMap()->Lookup(tree, &arrInfo); + assert(b); + structHnd = EncodeElemType(arrInfo.m_elemType, arrInfo.m_elemStructType); } break; #ifdef FEATURE_SIMD diff --git a/src/jit/gentree.h b/src/jit/gentree.h index 2f99ce4955..a5d0337f6d 100644 --- a/src/jit/gentree.h +++ b/src/jit/gentree.h @@ -4243,68 +4243,6 @@ struct GenTreeIndex : public GenTreeOp #endif }; -// gtIndexAddr: given an array object and an index, checks that the index is within the bounds of the array if -// necessary and produces the address of the value at that index of the array. -struct GenTreeIndexAddr : public GenTreeOp -{ - GenTree*& Arr() - { - return gtOp1; - } - GenTree*& Index() - { - return gtOp2; - } - - CORINFO_CLASS_HANDLE gtStructElemClass; // If the element type is a struct, this is the struct type. - - GenTree* gtIndRngFailBB; // Label to jump to for array-index-out-of-range - unsigned gtStkDepth; // Stack depth at which the jump occurs (required for fgSetRngChkTarget) - - var_types gtElemType; // The element type of the array. - unsigned gtElemSize; // size of elements in the array - unsigned gtLenOffset; // The offset from the array's base address to its length. - unsigned gtElemOffset; // The offset from the array's base address to its first element. - - GenTreeIndexAddr(GenTree* arr, - GenTree* ind, - var_types elemType, - CORINFO_CLASS_HANDLE structElemClass, - unsigned elemSize, - unsigned lenOffset, - unsigned elemOffset) - : GenTreeOp(GT_INDEX_ADDR, TYP_BYREF, arr, ind) - , gtStructElemClass(structElemClass) - , gtIndRngFailBB(nullptr) - , gtStkDepth(0) - , gtElemType(elemType) - , gtElemSize(elemSize) - , gtLenOffset(lenOffset) - , gtElemOffset(elemOffset) - { -#ifdef DEBUG - if (JitConfig.JitSkipArrayBoundCheck() == 1) - { - // Skip bounds check - } - else -#endif - { - // Do bounds check - gtFlags |= GTF_INX_RNGCHK; - } - - // REVERSE_OPS is set because we must evaluate the index before the array address. - gtFlags |= GTF_EXCEPT | GTF_GLOB_REF | GTF_REVERSE_OPS; - } - -#if DEBUGGABLE_GENTREE - GenTreeIndexAddr() : GenTreeOp() - { - } -#endif -}; - /* gtArrLen -- array length (GT_ARR_LENGTH) GT_ARR_LENGTH is used for "arr.length" */ diff --git a/src/jit/gtlist.h b/src/jit/gtlist.h index 544023391f..7e78b27dd2 100644 --- a/src/jit/gtlist.h +++ b/src/jit/gtlist.h @@ -163,8 +163,6 @@ GTNODE(QMARK , GenTreeQmark ,0,GTK_BINOP|GTK_EXOP|GTK_NOTLIR) GTNODE(COLON , GenTreeColon ,0,GTK_BINOP|GTK_NOTLIR) GTNODE(INDEX , GenTreeIndex ,0,GTK_BINOP|GTK_EXOP|GTK_NOTLIR) // SZ-array-element -GTNODE(INDEX_ADDR , GenTreeIndex ,0,GTK_BINOP|GTK_EXOP) // addr of SZ-array-element; used when - // aiming to minimize compile times. GTNODE(MKREFANY , GenTreeOp ,0,GTK_BINOP) diff --git a/src/jit/gtstructs.h b/src/jit/gtstructs.h index 34d1794f4b..1d623b71ff 100644 --- a/src/jit/gtstructs.h +++ b/src/jit/gtstructs.h @@ -71,7 +71,6 @@ GTSTRUCT_1(Colon , GT_COLON) GTSTRUCT_1(FptrVal , GT_FTN_ADDR) GTSTRUCT_1(Intrinsic , GT_INTRINSIC) GTSTRUCT_1(Index , GT_INDEX) -GTSTRUCT_1(IndexAddr , GT_INDEX_ADDR) #ifdef FEATURE_SIMD GTSTRUCT_2(BoundsChk , GT_ARR_BOUNDS_CHECK, GT_SIMD_CHK) #else // !FEATURE_SIMD diff --git a/src/jit/lsraarm.cpp b/src/jit/lsraarm.cpp index 49127052cb..bfe25bf99b 100644 --- a/src/jit/lsraarm.cpp +++ b/src/jit/lsraarm.cpp @@ -769,12 +769,6 @@ void LinearScan::TreeNodeInfoInit(GenTree* tree) unreached(); } break; - - case GT_INDEX_ADDR: - info->srcCount = 2; - info->dstCount = 1; - info->internalIntCount = 1; - break; } // end switch (tree->OperGet()) // We need to be sure that we've set info->srcCount and info->dstCount appropriately diff --git a/src/jit/lsraarm64.cpp b/src/jit/lsraarm64.cpp index 66a45192d0..dc2ceb7b76 100644 --- a/src/jit/lsraarm64.cpp +++ b/src/jit/lsraarm64.cpp @@ -661,12 +661,6 @@ void LinearScan::TreeNodeInfoInit(GenTree* tree) assert((tree->gtFlags & (GTF_VAR_DEF | GTF_VAR_USEASG)) == 0); info->internalIntCount = 1; break; - - case GT_INDEX_ADDR: - info->srcCount = 2; - info->dstCount = 1; - info->internalIntCount = 1; - break; } // end switch (tree->OperGet()) // We need to be sure that we've set info->srcCount and info->dstCount appropriately diff --git a/src/jit/lsraxarch.cpp b/src/jit/lsraxarch.cpp index 4945db32b4..7455569b46 100644 --- a/src/jit/lsraxarch.cpp +++ b/src/jit/lsraxarch.cpp @@ -613,31 +613,6 @@ void LinearScan::TreeNodeInfoInit(GenTree* tree) JITDUMP("Unexpected node %s in Lower.\n", GenTree::OpName(tree->OperGet())); unreached(); break; - - case GT_INDEX_ADDR: - info->srcCount = 2; - info->dstCount = 1; - - if (tree->AsIndexAddr()->Index()->TypeGet() == TYP_I_IMPL) - { - info->internalIntCount = 1; - } - else - { - switch (tree->AsIndexAddr()->gtElemSize) - { - case 1: - case 2: - case 4: - case 8: - break; - - default: - info->internalIntCount = 1; - break; - } - } - break; } // end switch (tree->OperGet()) // If op2 of a binary-op gets marked as contained, then binary-op srcCount will be 1. diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp index 45a8d14afb..d7b3aae456 100644 --- a/src/jit/morph.cpp +++ b/src/jit/morph.cpp @@ -5720,78 +5720,76 @@ void Compiler::fgMoveOpsLeft(GenTreePtr tree) /*****************************************************************************/ -void Compiler::fgSetRngChkTarget(GenTree* tree, bool delay) +void Compiler::fgSetRngChkTarget(GenTreePtr tree, bool delay) { - if (tree->OperIsBoundsCheck()) - { - GenTreeBoundsChk* const boundsChk = tree->AsBoundsChk(); - BasicBlock* const failBlock = fgSetRngChkTargetInner(boundsChk->gtThrowKind, delay, &boundsChk->gtStkDepth); - if (failBlock != nullptr) - { - boundsChk->gtIndRngFailBB = gtNewCodeRef(failBlock); - } - } - else if (tree->OperIs(GT_INDEX_ADDR)) + GenTreeBoundsChk* bndsChk = nullptr; + SpecialCodeKind kind = SCK_RNGCHK_FAIL; + +#ifdef FEATURE_SIMD + if ((tree->gtOper == GT_ARR_BOUNDS_CHECK) || (tree->gtOper == GT_SIMD_CHK)) +#else // FEATURE_SIMD + if (tree->gtOper == GT_ARR_BOUNDS_CHECK) +#endif // FEATURE_SIMD { - GenTreeIndexAddr* const indexAddr = tree->AsIndexAddr(); - BasicBlock* const failBlock = fgSetRngChkTargetInner(SCK_RNGCHK_FAIL, delay, &indexAddr->gtStkDepth); - if (failBlock != nullptr) - { - indexAddr->gtIndRngFailBB = gtNewCodeRef(failBlock); - } + bndsChk = tree->AsBoundsChk(); + kind = tree->gtBoundsChk.gtThrowKind; } else { - noway_assert(tree->OperIs(GT_ARR_ELEM, GT_ARR_INDEX)); - fgSetRngChkTargetInner(SCK_RNGCHK_FAIL, delay, nullptr); + noway_assert((tree->gtOper == GT_ARR_ELEM) || (tree->gtOper == GT_ARR_INDEX)); } -} -BasicBlock* Compiler::fgSetRngChkTargetInner(SpecialCodeKind kind, bool delay, unsigned* stkDepth) -{ +#ifdef _TARGET_X86_ + unsigned callStkDepth = fgPtrArgCntCur; +#else + // only x86 pushes args + const unsigned callStkDepth = 0; +#endif + if (opts.MinOpts()) { delay = false; -#ifdef _TARGET_X86_ // we need to initialize this field - if (fgGlobalMorph && (stkDepth != nullptr)) + if (fgGlobalMorph && bndsChk != nullptr) { - *stkDepth = fgPtrArgCntCur; + bndsChk->gtStkDepth = callStkDepth; } -#endif // _TARGET_X86_ } if (!opts.compDbgCode) { if (delay || compIsForInlining()) { -#ifdef _TARGET_X86_ - // We delay this until after loop-oriented range check analysis. For now we merely store the current stack - // level in the tree node. - if (stkDepth != nullptr) + /* We delay this until after loop-oriented range check + analysis. For now we merely store the current stack + level in the tree node. + */ + if (bndsChk != nullptr) { - *stkDepth = fgPtrArgCntCur; + noway_assert(!bndsChk->gtIndRngFailBB || previousCompletedPhase >= PHASE_OPTIMIZE_LOOPS); + bndsChk->gtStkDepth = callStkDepth; } -#endif // _TARGET_X86_ } else { -#ifdef _TARGET_X86_ + /* Create/find the appropriate "range-fail" label */ + // fgPtrArgCntCur is only valid for global morph or if we walk full stmt. - noway_assert(fgGlobalMorph || (stkDepth != nullptr)); - const unsigned theStkDepth = fgGlobalMorph ? fgPtrArgCntCur : *stkDepth; -#else - // only x86 pushes args - const unsigned theStkDepth = 0; -#endif + noway_assert((bndsChk != nullptr) || fgGlobalMorph); - // Create/find the appropriate "range-fail" label - return fgRngChkTarget(compCurBB, theStkDepth, kind); + unsigned stkDepth = (bndsChk != nullptr) ? bndsChk->gtStkDepth : callStkDepth; + + BasicBlock* rngErrBlk = fgRngChkTarget(compCurBB, stkDepth, kind); + + /* Add the label to the indirection node */ + + if (bndsChk != nullptr) + { + bndsChk->gtIndRngFailBB = gtNewCodeRef(rngErrBlk); + } } } - - return nullptr; } /***************************************************************************** @@ -5846,6 +5844,9 @@ GenTreePtr Compiler::fgMorphArrayIndex(GenTreePtr tree) } #endif // FEATURE_SIMD + GenTreePtr arrRef = asIndex->Arr(); + GenTreePtr index = asIndex->Index(); + // Set up the the array length's offset into lenOffs // And the the first element's offset into elemOffs ssize_t lenOffs; @@ -5867,58 +5868,6 @@ GenTreePtr Compiler::fgMorphArrayIndex(GenTreePtr tree) elemOffs = offsetof(CORINFO_Array, u1Elems); } -#ifndef LEGACY_BACKEND - // In minopts, we expand GT_INDEX to GT_IND(GT_INDEX_ADDR) in order to minimize the size of the IR. As minopts - // compilation time is roughly proportional to the size of the IR, this helps keep compilation times down. - // Furthermore, this representation typically saves on code size in minopts w.r.t. the complete expansion - // performed when optimizing, as it does not require LclVar nodes (which are always stack loads/stores in - // minopts). - // - // When we *are* optimizing, we fully expand GT_INDEX to: - // 1. Evaluate the array address expression and store the result in a temp if the expression is complex or - // 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_CHK(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. - // - // This expansion explicitly exposes the bounds check and the address calculation to the optimizer, which allows - // for more straightforward bounds-check removal, CSE, etc. - if (opts.MinOpts()) - { - GenTree* const array = fgMorphTree(asIndex->Arr()); - GenTree* const index = fgMorphTree(asIndex->Index()); - - GenTreeIndexAddr* const indexAddr = - new (this, GT_INDEX_ADDR) GenTreeIndexAddr(array, index, elemTyp, elemStructType, elemSize, - static_cast<unsigned>(lenOffs), static_cast<unsigned>(elemOffs)); - indexAddr->gtFlags |= (array->gtFlags | index->gtFlags) & GTF_ALL_EFFECT; - - // Mark the indirection node as needing a range check if necessary. - if ((indexAddr->gtFlags & GTF_INX_RNGCHK) != 0) - { - fgSetRngChkTarget(indexAddr); - } - - // Change `tree` into an indirection and return. - tree->ChangeOper(GT_IND); - GenTreeIndir* const indir = tree->AsIndir(); - indir->Addr() = indexAddr; - indir->gtFlags = GTF_IND_ARR_INDEX | (indexAddr->gtFlags & GTF_ALL_EFFECT); - -#ifdef DEBUG - indexAddr->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED; -#endif // DEBUG - - return indir; - } -#endif // LEGACY_BACKEND - - GenTreePtr arrRef = asIndex->Arr(); - GenTreePtr index = asIndex->Index(); - bool chkd = ((tree->gtFlags & GTF_INX_RNGCHK) != 0); // if false, range checking will be disabled bool nCSE = ((tree->gtFlags & GTF_DONT_CSE) != 0); @@ -9944,9 +9893,6 @@ GenTreePtr Compiler::fgMorphGetStructAddr(GenTreePtr* pTree, CORINFO_CLASS_HANDL case GT_ARR_ELEM: addr = gtNewOperNode(GT_ADDR, TYP_BYREF, tree); break; - case GT_INDEX_ADDR: - addr = tree; - break; default: { // TODO: Consider using lvaGrabTemp and gtNewTempAssign instead, since we're @@ -9974,12 +9920,10 @@ GenTreePtr Compiler::fgMorphGetStructAddr(GenTreePtr* pTree, CORINFO_CLASS_HANDL GenTree* Compiler::fgMorphBlkNode(GenTreePtr tree, bool isDest) { - GenTree* handleTree = nullptr; - GenTree* addr = nullptr; - if (tree->OperIs(GT_COMMA)) + if (tree->gtOper == GT_COMMA) { GenTree* effectiveVal = tree->gtEffectiveVal(); - addr = gtNewOperNode(GT_ADDR, TYP_BYREF, effectiveVal); + GenTree* addr = gtNewOperNode(GT_ADDR, TYP_BYREF, effectiveVal); #ifdef DEBUG addr->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED; #endif @@ -10002,24 +9946,13 @@ GenTree* Compiler::fgMorphBlkNode(GenTreePtr tree, bool isDest) lastComma->gtOp.gtOp2 = addr; addr = tree; } - - handleTree = effectiveVal; - } - else if (tree->OperIs(GT_IND) && tree->AsIndir()->Addr()->OperIs(GT_INDEX_ADDR)) - { - handleTree = tree; - addr = tree->AsIndir()->Addr(); - } - - if (addr != nullptr) - { - var_types structType = handleTree->TypeGet(); + var_types structType = effectiveVal->TypeGet(); if (structType == TYP_STRUCT) { - CORINFO_CLASS_HANDLE structHnd = gtGetStructHandleIfPresent(handleTree); + CORINFO_CLASS_HANDLE structHnd = gtGetStructHandleIfPresent(effectiveVal); if (structHnd == NO_CLASS_HANDLE) { - tree = gtNewOperNode(GT_IND, structType, addr); + tree = gtNewOperNode(GT_IND, effectiveVal->TypeGet(), addr); } else { @@ -15667,11 +15600,6 @@ GenTreePtr Compiler::fgMorphTree(GenTreePtr tree, MorphAddrContext* mac) tree->gtDynBlk.gtDynamicSize = fgMorphTree(tree->gtDynBlk.gtDynamicSize); break; - case GT_INDEX_ADDR: - tree->AsIndexAddr()->Index() = fgMorphTree(tree->AsIndexAddr()->Index()); - tree->AsIndexAddr()->Arr() = fgMorphTree(tree->AsIndexAddr()->Arr()); - break; - default: #ifdef DEBUG gtDispTree(tree); |