summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kotas <jkotas@microsoft.com>2017-08-30 06:35:44 -0700
committerGitHub <noreply@github.com>2017-08-30 06:35:44 -0700
commitbec6ac10f3968a8f699aad6233657ac59df37a73 (patch)
treee15ceba1e2db154612457bee107dd85d627ad81a
parent4d9f5e3a0bc2b01c99337d68a8c90fc77b3182bd (diff)
downloadcoreclr-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.cpp89
-rw-r--r--src/jit/codegenlinear.h1
-rw-r--r--src/jit/codegenxarch.cpp85
-rw-r--r--src/jit/compiler.h22
-rw-r--r--src/jit/flowgraph.cpp7
-rw-r--r--src/jit/gentree.cpp54
-rw-r--r--src/jit/gentree.h62
-rw-r--r--src/jit/gtlist.h2
-rw-r--r--src/jit/gtstructs.h1
-rw-r--r--src/jit/lsraarm.cpp6
-rw-r--r--src/jit/lsraarm64.cpp6
-rw-r--r--src/jit/lsraxarch.cpp25
-rw-r--r--src/jit/morph.cpp170
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);