diff options
Diffstat (limited to 'src/jit/gentree.cpp')
-rw-r--r-- | src/jit/gentree.cpp | 315 |
1 files changed, 198 insertions, 117 deletions
diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp index 4a6cc740c6..7af500f877 100644 --- a/src/jit/gentree.cpp +++ b/src/jit/gentree.cpp @@ -678,7 +678,7 @@ Compiler::fgWalkResult Compiler::fgWalkTreePreRec(GenTreePtr* pTree, fgWalkData* if (kind & GTK_SMPOP) { - if (tree->gtGetOp2()) + if (tree->gtGetOp2IfPresent()) { if (tree->gtOp.gtOp1 != nullptr) { @@ -847,12 +847,12 @@ Compiler::fgWalkResult Compiler::fgWalkTreePreRec(GenTreePtr* pTree, fgWalkData* #ifdef FEATURE_SIMD case GT_SIMD_CHK: #endif // FEATURE_SIMD - result = fgWalkTreePreRec<computeStack>(&tree->gtBoundsChk.gtArrLen, fgWalkData); + result = fgWalkTreePreRec<computeStack>(&tree->gtBoundsChk.gtIndex, fgWalkData); if (result == WALK_ABORT) { return result; } - result = fgWalkTreePreRec<computeStack>(&tree->gtBoundsChk.gtIndex, fgWalkData); + result = fgWalkTreePreRec<computeStack>(&tree->gtBoundsChk.gtArrLen, fgWalkData); if (result == WALK_ABORT) { return result; @@ -1102,12 +1102,12 @@ Compiler::fgWalkResult Compiler::fgWalkTreePostRec(GenTreePtr* pTree, fgWalkData #ifdef FEATURE_SIMD case GT_SIMD_CHK: #endif // FEATURE_SIMD - result = fgWalkTreePostRec<computeStack>(&tree->gtBoundsChk.gtArrLen, fgWalkData); + result = fgWalkTreePostRec<computeStack>(&tree->gtBoundsChk.gtIndex, fgWalkData); if (result == WALK_ABORT) { return result; } - result = fgWalkTreePostRec<computeStack>(&tree->gtBoundsChk.gtIndex, fgWalkData); + result = fgWalkTreePostRec<computeStack>(&tree->gtBoundsChk.gtArrLen, fgWalkData); if (result == WALK_ABORT) { return result; @@ -1301,7 +1301,7 @@ Compiler::fgWalkResult Compiler::fgWalkTreeRec(GenTreePtr* pTree, fgWalkData* fg } } - if (tree->gtGetOp2()) + if (tree->gtGetOp2IfPresent()) { result = fgWalkTreeRec<doPreOrder, doPostOrder>(&tree->gtOp.gtOp2, fgWalkData); if (result == WALK_ABORT) @@ -1446,12 +1446,12 @@ Compiler::fgWalkResult Compiler::fgWalkTreeRec(GenTreePtr* pTree, fgWalkData* fg #ifdef FEATURE_SIMD case GT_SIMD_CHK: #endif // FEATURE_SIMD - result = fgWalkTreeRec<doPreOrder, doPostOrder>(&tree->gtBoundsChk.gtArrLen, fgWalkData); + result = fgWalkTreeRec<doPreOrder, doPostOrder>(&tree->gtBoundsChk.gtIndex, fgWalkData); if (result == WALK_ABORT) { return result; } - result = fgWalkTreeRec<doPreOrder, doPostOrder>(&tree->gtBoundsChk.gtIndex, fgWalkData); + result = fgWalkTreeRec<doPreOrder, doPostOrder>(&tree->gtBoundsChk.gtArrLen, fgWalkData); if (result == WALK_ABORT) { return result; @@ -2378,8 +2378,8 @@ AGAIN: #ifdef FEATURE_SIMD case GT_SIMD_CHK: #endif // FEATURE_SIMD - return Compare(op1->gtBoundsChk.gtArrLen, op2->gtBoundsChk.gtArrLen) && - Compare(op1->gtBoundsChk.gtIndex, op2->gtBoundsChk.gtIndex) && + return Compare(op1->gtBoundsChk.gtIndex, op2->gtBoundsChk.gtIndex) && + Compare(op1->gtBoundsChk.gtArrLen, op2->gtBoundsChk.gtArrLen) && (op1->gtBoundsChk.gtThrowKind == op2->gtBoundsChk.gtThrowKind); case GT_STORE_DYN_BLK: @@ -2447,7 +2447,7 @@ AGAIN: if (kind & GTK_SMPOP) { - if (tree->gtGetOp2()) + if (tree->gtGetOp2IfPresent()) { if (gtHasRef(tree->gtOp.gtOp1, lclNum, defOnly)) { @@ -2604,11 +2604,11 @@ AGAIN: #ifdef FEATURE_SIMD case GT_SIMD_CHK: #endif // FEATURE_SIMD - if (gtHasRef(tree->gtBoundsChk.gtArrLen, lclNum, defOnly)) + if (gtHasRef(tree->gtBoundsChk.gtIndex, lclNum, defOnly)) { return true; } - if (gtHasRef(tree->gtBoundsChk.gtIndex, lclNum, defOnly)) + if (gtHasRef(tree->gtBoundsChk.gtArrLen, lclNum, defOnly)) { return true; } @@ -2686,6 +2686,8 @@ bool Compiler::gtHasLocalsWithAddrOp(GenTreePtr tree) return desc.hasAddrTakenLcl; } +#ifdef DEBUG + /***************************************************************************** * * Helper used to compute hash values for trees. @@ -2701,11 +2703,6 @@ inline unsigned genTreeHashAdd(unsigned old, void* add) return genTreeHashAdd(old, (unsigned)(size_t)add); } -inline unsigned genTreeHashAdd(unsigned old, unsigned add1, unsigned add2) -{ - return (old + old / 2) ^ add1 ^ add2; -} - /***************************************************************************** * * Given an arbitrary expression tree, compute a hash value for it. @@ -2900,18 +2897,6 @@ AGAIN: unsigned hsh1 = gtHashValue(op1); - /* Special case: addition of two values */ - - if (GenTree::OperIsCommutative(oper)) - { - unsigned hsh2 = gtHashValue(op2); - - /* Produce a hash that allows swapping the operands */ - - hash = genTreeHashAdd(hash, hsh1, hsh2); - goto DONE; - } - /* Add op1's hash to the running value and continue with op2 */ hash = genTreeHashAdd(hash, hsh1); @@ -3001,8 +2986,8 @@ AGAIN: #ifdef FEATURE_SIMD case GT_SIMD_CHK: #endif // FEATURE_SIMD - hash = genTreeHashAdd(hash, gtHashValue(tree->gtBoundsChk.gtArrLen)); hash = genTreeHashAdd(hash, gtHashValue(tree->gtBoundsChk.gtIndex)); + hash = genTreeHashAdd(hash, gtHashValue(tree->gtBoundsChk.gtArrLen)); hash = genTreeHashAdd(hash, tree->gtBoundsChk.gtThrowKind); break; @@ -3027,6 +3012,8 @@ DONE: return hash; } +#endif // DEBUG + /***************************************************************************** * * Given an arbitrary expression tree, attempts to find the set of all local variables @@ -3194,7 +3181,7 @@ AGAIN: } } - if (tree->gtGetOp2()) + if (tree->gtGetOp2IfPresent()) { /* It's a binary operator */ if (!lvaLclVarRefsAccum(tree->gtOp.gtOp1, findPtr, refsPtr, &allVars, &trkdVars)) @@ -3265,12 +3252,12 @@ AGAIN: case GT_SIMD_CHK: #endif // FEATURE_SIMD { - if (!lvaLclVarRefsAccum(tree->gtBoundsChk.gtArrLen, findPtr, refsPtr, &allVars, &trkdVars)) + if (!lvaLclVarRefsAccum(tree->gtBoundsChk.gtIndex, findPtr, refsPtr, &allVars, &trkdVars)) { return false; } // Otherwise... - if (!lvaLclVarRefsAccum(tree->gtBoundsChk.gtIndex, findPtr, refsPtr, &allVars, &trkdVars)) + if (!lvaLclVarRefsAccum(tree->gtBoundsChk.gtArrLen, findPtr, refsPtr, &allVars, &trkdVars)) { return false; } @@ -3375,6 +3362,10 @@ genTreeOps GenTree::ReverseRelop(genTreeOps relop) GT_GT, // GT_LE GT_LT, // GT_GE GT_LE, // GT_GT +#ifndef LEGACY_BACKEND + GT_TEST_NE, // GT_TEST_EQ + GT_TEST_EQ, // GT_TEST_NE +#endif }; assert(reverseOps[GT_EQ - GT_EQ] == GT_NE); @@ -3385,6 +3376,11 @@ genTreeOps GenTree::ReverseRelop(genTreeOps relop) assert(reverseOps[GT_GE - GT_EQ] == GT_LT); assert(reverseOps[GT_GT - GT_EQ] == GT_LE); +#ifndef LEGACY_BACKEND + assert(reverseOps[GT_TEST_EQ - GT_EQ] == GT_TEST_NE); + assert(reverseOps[GT_TEST_NE - GT_EQ] == GT_TEST_EQ); +#endif + assert(OperIsCompare(relop)); assert(relop >= GT_EQ && (unsigned)(relop - GT_EQ) < sizeof(reverseOps)); @@ -3406,6 +3402,10 @@ genTreeOps GenTree::SwapRelop(genTreeOps relop) GT_GE, // GT_LE GT_LE, // GT_GE GT_LT, // GT_GT +#ifndef LEGACY_BACKEND + GT_TEST_EQ, // GT_TEST_EQ + GT_TEST_NE, // GT_TEST_NE +#endif }; assert(swapOps[GT_EQ - GT_EQ] == GT_EQ); @@ -3416,6 +3416,11 @@ genTreeOps GenTree::SwapRelop(genTreeOps relop) assert(swapOps[GT_GE - GT_EQ] == GT_LE); assert(swapOps[GT_GT - GT_EQ] == GT_LT); +#ifndef LEGACY_BACKEND + assert(swapOps[GT_TEST_EQ - GT_EQ] == GT_TEST_EQ); + assert(swapOps[GT_TEST_NE - GT_EQ] == GT_TEST_NE); +#endif + assert(OperIsCompare(relop)); assert(relop >= GT_EQ && (unsigned)(relop - GT_EQ) < sizeof(swapOps)); @@ -4146,7 +4151,7 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) unsigned lvl2; // scratch variable GenTreePtr op1 = tree->gtOp.gtOp1; - GenTreePtr op2 = tree->gtGetOp2(); + GenTreePtr op2 = tree->gtGetOp2IfPresent(); costEx = 0; costSz = 0; @@ -5622,17 +5627,17 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) costEx = 4; // cmp reg,reg and jae throw (not taken) costSz = 7; // jump to cold section - level = gtSetEvalOrder(tree->gtBoundsChk.gtArrLen); - costEx += tree->gtBoundsChk.gtArrLen->gtCostEx; - costSz += tree->gtBoundsChk.gtArrLen->gtCostSz; + level = gtSetEvalOrder(tree->gtBoundsChk.gtIndex); + costEx += tree->gtBoundsChk.gtIndex->gtCostEx; + costSz += tree->gtBoundsChk.gtIndex->gtCostSz; - lvl2 = gtSetEvalOrder(tree->gtBoundsChk.gtIndex); + lvl2 = gtSetEvalOrder(tree->gtBoundsChk.gtArrLen); if (level < lvl2) { level = lvl2; } - costEx += tree->gtBoundsChk.gtIndex->gtCostEx; - costSz += tree->gtBoundsChk.gtIndex->gtCostSz; + costEx += tree->gtBoundsChk.gtArrLen->gtCostEx; + costSz += tree->gtBoundsChk.gtArrLen->gtCostSz; break; @@ -5761,7 +5766,7 @@ void Compiler::gtComputeFPlvls(GenTreePtr tree) if (kind & GTK_SMPOP) { GenTreePtr op1 = tree->gtOp.gtOp1; - GenTreePtr op2 = tree->gtGetOp2(); + GenTreePtr op2 = tree->gtGetOp2IfPresent(); /* Check for some special cases */ @@ -5954,16 +5959,16 @@ void Compiler::gtComputeFPlvls(GenTreePtr tree) break; case GT_ARR_BOUNDS_CHECK: - gtComputeFPlvls(tree->gtBoundsChk.gtArrLen); gtComputeFPlvls(tree->gtBoundsChk.gtIndex); + gtComputeFPlvls(tree->gtBoundsChk.gtArrLen); noway_assert(!isflt); break; -#ifdef DEBUG default: +#ifdef DEBUG noway_assert(!"Unhandled special operator in gtComputeFPlvls()"); - break; #endif + break; } DONE: @@ -6134,14 +6139,14 @@ GenTreePtr* GenTree::gtGetChildPointer(GenTreePtr parent) #ifdef FEATURE_SIMD case GT_SIMD_CHK: #endif // FEATURE_SIMD - if (this == parent->gtBoundsChk.gtArrLen) - { - return &(parent->gtBoundsChk.gtArrLen); - } if (this == parent->gtBoundsChk.gtIndex) { return &(parent->gtBoundsChk.gtIndex); } + if (this == parent->gtBoundsChk.gtArrLen) + { + return &(parent->gtBoundsChk.gtArrLen); + } if (this == parent->gtBoundsChk.gtIndRngFailBB) { return &(parent->gtBoundsChk.gtIndRngFailBB); @@ -6787,6 +6792,57 @@ GenTreePtr Compiler::gtNewOneConNode(var_types type) } } +#ifdef FEATURE_SIMD +//--------------------------------------------------------------------- +// gtNewSIMDVectorZero: create a GT_SIMD node for Vector<T>.Zero +// +// Arguments: +// simdType - simd vector type +// baseType - element type of vector +// size - size of vector in bytes +GenTreePtr Compiler::gtNewSIMDVectorZero(var_types simdType, var_types baseType, unsigned size) +{ + baseType = genActualType(baseType); + GenTree* initVal = gtNewZeroConNode(baseType); + initVal->gtType = baseType; + return gtNewSIMDNode(simdType, initVal, nullptr, SIMDIntrinsicInit, baseType, size); +} + +//--------------------------------------------------------------------- +// gtNewSIMDVectorOne: create a GT_SIMD node for Vector<T>.One +// +// Arguments: +// simdType - simd vector type +// baseType - element type of vector +// size - size of vector in bytes +GenTreePtr Compiler::gtNewSIMDVectorOne(var_types simdType, var_types baseType, unsigned size) +{ + GenTree* initVal; + if (varTypeIsSmallInt(baseType)) + { + unsigned baseSize = genTypeSize(baseType); + int val; + if (baseSize == 1) + { + val = 0x01010101; + } + else + { + val = 0x00010001; + } + initVal = gtNewIconNode(val); + } + else + { + initVal = gtNewOneConNode(baseType); + } + + baseType = genActualType(baseType); + initVal->gtType = baseType; + return gtNewSIMDNode(simdType, initVal, nullptr, SIMDIntrinsicInit, baseType, size); +} +#endif // FEATURE_SIMD + GenTreeCall* Compiler::gtNewIndCallNode(GenTreePtr addr, var_types type, GenTreeArgList* args, IL_OFFSETX ilOffset) { return gtNewCallNode(CT_INDIRECT, (CORINFO_METHOD_HANDLE)addr, type, args, ilOffset); @@ -7525,9 +7581,7 @@ void Compiler::gtBlockOpInit(GenTreePtr result, GenTreePtr dst, GenTreePtr srcOr if (dst->OperIsLocal() && varTypeIsStruct(dst)) { - unsigned lclNum = dst->AsLclVarCommon()->GetLclNum(); - LclVarDsc* lclVarDsc = &lvaTable[lclNum]; - lclVarDsc->lvUsedInSIMDIntrinsic = true; + setLclRelatedToSIMDIntrinsic(dst); } } } @@ -8031,7 +8085,7 @@ GenTreePtr Compiler::gtCloneExpr( case GT_SIMD: { GenTreeSIMD* simdOp = tree->AsSIMD(); - copy = gtNewSIMDNode(simdOp->TypeGet(), simdOp->gtGetOp1(), simdOp->gtGetOp2(), + copy = gtNewSIMDNode(simdOp->TypeGet(), simdOp->gtGetOp1(), simdOp->gtGetOp2IfPresent(), simdOp->gtSIMDIntrinsicID, simdOp->gtSIMDBaseType, simdOp->gtSIMDSize); } break; @@ -8079,7 +8133,7 @@ GenTreePtr Compiler::gtCloneExpr( } } - if (tree->gtGetOp2()) + if (tree->gtGetOp2IfPresent()) { copy->gtOp.gtOp2 = gtCloneExpr(tree->gtOp.gtOp2, addFlags, deepVarNum, deepVarVal); } @@ -8130,7 +8184,7 @@ GenTreePtr Compiler::gtCloneExpr( { copy->gtFlags |= (copy->gtOp.gtOp1->gtFlags & GTF_ALL_EFFECT); } - if (copy->gtGetOp2() != nullptr) + if (copy->gtGetOp2IfPresent() != nullptr) { copy->gtFlags |= (copy->gtGetOp2()->gtFlags & GTF_ALL_EFFECT); } @@ -8290,8 +8344,8 @@ GenTreePtr Compiler::gtCloneExpr( #endif // FEATURE_SIMD copy = new (this, oper) GenTreeBoundsChk(oper, tree->TypeGet(), - gtCloneExpr(tree->gtBoundsChk.gtArrLen, addFlags, deepVarNum, deepVarVal), gtCloneExpr(tree->gtBoundsChk.gtIndex, addFlags, deepVarNum, deepVarVal), + gtCloneExpr(tree->gtBoundsChk.gtArrLen, addFlags, deepVarNum, deepVarVal), tree->gtBoundsChk.gtThrowKind); break; @@ -9000,9 +9054,9 @@ GenTreePtr GenTree::GetChild(unsigned childNum) switch (childNum) { case 0: - return AsBoundsChk()->gtArrLen; - case 1: return AsBoundsChk()->gtIndex; + case 1: + return AsBoundsChk()->gtArrLen; default: unreached(); } @@ -9176,9 +9230,9 @@ GenTree** GenTreeUseEdgeIterator::GetNextUseEdge() const switch (m_state) { case 0: - return &m_node->AsBoundsChk()->gtArrLen; - case 1: return &m_node->AsBoundsChk()->gtIndex; + case 1: + return &m_node->AsBoundsChk()->gtArrLen; default: return nullptr; } @@ -10208,6 +10262,10 @@ void Compiler::gtDispNode(GenTreePtr tree, IndentStack* indentStack, __in __in_z case GT_LE: case GT_GE: case GT_GT: +#ifndef LEGACY_BACKEND + case GT_TEST_EQ: + case GT_TEST_NE: +#endif if (tree->gtFlags & GTF_RELOP_NAN_UN) { printf("N"); @@ -10226,12 +10284,6 @@ void Compiler::gtDispNode(GenTreePtr tree, IndentStack* indentStack, __in __in_z --msgLength; break; } - if (tree->gtFlags & GTF_RELOP_SMALL) - { - printf("S"); - --msgLength; - break; - } goto DASH; default: @@ -10694,7 +10746,17 @@ void Compiler::gtDispConst(GenTree* tree) case GT_CNS_INT: if (tree->IsIconHandle(GTF_ICON_STR_HDL)) { - printf(" 0x%X \"%S\"", dspPtr(tree->gtIntCon.gtIconVal), eeGetCPString(tree->gtIntCon.gtIconVal)); + const wchar_t* str = eeGetCPString(tree->gtIntCon.gtIconVal); + if (str != nullptr) + { + printf(" 0x%X \"%S\"", dspPtr(tree->gtIntCon.gtIconVal), str); + } + else + { + // Note that eGetCPString isn't currently implemented on Linux/ARM + // and instead always returns nullptr + printf(" 0x%X [ICON_STR_HDL]", dspPtr(tree->gtIntCon.gtIconVal)); + } } else { @@ -11255,7 +11317,7 @@ void Compiler::gtDispTree(GenTreePtr tree, { if (!topOnly) { - if (tree->gtGetOp2()) + if (tree->gtGetOp2IfPresent()) { // Label the childMsgs of the GT_COLON operator // op2 is the then part @@ -11670,8 +11732,8 @@ void Compiler::gtDispTree(GenTreePtr tree, printf("\n"); if (!topOnly) { - gtDispChild(tree->gtBoundsChk.gtArrLen, indentStack, IIArc, nullptr, topOnly); - gtDispChild(tree->gtBoundsChk.gtIndex, indentStack, IIArcBottom, nullptr, topOnly); + gtDispChild(tree->gtBoundsChk.gtIndex, indentStack, IIArc, nullptr, topOnly); + gtDispChild(tree->gtBoundsChk.gtArrLen, indentStack, IIArcBottom, nullptr, topOnly); } break; @@ -11955,6 +12017,10 @@ void Compiler::gtDispLIRNode(GenTree* node) // 49 spaces for alignment printf("%-49s", ""); +#ifdef FEATURE_SET_FLAGS + // additional flag enlarges the flag field by one character + printf(" "); +#endif indentStack.Push(operandArc); indentStack.print(); @@ -12615,7 +12681,7 @@ GenTreePtr Compiler::gtFoldExprConst(GenTreePtr tree) assert(kind & (GTK_UNOP | GTK_BINOP)); GenTreePtr op1 = tree->gtOp.gtOp1; - GenTreePtr op2 = tree->gtGetOp2(); + GenTreePtr op2 = tree->gtGetOp2IfPresent(); if (!opts.OptEnabled(CLFLG_CONSTANTFOLD)) { @@ -14411,12 +14477,14 @@ GenTreePtr Compiler::gtBuildCommaList(GenTreePtr list, GenTreePtr expr) result->gtFlags |= (list->gtFlags & GTF_ALL_EFFECT); result->gtFlags |= (expr->gtFlags & GTF_ALL_EFFECT); - // 'list' and 'expr' should have valuenumbers defined for both or for neither one - noway_assert(list->gtVNPair.BothDefined() == expr->gtVNPair.BothDefined()); + // 'list' and 'expr' should have valuenumbers defined for both or for neither one (unless we are remorphing, + // in which case a prior transform involving either node may have discarded or otherwise invalidated the value + // numbers). + assert((list->gtVNPair.BothDefined() == expr->gtVNPair.BothDefined()) || !fgGlobalMorph); // Set the ValueNumber 'gtVNPair' for the new GT_COMMA node // - if (expr->gtVNPair.BothDefined()) + if (list->gtVNPair.BothDefined() && expr->gtVNPair.BothDefined()) { // The result of a GT_COMMA node is op2, the normal value number is op2vnp // But we also need to include the union of side effects from op1 and op2. @@ -14505,7 +14573,7 @@ void Compiler::gtExtractSideEffList(GenTreePtr expr, if (kind & GTK_SMPOP) { GenTreePtr op1 = expr->gtOp.gtOp1; - GenTreePtr op2 = expr->gtGetOp2(); + GenTreePtr op2 = expr->gtGetOp2IfPresent(); if (flags & GTF_EXCEPT) { @@ -14589,8 +14657,8 @@ void Compiler::gtExtractSideEffList(GenTreePtr expr, #endif // FEATURE_SIMD ) { - gtExtractSideEffList(expr->AsBoundsChk()->gtArrLen, pList, flags); gtExtractSideEffList(expr->AsBoundsChk()->gtIndex, pList, flags); + gtExtractSideEffList(expr->AsBoundsChk()->gtArrLen, pList, flags); } if (expr->OperGet() == GT_DYN_BLK || expr->OperGet() == GT_STORE_DYN_BLK) @@ -15046,7 +15114,6 @@ BasicBlock* Compiler::bbNewBasicBlock(BBjumpKinds jumpKind) { VarSetOps::AssignNoCopy(this, block->bbVarUse, VarSetOps::MakeEmpty(this)); VarSetOps::AssignNoCopy(this, block->bbVarDef, VarSetOps::MakeEmpty(this)); - VarSetOps::AssignNoCopy(this, block->bbVarTmp, VarSetOps::MakeEmpty(this)); VarSetOps::AssignNoCopy(this, block->bbLiveIn, VarSetOps::MakeEmpty(this)); VarSetOps::AssignNoCopy(this, block->bbLiveOut, VarSetOps::MakeEmpty(this)); VarSetOps::AssignNoCopy(this, block->bbScope, VarSetOps::MakeEmpty(this)); @@ -15055,20 +15122,22 @@ BasicBlock* Compiler::bbNewBasicBlock(BBjumpKinds jumpKind) { VarSetOps::AssignNoCopy(this, block->bbVarUse, VarSetOps::UninitVal()); VarSetOps::AssignNoCopy(this, block->bbVarDef, VarSetOps::UninitVal()); - VarSetOps::AssignNoCopy(this, block->bbVarTmp, VarSetOps::UninitVal()); VarSetOps::AssignNoCopy(this, block->bbLiveIn, VarSetOps::UninitVal()); VarSetOps::AssignNoCopy(this, block->bbLiveOut, VarSetOps::UninitVal()); VarSetOps::AssignNoCopy(this, block->bbScope, VarSetOps::UninitVal()); } - block->bbHeapUse = false; - block->bbHeapDef = false; - block->bbHeapLiveIn = false; - block->bbHeapLiveOut = false; + block->bbMemoryUse = emptyMemoryKindSet; + block->bbMemoryDef = emptyMemoryKindSet; + block->bbMemoryLiveIn = emptyMemoryKindSet; + block->bbMemoryLiveOut = emptyMemoryKindSet; - block->bbHeapSsaPhiFunc = nullptr; - block->bbHeapSsaNumIn = 0; - block->bbHeapSsaNumOut = 0; + for (MemoryKind memoryKind : allMemoryKinds()) + { + block->bbMemorySsaPhiFunc[memoryKind] = nullptr; + block->bbMemorySsaNumIn[memoryKind] = 0; + block->bbMemorySsaNumOut[memoryKind] = 0; + } // Make sure we reserve a NOT_IN_LOOP value that isn't a legal table index. static_assert_no_msg(MAX_LOOP_NUM < BasicBlock::NOT_IN_LOOP); @@ -15717,18 +15786,21 @@ unsigned GenTree::IsLclVarUpdateTree(GenTree** pOtherTree, genTreeOps* pOper) return lclNum; } -// return true if this tree node is a subcomponent of parent for codegen purposes -// (essentially, will be rolled into the same instruction) -// Note that this method relies upon the value of gtRegNum field to determine -// if the treenode is contained or not. Therefore you can not call this method -// until after the LSRA phase has allocated physical registers to the treenodes. +//------------------------------------------------------------------------ +// isContained: check whether this tree node is a subcomponent of its parent for codegen purposes +// +// Return Value: +// Returns true if there is no code generated explicitly for this node. +// Essentially, it will be rolled into the code generation for the parent. +// +// Assumptions: +// This method relies upon the value of gtRegNum field to determine whether the tree node +// is contained. +// Therefore you can not call this method until after the LSRA phase has allocated physical +// registers to the treenodes. +// bool GenTree::isContained() const { - if (isContainedSpillTemp()) - { - return true; - } - if (gtHasReg()) { return false; @@ -15747,7 +15819,6 @@ bool GenTree::isContained() const return false; } - // TODO-Cleanup : this is not clean, would be nice to have some way of marking this. switch (OperGet()) { case GT_STOREIND: @@ -16253,8 +16324,15 @@ CORINFO_CLASS_HANDLE Compiler::gtGetStructHandleIfPresent(GenTree* tree) case GT_ASG: structHnd = gtGetStructHandleIfPresent(tree->gtGetOp1()); break; - case GT_LCL_VAR: case GT_LCL_FLD: +#ifdef FEATURE_SIMD + if (varTypeIsSIMD(tree)) + { + structHnd = gtGetStructHandleForSIMD(tree->gtType, TYP_FLOAT); + } +#endif + break; + case GT_LCL_VAR: structHnd = lvaTable[tree->AsLclVarCommon()->gtLclNum].lvVerTypeInfo.GetClassHandle(); break; case GT_RETURN: @@ -16792,15 +16870,8 @@ bool FieldSeqNode::IsPseudoField() GenTreeSIMD* Compiler::gtNewSIMDNode( var_types type, GenTreePtr op1, SIMDIntrinsicID simdIntrinsicID, var_types baseType, unsigned size) { - // TODO-CQ: An operand may be a GT_OBJ(GT_ADDR(GT_LCL_VAR))), in which case it should be - // marked lvUsedInSIMDIntrinsic. assert(op1 != nullptr); - if (op1->OperGet() == GT_LCL_VAR) - { - unsigned lclNum = op1->AsLclVarCommon()->GetLclNum(); - LclVarDsc* lclVarDsc = &lvaTable[lclNum]; - lclVarDsc->lvUsedInSIMDIntrinsic = true; - } + SetOpLclRelatedToSIMDIntrinsic(op1); return new (this, GT_SIMD) GenTreeSIMD(type, op1, simdIntrinsicID, baseType, size); } @@ -16808,24 +16879,34 @@ GenTreeSIMD* Compiler::gtNewSIMDNode( GenTreeSIMD* Compiler::gtNewSIMDNode( var_types type, GenTreePtr op1, GenTreePtr op2, SIMDIntrinsicID simdIntrinsicID, var_types baseType, unsigned size) { - // TODO-CQ: An operand may be a GT_OBJ(GT_ADDR(GT_LCL_VAR))), in which case it should be - // marked lvUsedInSIMDIntrinsic. assert(op1 != nullptr); - if (op1->OperIsLocal()) + SetOpLclRelatedToSIMDIntrinsic(op1); + if (op2 != nullptr) { - unsigned lclNum = op1->AsLclVarCommon()->GetLclNum(); - LclVarDsc* lclVarDsc = &lvaTable[lclNum]; - lclVarDsc->lvUsedInSIMDIntrinsic = true; + SetOpLclRelatedToSIMDIntrinsic(op2); } - if (op2 != nullptr && op2->OperIsLocal()) + return new (this, GT_SIMD) GenTreeSIMD(type, op1, op2, simdIntrinsicID, baseType, size); +} + +//------------------------------------------------------------------- +// SetOpLclRelatedToSIMDIntrinsic: Determine if the tree has a local var that needs to be set +// as used by a SIMD intrinsic, and if so, set that local var appropriately. +// +// Arguments: +// op - The tree, to be an operand of a new GT_SIMD node, to check. +// +void Compiler::SetOpLclRelatedToSIMDIntrinsic(GenTreePtr op) +{ + if (op->OperIsLocal()) { - unsigned lclNum = op2->AsLclVarCommon()->GetLclNum(); - LclVarDsc* lclVarDsc = &lvaTable[lclNum]; - lclVarDsc->lvUsedInSIMDIntrinsic = true; + setLclRelatedToSIMDIntrinsic(op); + } + else if ((op->OperGet() == GT_OBJ) && (op->gtOp.gtOp1->OperGet() == GT_ADDR) && + op->gtOp.gtOp1->gtOp.gtOp1->OperIsLocal()) + { + setLclRelatedToSIMDIntrinsic(op->gtOp.gtOp1->gtOp.gtOp1); } - - return new (this, GT_SIMD) GenTreeSIMD(type, op1, op2, simdIntrinsicID, baseType, size); } bool GenTree::isCommutativeSIMDIntrinsic() |