From 51b51bffbb4733a50c93a39f047b29ff424494d9 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Tue, 27 Feb 2024 11:31:21 +0100 Subject: [PATCH] Remove GT_STORE_DYN_BLK (#98905) --- .../design/coreclr/jit/first-class-structs.md | 4 - src/coreclr/jit/assertionprop.cpp | 1 - src/coreclr/jit/codegenarmarch.cpp | 5 +- src/coreclr/jit/codegencommon.cpp | 2 +- src/coreclr/jit/codegenlinear.cpp | 21 +- src/coreclr/jit/codegenloongarch64.cpp | 5 +- src/coreclr/jit/codegenriscv64.cpp | 5 +- src/coreclr/jit/codegenxarch.cpp | 3 +- src/coreclr/jit/compiler.cpp | 1 - src/coreclr/jit/compiler.h | 26 --- src/coreclr/jit/compiler.hpp | 15 -- src/coreclr/jit/gentree.cpp | 198 +----------------- src/coreclr/jit/gentree.h | 56 +---- src/coreclr/jit/gtlist.h | 1 - src/coreclr/jit/gtstructs.h | 5 +- src/coreclr/jit/importer.cpp | 17 -- src/coreclr/jit/liveness.cpp | 2 - src/coreclr/jit/lower.cpp | 28 +-- src/coreclr/jit/lowerarmarch.cpp | 7 +- src/coreclr/jit/lowerloongarch64.cpp | 7 +- src/coreclr/jit/lowerriscv64.cpp | 6 +- src/coreclr/jit/lowerxarch.cpp | 6 +- src/coreclr/jit/lsraarm.cpp | 1 - src/coreclr/jit/lsraarm64.cpp | 1 - src/coreclr/jit/lsraarmarch.cpp | 8 +- src/coreclr/jit/lsrabuild.cpp | 1 - src/coreclr/jit/lsraloongarch64.cpp | 9 +- src/coreclr/jit/lsrariscv64.cpp | 9 +- src/coreclr/jit/lsraxarch.cpp | 9 +- src/coreclr/jit/morph.cpp | 10 +- src/coreclr/jit/morphblock.cpp | 67 ------ src/coreclr/jit/optimizer.cpp | 1 - src/coreclr/jit/sideeffects.cpp | 2 +- src/coreclr/jit/simd.cpp | 2 - src/coreclr/jit/valuenum.cpp | 35 +--- src/coreclr/vm/callcounting.cpp | 2 +- .../src/System/SpanHelpers.ByteMemOps.cs | 1 - .../JIT/opt/Structs/MemsetMemcpyNullref.cs | 16 ++ src/tests/issues.targets | 10 - 39 files changed, 65 insertions(+), 540 deletions(-) diff --git a/docs/design/coreclr/jit/first-class-structs.md b/docs/design/coreclr/jit/first-class-structs.md index dc017aee75f2e..4211f75ff745f 100644 --- a/docs/design/coreclr/jit/first-class-structs.md +++ b/docs/design/coreclr/jit/first-class-structs.md @@ -94,10 +94,6 @@ encountered by most phases of the JIT: [#21705](https://github.com/dotnet/coreclr/pull/21705) they are no longer large nodes. * `GT_STORE_OBJ` and `GT_STORE_BLK` have the same structure as `GT_OBJ` and `GT_BLK`, respectively * `Data()` is op2 - * `GT_STORE_DYN_BLK` (GenTreeStoreDynBlk extends GenTreeBlk) - * Additional child `gtDynamicSize` - * Note that these aren't really struct stores; they represent dynamically sized blocks - of arbitrary data. * For `GT_LCL_FLD` nodes, we store a pointer to `ClassLayout` in the node. * For `GT_LCL_VAR` nodes, the `ClassLayout` is obtained from the `LclVarDsc`. diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index ba25a60af8edb..f191f37d048fc 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -5493,7 +5493,6 @@ GenTree* Compiler::optAssertionProp(ASSERT_VALARG_TP assertions, GenTree* tree, case GT_IND: case GT_STOREIND: case GT_NULLCHECK: - case GT_STORE_DYN_BLK: return optAssertionProp_Ind(assertions, tree, stmt); case GT_BOUNDS_CHECK: diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index 1e517e77c2e9b..1535ed68d9ee4 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -513,7 +513,6 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) #endif break; - case GT_STORE_DYN_BLK: case GT_STORE_BLK: genCodeForStoreBlk(treeNode->AsBlk()); break; @@ -4568,14 +4567,14 @@ void CodeGen::inst_JMP(emitJumpKind jmp, BasicBlock* tgtBlock) } //------------------------------------------------------------------------ -// genCodeForStoreBlk: Produce code for a GT_STORE_DYN_BLK/GT_STORE_BLK node. +// genCodeForStoreBlk: Produce code for a GT_STORE_BLK node. // // Arguments: // tree - the node // void CodeGen::genCodeForStoreBlk(GenTreeBlk* blkOp) { - assert(blkOp->OperIs(GT_STORE_DYN_BLK, GT_STORE_BLK)); + assert(blkOp->OperIs(GT_STORE_BLK)); bool isCopyBlk = blkOp->OperIsCopyBlkOp(); diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 244b218db34b8..9d7992ea4efe2 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -6546,7 +6546,7 @@ void CodeGen::genDefinePendingCallLabel(GenTreeCall* call) // For certain indirect calls we may introduce helper calls before that we need to skip: // - CFG may introduce a call to the validator first // - Generic virtual methods may compute the target dynamically through a separate helper call - // - memset/memcpy helper calls emitted for GT_STORE_DYN_BLK/GT_STORE_BLK + // - memset/memcpy helper calls emitted for GT_STORE_BLK if (call->IsHelperCall()) { switch (compiler->eeGetHelperNum(call->gtCallMethHnd)) diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index 913f3a47002a5..78df10811a4c2 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -1935,18 +1935,9 @@ void CodeGen::genSetBlockSize(GenTreeBlk* blkNode, regNumber sizeReg) { if (sizeReg != REG_NA) { - unsigned blockSize = blkNode->Size(); - if (!blkNode->OperIs(GT_STORE_DYN_BLK)) - { - assert((blkNode->gtRsvdRegs & genRegMask(sizeReg)) != 0); - // This can go via helper which takes the size as a native uint. - instGen_Set_Reg_To_Imm(EA_PTRSIZE, sizeReg, blockSize); - } - else - { - GenTree* sizeNode = blkNode->AsStoreDynBlk()->gtDynamicSize; - inst_Mov(sizeNode->TypeGet(), sizeReg, sizeNode->GetRegNum(), /* canSkip */ true); - } + assert((blkNode->gtRsvdRegs & genRegMask(sizeReg)) != 0); + // This can go via helper which takes the size as a native uint. + instGen_Set_Reg_To_Imm(EA_PTRSIZE, sizeReg, blkNode->Size()); } } @@ -2052,12 +2043,6 @@ void CodeGen::genConsumeBlockOp(GenTreeBlk* blkNode, regNumber dstReg, regNumber genConsumeReg(dstAddr); // The source may be a local or in a register; 'genConsumeBlockSrc' will check that. genConsumeBlockSrc(blkNode); - // 'genSetBlockSize' (called below) will ensure that a register has been reserved as needed - // in the case where the size is a constant (i.e. it is not GT_STORE_DYN_BLK). - if (blkNode->OperGet() == GT_STORE_DYN_BLK) - { - genConsumeReg(blkNode->AsStoreDynBlk()->gtDynamicSize); - } // Next, perform any necessary moves. genCopyRegIfNeeded(dstAddr, dstReg); diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index f287785951964..e894d98763331 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -5022,7 +5022,6 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) emit->emitIns_R_L(INS_ld_d, EA_PTRSIZE, genPendingCallLabel, targetReg); break; - case GT_STORE_DYN_BLK: case GT_STORE_BLK: genCodeForStoreBlk(treeNode->AsBlk()); break; @@ -7249,14 +7248,14 @@ void CodeGen::genCreateAndStoreGCInfo(unsigned codeSize, } //------------------------------------------------------------------------ -// genCodeForStoreBlk: Produce code for a GT_STORE_DYN_BLK/GT_STORE_BLK node. +// genCodeForStoreBlk: Produce code for a GT_STORE_BLK node. // // Arguments: // tree - the node // void CodeGen::genCodeForStoreBlk(GenTreeBlk* blkOp) { - assert(blkOp->OperIs(GT_STORE_DYN_BLK, GT_STORE_BLK)); + assert(blkOp->OperIs(GT_STORE_BLK)); if (blkOp->gtBlkOpGcUnsafe) { diff --git a/src/coreclr/jit/codegenriscv64.cpp b/src/coreclr/jit/codegenriscv64.cpp index 6dc76478246be..b34cd52d34afe 100644 --- a/src/coreclr/jit/codegenriscv64.cpp +++ b/src/coreclr/jit/codegenriscv64.cpp @@ -5102,7 +5102,6 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) emit->emitIns_R_L(INS_ld, EA_PTRSIZE, genPendingCallLabel, targetReg); break; - case GT_STORE_DYN_BLK: case GT_STORE_BLK: genCodeForStoreBlk(treeNode->AsBlk()); break; @@ -7246,14 +7245,14 @@ void CodeGen::genCreateAndStoreGCInfo(unsigned codeSize, } //------------------------------------------------------------------------ -// genCodeForStoreBlk: Produce code for a GT_STORE_DYN_BLK/GT_STORE_BLK node. +// genCodeForStoreBlk: Produce code for a GT_STORE_BLK node. // // Arguments: // tree - the node // void CodeGen::genCodeForStoreBlk(GenTreeBlk* blkOp) { - assert(blkOp->OperIs(GT_STORE_DYN_BLK, GT_STORE_BLK)); + assert(blkOp->OperIs(GT_STORE_BLK)); if (blkOp->gtBlkOpGcUnsafe) { diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 0cd02f2924309..0b984ea2ef208 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -2183,7 +2183,6 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) emit->emitIns_R_L(INS_lea, EA_PTR_DSP_RELOC, genPendingCallLabel, treeNode->GetRegNum()); break; - case GT_STORE_DYN_BLK: case GT_STORE_BLK: genCodeForStoreBlk(treeNode->AsBlk()); break; @@ -3057,7 +3056,7 @@ void CodeGen::genLclHeap(GenTree* tree) void CodeGen::genCodeForStoreBlk(GenTreeBlk* storeBlkNode) { - assert(storeBlkNode->OperIs(GT_STORE_DYN_BLK, GT_STORE_BLK)); + assert(storeBlkNode->OperIs(GT_STORE_BLK)); bool isCopyBlk = storeBlkNode->OperIsCopyBlkOp(); diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 9fded7a13ccb0..f5a65e2ab1d94 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -9920,7 +9920,6 @@ JITDBGAPI void __cdecl cTreeFlags(Compiler* comp, GenTree* tree) case GT_BLK: case GT_STORE_BLK: - case GT_STORE_DYN_BLK: if (tree->gtFlags & GTF_IND_VOLATILE) { diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 364f51c2b529b..f3ebaf3e57ef1 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -3364,9 +3364,6 @@ class Compiler GenTreeBlk* gtNewStoreBlkNode( ClassLayout* layout, GenTree* addr, GenTree* data, GenTreeFlags indirFlags = GTF_EMPTY); - GenTreeStoreDynBlk* gtNewStoreDynBlkNode( - GenTree* addr, GenTree* data, GenTree* dynamicSize, GenTreeFlags indirFlags = GTF_EMPTY); - GenTreeStoreInd* gtNewStoreIndNode( var_types type, GenTree* addr, GenTree* data, GenTreeFlags indirFlags = GTF_EMPTY); @@ -6463,7 +6460,6 @@ class Compiler public: GenTree* fgMorphInitBlock(GenTree* tree); GenTree* fgMorphCopyBlock(GenTree* tree); - GenTree* fgMorphStoreDynBlock(GenTreeStoreDynBlk* tree); private: GenTree* fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optAssertionPropDone = nullptr); void fgTryReplaceStructLocalWithField(GenTree* tree); @@ -11447,28 +11443,6 @@ class GenTreeVisitor break; } - case GT_STORE_DYN_BLK: - { - GenTreeStoreDynBlk* const dynBlock = node->AsStoreDynBlk(); - - result = WalkTree(&dynBlock->gtOp1, dynBlock); - if (result == fgWalkResult::WALK_ABORT) - { - return result; - } - result = WalkTree(&dynBlock->gtOp2, dynBlock); - if (result == fgWalkResult::WALK_ABORT) - { - return result; - } - result = WalkTree(&dynBlock->gtDynamicSize, dynBlock); - if (result == fgWalkResult::WALK_ABORT) - { - return result; - } - break; - } - case GT_CALL: { GenTreeCall* const call = node->AsCall(); diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index a8ef2c7086c9b..073a5cde7e2c3 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -4362,21 +4362,6 @@ void GenTree::VisitOperands(TVisitor visitor) return; } - case GT_STORE_DYN_BLK: - { - GenTreeStoreDynBlk* const dynBlock = this->AsStoreDynBlk(); - if (visitor(dynBlock->gtOp1) == VisitResult::Abort) - { - return; - } - if (visitor(dynBlock->gtOp2) == VisitResult::Abort) - { - return; - } - visitor(dynBlock->gtDynamicSize); - return; - } - case GT_CALL: { GenTreeCall* const call = this->AsCall(); diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index d19a857bca161..08ee377991256 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -252,7 +252,6 @@ void GenTree::InitNodeSize() GenTree::s_gtNodeSizes[GT_FIELD_ADDR] = 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_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 @@ -318,7 +317,6 @@ void GenTree::InitNodeSize() static_assert_no_msg(sizeof(GenTreeStoreInd) <= TREE_NODE_SZ_SMALL); static_assert_no_msg(sizeof(GenTreeAddrMode) <= TREE_NODE_SZ_SMALL); static_assert_no_msg(sizeof(GenTreeBlk) <= TREE_NODE_SZ_SMALL); - static_assert_no_msg(sizeof(GenTreeStoreDynBlk) <= TREE_NODE_SZ_LARGE); // *** large node static_assert_no_msg(sizeof(GenTreeRetExpr) <= TREE_NODE_SZ_LARGE); // *** large node static_assert_no_msg(sizeof(GenTreeILOffset) <= TREE_NODE_SZ_SMALL); static_assert_no_msg(sizeof(GenTreePhiArg) <= TREE_NODE_SZ_SMALL); @@ -3151,11 +3149,6 @@ bool GenTree::Compare(GenTree* op1, GenTree* op2, bool swapOK) Compare(op1->AsCmpXchg()->Data(), op2->AsCmpXchg()->Data()) && Compare(op1->AsCmpXchg()->Comparand(), op2->AsCmpXchg()->Comparand()); - case GT_STORE_DYN_BLK: - return Compare(op1->AsStoreDynBlk()->Addr(), op2->AsStoreDynBlk()->Addr()) && - Compare(op1->AsStoreDynBlk()->Data(), op2->AsStoreDynBlk()->Data()) && - Compare(op1->AsStoreDynBlk()->gtDynamicSize, op2->AsStoreDynBlk()->gtDynamicSize); - default: assert(!"unexpected operator"); } @@ -3704,12 +3697,6 @@ unsigned Compiler::gtHashValue(GenTree* tree) hash = genTreeHashAdd(hash, gtHashValue(tree->AsCmpXchg()->Comparand())); break; - case GT_STORE_DYN_BLK: - hash = genTreeHashAdd(hash, gtHashValue(tree->AsStoreDynBlk()->Data())); - hash = genTreeHashAdd(hash, gtHashValue(tree->AsStoreDynBlk()->Addr())); - hash = genTreeHashAdd(hash, gtHashValue(tree->AsStoreDynBlk()->gtDynamicSize)); - break; - default: #ifdef DEBUG gtDispTree(tree); @@ -4520,12 +4507,6 @@ bool Compiler::gtGetIndNodeCost(GenTreeIndir* node, int* pCostEx, int* pCostSz) { // See if we can form a complex addressing mode. bool doAddrMode = true; - - // TODO-1stClassStructs: delete once IND nodes are no more. - if (node->TypeGet() == TYP_STRUCT) - { - doAddrMode = false; - } #ifdef TARGET_ARM64 if (node->IsVolatile()) { @@ -6384,22 +6365,6 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) } break; - case GT_STORE_DYN_BLK: - level = gtSetEvalOrder(tree->AsStoreDynBlk()->Addr()); - costEx = tree->AsStoreDynBlk()->Addr()->GetCostEx(); - costSz = tree->AsStoreDynBlk()->Addr()->GetCostSz(); - - lvl2 = gtSetEvalOrder(tree->AsStoreDynBlk()->Data()); - level = max(level, lvl2); - costEx += tree->AsStoreDynBlk()->Data()->GetCostEx(); - costSz += tree->AsStoreDynBlk()->Data()->GetCostSz(); - - lvl2 = gtSetEvalOrder(tree->AsStoreDynBlk()->gtDynamicSize); - level = max(level, lvl2); - costEx += tree->AsStoreDynBlk()->gtDynamicSize->GetCostEx(); - costSz += tree->AsStoreDynBlk()->gtDynamicSize->GetCostSz(); - break; - case GT_SELECT: level = gtSetEvalOrder(tree->AsConditional()->gtCond); costEx = tree->AsConditional()->gtCond->GetCostEx(); @@ -6846,27 +6811,6 @@ bool GenTree::TryGetUse(GenTree* operand, GenTree*** pUse) return false; } - case GT_STORE_DYN_BLK: - { - GenTreeStoreDynBlk* const dynBlock = this->AsStoreDynBlk(); - if (operand == dynBlock->gtOp1) - { - *pUse = &dynBlock->gtOp1; - return true; - } - if (operand == dynBlock->gtOp2) - { - *pUse = &dynBlock->gtOp2; - return true; - } - if (operand == dynBlock->gtDynamicSize) - { - *pUse = &dynBlock->gtDynamicSize; - return true; - } - return false; - } - case GT_CALL: { GenTreeCall* const call = this->AsCall(); @@ -7026,7 +6970,6 @@ bool GenTree::OperRequiresAsgFlag() const case GT_STORE_LCL_FLD: case GT_STOREIND: case GT_STORE_BLK: - case GT_STORE_DYN_BLK: case GT_XADD: case GT_XORR: case GT_XAND: @@ -7139,7 +7082,6 @@ bool GenTree::OperIsImplicitIndir() const case GT_CMPXCHG: case GT_BLK: case GT_STORE_BLK: - case GT_STORE_DYN_BLK: case GT_BOX: case GT_ARR_ELEM: case GT_ARR_LENGTH: @@ -7236,7 +7178,6 @@ ExceptionSetFlags GenTree::OperExceptions(Compiler* comp) case GT_BLK: case GT_NULLCHECK: case GT_STORE_BLK: - case GT_STORE_DYN_BLK: case GT_ARR_LENGTH: case GT_MDARR_LENGTH: case GT_MDARR_LOWER_BOUND: @@ -7356,7 +7297,6 @@ bool GenTree::OperRequiresGlobRefFlag(Compiler* comp) const case GT_STOREIND: case GT_STORE_BLK: - case GT_STORE_DYN_BLK: case GT_XADD: case GT_XORR: case GT_XAND: @@ -7415,7 +7355,6 @@ bool GenTree::OperSupportsOrderingSideEffect() const case GT_STOREIND: case GT_NULLCHECK: case GT_STORE_BLK: - case GT_STORE_DYN_BLK: case GT_XADD: case GT_XORR: case GT_XAND: @@ -8750,34 +8689,6 @@ GenTreeBlk* Compiler::gtNewStoreBlkNode(ClassLayout* layout, GenTree* addr, GenT return store; } -//------------------------------------------------------------------------------ -// gtNewStoreDynBlkNode : Create a dynamic block store node. -// -// Arguments: -// addr - Destination address -// data - Value to store (init val or indirection representing a location) -// dynamicSize - Node that computes number of bytes to store -// indirFlags - Indirection flags -// -// Return Value: -// The created GT_STORE_DYN_BLK node. -// -GenTreeStoreDynBlk* Compiler::gtNewStoreDynBlkNode(GenTree* addr, - GenTree* data, - GenTree* dynamicSize, - GenTreeFlags indirFlags) -{ - assert((indirFlags & GTF_IND_INVARIANT) == 0); - assert(data->IsInitVal() || data->OperIs(GT_IND)); - - GenTreeStoreDynBlk* store = new (this, GT_STORE_DYN_BLK) GenTreeStoreDynBlk(addr, data, dynamicSize); - store->gtFlags |= GTF_ASG; - gtInitializeIndirNode(store, indirFlags); - gtInitializeStoreNode(store, data); - - return store; -} - //------------------------------------------------------------------------------ // gtNewStoreIndNode : Create an indirect store node. // @@ -9815,12 +9726,6 @@ GenTree* Compiler::gtCloneExpr(GenTree* tree) gtCloneExpr(tree->AsCmpXchg()->Data()), gtCloneExpr(tree->AsCmpXchg()->Comparand())); break; - case GT_STORE_DYN_BLK: - copy = new (this, oper) GenTreeStoreDynBlk(gtCloneExpr(tree->AsStoreDynBlk()->Addr()), - gtCloneExpr(tree->AsStoreDynBlk()->Data()), - gtCloneExpr(tree->AsStoreDynBlk()->gtDynamicSize)); - break; - case GT_SELECT: copy = new (this, oper) GenTreeConditional(oper, tree->TypeGet(), gtCloneExpr(tree->AsConditional()->gtCond), @@ -10433,12 +10338,6 @@ GenTreeUseEdgeIterator::GenTreeUseEdgeIterator(GenTree* node) m_advance = &GenTreeUseEdgeIterator::AdvanceArrElem; return; - case GT_STORE_DYN_BLK: - m_edge = &m_node->AsStoreDynBlk()->Addr(); - assert(*m_edge != nullptr); - m_advance = &GenTreeUseEdgeIterator::AdvanceStoreDynBlk; - return; - case GT_CALL: m_statePtr = m_node->AsCall()->gtArgs.Args().begin().GetArg(); m_advance = &GenTreeUseEdgeIterator::AdvanceCall; @@ -10504,29 +10403,6 @@ void GenTreeUseEdgeIterator::AdvanceArrElem() } } -//------------------------------------------------------------------------ -// GenTreeUseEdgeIterator::AdvanceStoreDynBlk: produces the next operand of a StoreDynBlk node and advances the state. -// -void GenTreeUseEdgeIterator::AdvanceStoreDynBlk() -{ - GenTreeStoreDynBlk* const dynBlock = m_node->AsStoreDynBlk(); - switch (m_state) - { - case 0: - m_edge = &dynBlock->Data(); - m_state = 1; - break; - case 1: - m_edge = &dynBlock->gtDynamicSize; - m_advance = &GenTreeUseEdgeIterator::Terminate; - break; - default: - unreached(); - } - - assert(*m_edge != nullptr); -} - //------------------------------------------------------------------------ // GenTreeUseEdgeIterator::AdvanceFieldList: produces the next operand of a FieldList node and advances the state. // @@ -10882,7 +10758,7 @@ bool GenTree::Precedes(GenTree* other) // void GenTree::SetIndirExceptionFlags(Compiler* comp) { - assert(OperIsIndirOrArrMetaData() && (OperIsSimple() || OperIs(GT_CMPXCHG, GT_STORE_DYN_BLK))); + assert(OperIsIndirOrArrMetaData() && (OperIsSimple() || OperIs(GT_CMPXCHG))); if (IndirMayFault(comp)) { @@ -10904,11 +10780,6 @@ void GenTree::SetIndirExceptionFlags(Compiler* comp) gtFlags |= AsCmpXchg()->Data()->gtFlags & GTF_EXCEPT; gtFlags |= AsCmpXchg()->Comparand()->gtFlags & GTF_EXCEPT; } - else if (OperIs(GT_STORE_DYN_BLK)) - { - gtFlags |= AsStoreDynBlk()->Data()->gtFlags & GTF_EXCEPT; - gtFlags |= AsStoreDynBlk()->gtDynamicSize->gtFlags & GTF_EXCEPT; - } } #ifdef DEBUG @@ -11331,7 +11202,6 @@ void Compiler::gtDispNode(GenTree* tree, IndentStack* indentStack, _In_ _In_opt_ case GT_IND: case GT_STOREIND: case GT_STORE_BLK: - case GT_STORE_DYN_BLK: // We prefer printing V or U if ((tree->gtFlags & (GTF_IND_VOLATILE | GTF_IND_UNALIGNED)) == 0) { @@ -13159,28 +13029,6 @@ void Compiler::gtDispTree(GenTree* tree, } break; - case GT_STORE_DYN_BLK: - if (tree->OperIsCopyBlkOp()) - { - printf(" (copy)"); - } - else if (tree->OperIsInitBlkOp()) - { - printf(" (init)"); - } - gtDispCommonEndLine(tree); - - if (!topOnly) - { - gtDispChild(tree->AsStoreDynBlk()->Addr(), indentStack, IIArc, nullptr, topOnly); - if (tree->AsStoreDynBlk()->Data() != nullptr) - { - gtDispChild(tree->AsStoreDynBlk()->Data(), indentStack, IIArc, nullptr, topOnly); - } - gtDispChild(tree->AsStoreDynBlk()->gtDynamicSize, indentStack, IIArcBottom, nullptr, topOnly); - } - break; - case GT_SELECT: gtDispCommonEndLine(tree); @@ -13612,22 +13460,6 @@ void Compiler::gtDispLIRNode(GenTree* node, const char* prefixMsg /* = nullptr * displayOperand(operand, buf, operandArc, indentStack, prefixIndent); } } - else if (node->OperIs(GT_STORE_DYN_BLK)) - { - if (operand == node->AsBlk()->Addr()) - { - displayOperand(operand, "lhs", operandArc, indentStack, prefixIndent); - } - else if (operand == node->AsBlk()->Data()) - { - displayOperand(operand, "rhs", operandArc, indentStack, prefixIndent); - } - else - { - assert(operand == node->AsStoreDynBlk()->gtDynamicSize); - displayOperand(operand, "size", operandArc, indentStack, prefixIndent); - } - } else { displayOperand(operand, "", operandArc, indentStack, prefixIndent); @@ -16984,22 +16816,6 @@ bool Compiler::gtSplitTree( } private: - bool IsLocation(const UseInfo& useInf) - { - if (useInf.User == nullptr) - { - return false; - } - - if (useInf.User->OperIs(GT_STORE_DYN_BLK) && !(*useInf.Use)->OperIs(GT_CNS_INT, GT_INIT_VAL) && - (useInf.Use == &useInf.User->AsStoreDynBlk()->Data())) - { - return true; - } - - return false; - } - bool IsReturned(const UseInfo& useInf, bool userIsReturned) { if (useInf.User != nullptr) @@ -17093,18 +16909,6 @@ bool Compiler::gtSplitTree( return; } - if (IsLocation(useInf)) - { - // Only a handful of nodes can be location, and they are all unary or nullary. - assert((*use)->OperIs(GT_IND, GT_BLK, GT_LCL_VAR, GT_LCL_FLD)); - if ((*use)->OperIsUnary()) - { - SplitOutUse(UseInfo{&(*use)->AsUnOp()->gtOp1, user}, false); - } - - return; - } - #ifndef TARGET_64BIT // GT_MUL with GTF_MUL_64RSLT is required to stay with casts on the // operands. Note that one operand may also be a constant, but we diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index b648ba167dad7..adab37fc0835c 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -1216,7 +1216,7 @@ struct GenTree static bool OperIsStoreBlk(genTreeOps gtOper) { - return StaticOperIs(gtOper, GT_STORE_BLK, GT_STORE_DYN_BLK); + return StaticOperIs(gtOper, GT_STORE_BLK); } bool OperIsStoreBlk() const @@ -1545,7 +1545,7 @@ struct GenTree static bool OperIsIndir(genTreeOps gtOper) { static_assert_no_msg(AreContiguous(GT_LOCKADD, GT_XAND, GT_XORR, GT_XADD, GT_XCHG, GT_CMPXCHG, GT_IND, - GT_STOREIND, GT_BLK, GT_STORE_BLK, GT_STORE_DYN_BLK, GT_NULLCHECK)); + GT_STOREIND, GT_BLK, GT_STORE_BLK, GT_NULLCHECK)); return (GT_LOCKADD <= gtOper) && (gtOper <= GT_NULLCHECK); } @@ -2862,7 +2862,6 @@ class GenTreeUseEdgeIterator final // Advance functions for special nodes void AdvanceCmpXchg(); void AdvanceArrElem(); - void AdvanceStoreDynBlk(); void AdvanceFieldList(); void AdvancePhi(); void AdvanceConditional(); @@ -7358,15 +7357,10 @@ struct GenTreeBlk : public GenTreeIndir public: ClassLayout* GetLayout() const { + assert(m_layout != nullptr); return m_layout; } - void SetLayout(ClassLayout* layout) - { - assert((layout != nullptr) || OperIs(GT_STORE_DYN_BLK)); - m_layout = layout; - } - // The data to be stored (null for GT_BLK) GenTree*& Data() { @@ -7380,8 +7374,7 @@ struct GenTreeBlk : public GenTreeIndir // The size of the buffer to be copied. unsigned Size() const { - assert((m_layout != nullptr) || OperIs(GT_STORE_DYN_BLK)); - return (m_layout != nullptr) ? m_layout->GetSize() : 0; + return m_layout->GetSize(); } // Instruction selection: during codegen time, what code sequence we will be using @@ -7407,7 +7400,7 @@ struct GenTreeBlk : public GenTreeIndir bool ContainsReferences() { - return (m_layout != nullptr) && m_layout->HasGCPtr(); + return m_layout->HasGCPtr(); } bool IsOnHeapAndContainsReferences() @@ -7438,8 +7431,8 @@ struct GenTreeBlk : public GenTreeIndir void Initialize(ClassLayout* layout) { - assert(OperIsBlk(OperGet()) && ((layout != nullptr) || OperIs(GT_STORE_DYN_BLK))); - assert((layout == nullptr) || (layout->GetSize() != 0)); + assert(layout != nullptr); + assert(layout->GetSize() != 0); m_layout = layout; gtBlkOpKind = BlkOpKindInvalid; @@ -7457,35 +7450,6 @@ struct GenTreeBlk : public GenTreeIndir #endif // DEBUGGABLE_GENTREE }; -// GenTreeStoreDynBlk -- 'dynamic block store' (GT_STORE_DYN_BLK). -// -// This node is used to represent stores that have a dynamic size - the "cpblk" and "initblk" -// IL instructions are implemented with it. Note that such stores assume the input has no GC -// pointers in it, and as such do not ever use write barriers. -// -// The "Data()" member of this node will either be a "dummy" IND(struct) node, for "cpblk", or -// the zero constant/INIT_VAL for "initblk". -// -struct GenTreeStoreDynBlk : public GenTreeBlk -{ -public: - GenTree* gtDynamicSize; - - GenTreeStoreDynBlk(GenTree* dstAddr, GenTree* data, GenTree* dynamicSize) - : GenTreeBlk(GT_STORE_DYN_BLK, TYP_VOID, dstAddr, data, nullptr), gtDynamicSize(dynamicSize) - { - gtFlags |= dynamicSize->gtFlags & GTF_ALL_EFFECT; - } - -#if DEBUGGABLE_GENTREE -protected: - friend GenTree; - GenTreeStoreDynBlk() : GenTreeBlk() - { - } -#endif // DEBUGGABLE_GENTREE -}; - // Read-modify-write status of a RMW memory op rooted at a storeInd enum RMWStatus { @@ -8900,10 +8864,6 @@ struct GenTreeCCMP final : public GenTreeOpCC inline bool GenTree::OperIsBlkOp() { - if (OperIs(GT_STORE_DYN_BLK)) - { - return true; - } if (OperIsStore()) { return varTypeIsStruct(this); @@ -9311,7 +9271,7 @@ inline GenTree* GenTree::gtGetOp2IfPresent() const inline GenTree*& GenTree::Data() { - assert(OperIsStore() || OperIs(GT_STORE_DYN_BLK)); + assert(OperIsStore()); return OperIsLocalStore() ? AsLclVarCommon()->Data() : AsIndir()->Data(); } diff --git a/src/coreclr/jit/gtlist.h b/src/coreclr/jit/gtlist.h index 2d9208403b363..26513f0f3441b 100644 --- a/src/coreclr/jit/gtlist.h +++ b/src/coreclr/jit/gtlist.h @@ -83,7 +83,6 @@ GTNODE(IND , GenTreeIndir ,0,1,GTK_UNOP) GTNODE(STOREIND , GenTreeStoreInd ,0,1,GTK_BINOP|GTK_EXOP|GTK_NOVALUE|GTK_STORE) // Store indirection GTNODE(BLK , GenTreeBlk ,0,1,GTK_UNOP|GTK_EXOP) // Struct load GTNODE(STORE_BLK , GenTreeBlk ,0,1,GTK_BINOP|GTK_EXOP|GTK_NOVALUE|GTK_STORE) // Struct store -GTNODE(STORE_DYN_BLK , GenTreeStoreDynBlk ,0,1,GTK_SPECIAL|GTK_NOVALUE) // Dynamically sized block store, with native uint size GTNODE(NULLCHECK , GenTreeIndir ,0,1,GTK_UNOP|GTK_NOVALUE) // Null checks the source GTNODE(ARR_LENGTH , GenTreeArrLen ,0,0,GTK_UNOP|GTK_EXOP) // single-dimension (SZ) array length diff --git a/src/coreclr/jit/gtstructs.h b/src/coreclr/jit/gtstructs.h index 989b6e554eae7..e6823478a3c9a 100644 --- a/src/coreclr/jit/gtstructs.h +++ b/src/coreclr/jit/gtstructs.h @@ -88,9 +88,8 @@ GTSTRUCT_1(AddrMode , GT_LEA) GTSTRUCT_1(Qmark , GT_QMARK) GTSTRUCT_1(PhiArg , GT_PHI_ARG) GTSTRUCT_1(Phi , GT_PHI) -GTSTRUCT_N(Indir , GT_IND, GT_NULLCHECK, GT_BLK, GT_STORE_BLK, GT_STORE_DYN_BLK, GT_LOCKADD, GT_XAND, GT_XORR, GT_XADD, GT_XCHG, GT_CMPXCHG, GT_STOREIND) -GTSTRUCT_N(Blk , GT_BLK, GT_STORE_BLK, GT_STORE_DYN_BLK) -GTSTRUCT_1(StoreDynBlk , GT_STORE_DYN_BLK) +GTSTRUCT_N(Indir , GT_IND, GT_NULLCHECK, GT_BLK, GT_STORE_BLK, GT_LOCKADD, GT_XAND, GT_XORR, GT_XADD, GT_XCHG, GT_CMPXCHG, GT_STOREIND) +GTSTRUCT_N(Blk , GT_BLK, GT_STORE_BLK) GTSTRUCT_1(StoreInd , GT_STOREIND) GTSTRUCT_1(CmpXchg , GT_CMPXCHG) #ifdef TARGET_ARM64 diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 22bc4a2ba7337..be84141270654 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -10184,9 +10184,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) op3 = gtNewCastNode(TYP_LONG, op3, /* fromUnsigned */ true, TYP_LONG); } -// TODO: enable for X86 as well, it currently doesn't support memset/memcpy helpers -// Then, get rid of GT_STORE_DYN_BLK entirely. -#ifndef TARGET_X86 GenTreeCall* call; if (opcode == CEE_INITBLK) { @@ -10216,20 +10213,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) { op1 = call; } -#else - if (opcode == CEE_INITBLK) - { - if (!op2->IsIntegralConst(0)) - { - op2 = gtNewOperNode(GT_INIT_VAL, TYP_INT, op2); - } - } - else - { - op2 = gtNewIndir(TYP_STRUCT, op2); - } - op1 = gtNewStoreDynBlkNode(op1, op2, op3, indirFlags); -#endif } goto SPILL_APPEND; } diff --git a/src/coreclr/jit/liveness.cpp b/src/coreclr/jit/liveness.cpp index c4a4d44489f0d..78fb96fe3d77d 100644 --- a/src/coreclr/jit/liveness.cpp +++ b/src/coreclr/jit/liveness.cpp @@ -245,7 +245,6 @@ void Compiler::fgPerNodeLocalVarLiveness(GenTree* tree) case GT_STOREIND: case GT_STORE_BLK: - case GT_STORE_DYN_BLK: case GT_MEMORYBARRIER: // Similar to Volatile indirections, we must handle this as a memory def. fgCurMemoryDef |= memoryKindSet(GcHeap, ByrefExposed); break; @@ -1937,7 +1936,6 @@ void Compiler::fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALAR case GT_STOREIND: case GT_BOUNDS_CHECK: case GT_STORE_BLK: - case GT_STORE_DYN_BLK: case GT_JCMP: case GT_JTEST: case GT_JCC: diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 18008d7ed77e9..5d981ba577422 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -570,8 +570,6 @@ GenTree* Lowering::LowerNode(GenTree* node) LowerStoreSingleRegCallStruct(node->AsBlk()); break; } - FALLTHROUGH; - case GT_STORE_DYN_BLK: LowerBlockStoreCommon(node->AsBlk()); break; @@ -8128,17 +8126,9 @@ void Lowering::LowerBlockStoreAsHelperCall(GenTreeBlk* blkNode) } } - if (blkNode->OperIs(GT_STORE_DYN_BLK)) - { - // Size is not a constant - size = blkNode->AsStoreDynBlk()->gtDynamicSize; - } - else - { - // Size is a constant - size = comp->gtNewIconNode(blkNode->Size(), TYP_I_IMPL); - BlockRange().InsertBefore(data, size); - } + // Size is a constant + size = comp->gtNewIconNode(blkNode->Size(), TYP_I_IMPL); + BlockRange().InsertBefore(data, size); // A hacky way to safely call fgMorphTree in Lower GenTree* destPlaceholder = comp->gtNewZeroConNode(dest->TypeGet()); @@ -9227,13 +9217,10 @@ void Lowering::LowerLclHeap(GenTree* node) // void Lowering::LowerBlockStoreCommon(GenTreeBlk* blkNode) { - assert(blkNode->OperIs(GT_STORE_BLK, GT_STORE_DYN_BLK)); + assert(blkNode->OperIs(GT_STORE_BLK)); if (blkNode->ContainsReferences() && !blkNode->OperIsCopyBlkOp()) { - // Make sure we don't use GT_STORE_DYN_BLK - assert(blkNode->OperIs(GT_STORE_BLK)); - // and we only zero it (and that zero is better to be not hoisted/CSE'd) assert(blkNode->Data()->IsIntegralConst(0)); } @@ -9269,17 +9256,12 @@ void Lowering::LowerBlockStoreCommon(GenTreeBlk* blkNode) // bool Lowering::TryTransformStoreObjAsStoreInd(GenTreeBlk* blkNode) { - assert(blkNode->OperIs(GT_STORE_BLK, GT_STORE_DYN_BLK)); + assert(blkNode->OperIs(GT_STORE_BLK)); if (!comp->opts.OptimizationEnabled()) { return false; } - if (blkNode->OperIs(GT_STORE_DYN_BLK)) - { - return false; - } - var_types regType = blkNode->GetLayout()->GetRegisterType(); if (regType == TYP_UNDEF) { diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 4cc7144ad15d3..df987c1aeab55 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -585,8 +585,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) src = src->AsUnOp()->gtGetOp1(); } - if (!blkNode->OperIs(GT_STORE_DYN_BLK) && (size <= comp->getUnrollThreshold(Compiler::UnrollKind::Memset)) && - src->OperIs(GT_CNS_INT)) + if ((size <= comp->getUnrollThreshold(Compiler::UnrollKind::Memset)) && src->OperIs(GT_CNS_INT)) { blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindUnroll; @@ -651,7 +650,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) } ClassLayout* layout = blkNode->GetLayout(); - bool doCpObj = !blkNode->OperIs(GT_STORE_DYN_BLK) && layout->HasGCPtr(); + bool doCpObj = layout->HasGCPtr(); unsigned copyBlockUnrollLimit = comp->getUnrollThreshold(Compiler::UnrollKind::Memcpy); if (doCpObj && (size <= copyBlockUnrollLimit)) @@ -686,7 +685,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) } else { - assert(blkNode->OperIs(GT_STORE_BLK, GT_STORE_DYN_BLK)); + assert(blkNode->OperIs(GT_STORE_BLK)); LowerBlockStoreAsHelperCall(blkNode); } } diff --git a/src/coreclr/jit/lowerloongarch64.cpp b/src/coreclr/jit/lowerloongarch64.cpp index 507ef59256ca4..7b3fb43dfa5dc 100644 --- a/src/coreclr/jit/lowerloongarch64.cpp +++ b/src/coreclr/jit/lowerloongarch64.cpp @@ -296,8 +296,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) src = src->AsUnOp()->gtGetOp1(); } - if (!blkNode->OperIs(GT_STORE_DYN_BLK) && (size <= comp->getUnrollThreshold(Compiler::UnrollKind::Memset)) && - src->OperIs(GT_CNS_INT)) + if ((size <= comp->getUnrollThreshold(Compiler::UnrollKind::Memset)) && src->OperIs(GT_CNS_INT)) { blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindUnroll; @@ -351,7 +350,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) } ClassLayout* layout = blkNode->GetLayout(); - bool doCpObj = !blkNode->OperIs(GT_STORE_DYN_BLK) && layout->HasGCPtr(); + bool doCpObj = layout->HasGCPtr(); unsigned copyBlockUnrollLimit = comp->getUnrollThreshold(Compiler::UnrollKind::Memcpy); if (doCpObj && (size <= copyBlockUnrollLimit)) @@ -387,7 +386,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) } else { - assert(blkNode->OperIs(GT_STORE_BLK, GT_STORE_DYN_BLK)); + assert(blkNode->OperIs(GT_STORE_BLK)); LowerBlockStoreAsHelperCall(blkNode); } } diff --git a/src/coreclr/jit/lowerriscv64.cpp b/src/coreclr/jit/lowerriscv64.cpp index 405b9707c4114..d172ded699174 100644 --- a/src/coreclr/jit/lowerriscv64.cpp +++ b/src/coreclr/jit/lowerriscv64.cpp @@ -245,7 +245,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) src = src->AsUnOp()->gtGetOp1(); } - if (!blkNode->OperIs(GT_STORE_DYN_BLK) && (size <= INITBLK_UNROLL_LIMIT) && src->OperIs(GT_CNS_INT)) + if ((size <= INITBLK_UNROLL_LIMIT) && src->OperIs(GT_CNS_INT)) { blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindUnroll; @@ -299,7 +299,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) } ClassLayout* layout = blkNode->GetLayout(); - bool doCpObj = !blkNode->OperIs(GT_STORE_DYN_BLK) && layout->HasGCPtr(); + bool doCpObj = layout->HasGCPtr(); if (doCpObj && (size <= CPBLK_UNROLL_LIMIT)) { @@ -334,7 +334,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) } else { - assert(blkNode->OperIs(GT_STORE_BLK, GT_STORE_DYN_BLK)); + assert(blkNode->OperIs(GT_STORE_BLK)); LowerBlockStoreAsHelperCall(blkNode); } } diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index ea4db9fedbac4..e0ca67574e1c9 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -349,7 +349,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) src = src->AsUnOp()->gtGetOp1(); } - if (!blkNode->OperIs(GT_STORE_DYN_BLK) && (size <= comp->getUnrollThreshold(Compiler::UnrollKind::Memset))) + if (size <= comp->getUnrollThreshold(Compiler::UnrollKind::Memset)) { if (!src->OperIs(GT_CNS_INT)) { @@ -436,7 +436,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) } ClassLayout* layout = blkNode->GetLayout(); - bool doCpObj = !blkNode->OperIs(GT_STORE_DYN_BLK) && layout->HasGCPtr(); + bool doCpObj = layout->HasGCPtr(); unsigned copyBlockUnrollLimit = comp->getUnrollThreshold(Compiler::UnrollKind::Memcpy, false); #ifndef JIT32_GCENCODER @@ -516,7 +516,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode) } else { - assert(blkNode->OperIs(GT_STORE_BLK, GT_STORE_DYN_BLK)); + assert(blkNode->OperIs(GT_STORE_BLK)); #ifdef TARGET_AMD64 LowerBlockStoreAsHelperCall(blkNode); diff --git a/src/coreclr/jit/lsraarm.cpp b/src/coreclr/jit/lsraarm.cpp index 30991778868d6..2192265984d68 100644 --- a/src/coreclr/jit/lsraarm.cpp +++ b/src/coreclr/jit/lsraarm.cpp @@ -579,7 +579,6 @@ int LinearScan::BuildNode(GenTree* tree) break; case GT_STORE_BLK: - case GT_STORE_DYN_BLK: srcCount = BuildBlockStore(tree->AsBlk()); break; diff --git a/src/coreclr/jit/lsraarm64.cpp b/src/coreclr/jit/lsraarm64.cpp index 1893da10af960..52db29fd95abe 100644 --- a/src/coreclr/jit/lsraarm64.cpp +++ b/src/coreclr/jit/lsraarm64.cpp @@ -1076,7 +1076,6 @@ int LinearScan::BuildNode(GenTree* tree) break; case GT_STORE_BLK: - case GT_STORE_DYN_BLK: srcCount = BuildBlockStore(tree->AsBlk()); break; diff --git a/src/coreclr/jit/lsraarmarch.cpp b/src/coreclr/jit/lsraarmarch.cpp index c424a4d6bc620..1df68f5f3f574 100644 --- a/src/coreclr/jit/lsraarmarch.cpp +++ b/src/coreclr/jit/lsraarmarch.cpp @@ -805,7 +805,7 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) } } - if (!blkNode->OperIs(GT_STORE_DYN_BLK) && (sizeRegMask != RBM_NONE)) + if (sizeRegMask != RBM_NONE) { // Reserve a temp register for the block size argument. buildInternalIntRegisterDefForNode(blkNode, sizeRegMask); @@ -836,12 +836,6 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) } } - if (blkNode->OperIs(GT_STORE_DYN_BLK)) - { - useCount++; - BuildUse(blkNode->AsStoreDynBlk()->gtDynamicSize, sizeRegMask); - } - buildInternalRegisterUses(); regMaskTP killMask = getKillSetForBlockStore(blkNode); BuildDefsWithKills(blkNode, 0, RBM_NONE, killMask); diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 4b7454a4d71ed..6e746d35c93ad 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -1056,7 +1056,6 @@ regMaskTP LinearScan::getKillSetForNode(GenTree* tree) break; case GT_STORE_BLK: - case GT_STORE_DYN_BLK: killMask = getKillSetForBlockStore(tree->AsBlk()); break; diff --git a/src/coreclr/jit/lsraloongarch64.cpp b/src/coreclr/jit/lsraloongarch64.cpp index b6e3b53d63ee5..51b1871b40bdc 100644 --- a/src/coreclr/jit/lsraloongarch64.cpp +++ b/src/coreclr/jit/lsraloongarch64.cpp @@ -394,7 +394,6 @@ int LinearScan::BuildNode(GenTree* tree) break; case GT_STORE_BLK: - case GT_STORE_DYN_BLK: srcCount = BuildBlockStore(tree->AsBlk()); break; @@ -1157,7 +1156,7 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) } } - if (!blkNode->OperIs(GT_STORE_DYN_BLK) && (sizeRegMask != RBM_NONE)) + if (sizeRegMask != RBM_NONE) { // Reserve a temp register for the block size argument. buildInternalIntRegisterDefForNode(blkNode, sizeRegMask); @@ -1188,12 +1187,6 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) } } - if (blkNode->OperIs(GT_STORE_DYN_BLK)) - { - useCount++; - BuildUse(blkNode->AsStoreDynBlk()->gtDynamicSize, sizeRegMask); - } - buildInternalRegisterUses(); regMaskTP killMask = getKillSetForBlockStore(blkNode); BuildDefsWithKills(blkNode, 0, RBM_NONE, killMask); diff --git a/src/coreclr/jit/lsrariscv64.cpp b/src/coreclr/jit/lsrariscv64.cpp index c6e148d53d031..0a38d27574a13 100644 --- a/src/coreclr/jit/lsrariscv64.cpp +++ b/src/coreclr/jit/lsrariscv64.cpp @@ -512,7 +512,6 @@ int LinearScan::BuildNode(GenTree* tree) break; case GT_STORE_BLK: - case GT_STORE_DYN_BLK: srcCount = BuildBlockStore(tree->AsBlk()); break; @@ -1313,7 +1312,7 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) } } - if (!blkNode->OperIs(GT_STORE_DYN_BLK) && (sizeRegMask != RBM_NONE)) + if (sizeRegMask != RBM_NONE) { // Reserve a temp register for the block size argument. buildInternalIntRegisterDefForNode(blkNode, sizeRegMask); @@ -1344,12 +1343,6 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) } } - if (blkNode->OperIs(GT_STORE_DYN_BLK)) - { - useCount++; - BuildUse(blkNode->AsStoreDynBlk()->gtDynamicSize, sizeRegMask); - } - buildInternalRegisterUses(); regMaskTP killMask = getKillSetForBlockStore(blkNode); BuildDefsWithKills(blkNode, 0, RBM_NONE, killMask); diff --git a/src/coreclr/jit/lsraxarch.cpp b/src/coreclr/jit/lsraxarch.cpp index b108659f50ef5..a01c6ce5df057 100644 --- a/src/coreclr/jit/lsraxarch.cpp +++ b/src/coreclr/jit/lsraxarch.cpp @@ -507,7 +507,6 @@ int LinearScan::BuildNode(GenTree* tree) #endif // FEATURE_PUT_STRUCT_ARG_STK case GT_STORE_BLK: - case GT_STORE_DYN_BLK: srcCount = BuildBlockStore(tree->AsBlk()); break; @@ -1604,7 +1603,7 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) } } - if (!blkNode->OperIs(GT_STORE_DYN_BLK) && (sizeRegMask != RBM_NONE)) + if (sizeRegMask != RBM_NONE) { // Reserve a temp register for the block size argument. buildInternalIntRegisterDefForNode(blkNode, sizeRegMask); @@ -1635,12 +1634,6 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) } } - if (blkNode->OperIs(GT_STORE_DYN_BLK)) - { - useCount++; - BuildUse(blkNode->AsStoreDynBlk()->gtDynamicSize, sizeRegMask); - } - #ifdef TARGET_X86 // If we require a byte register on x86, we may run into an over-constrained situation // if we have BYTE_REG_COUNT or more uses (currently, it can be at most 4, if both the diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 6100cbb97489b..6ba44215a5f5d 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -12789,10 +12789,6 @@ GenTree* Compiler::fgMorphTree(GenTree* tree, MorphAddrContext* mac) gtUpdateNodeSideEffects(tree); break; - case GT_STORE_DYN_BLK: - tree = fgMorphStoreDynBlock(tree->AsStoreDynBlk()); - break; - case GT_SELECT: tree->AsConditional()->gtCond = fgMorphTree(tree->AsConditional()->gtCond); tree->AsConditional()->gtOp1 = fgMorphTree(tree->AsConditional()->gtOp1); @@ -13565,11 +13561,7 @@ void Compiler::fgMorphStmtBlockOps(BasicBlock* block, Statement* stmt) { if ((*use)->OperIsBlkOp()) { - if ((*use)->OperIs(GT_STORE_DYN_BLK)) - { - *use = m_compiler->fgMorphStoreDynBlock((*use)->AsStoreDynBlk()); - } - else if ((*use)->OperIsInitBlkOp()) + if ((*use)->OperIsInitBlkOp()) { *use = m_compiler->fgMorphInitBlock(*use); } diff --git a/src/coreclr/jit/morphblock.cpp b/src/coreclr/jit/morphblock.cpp index 94d10dd5887f5..3f4a20215ead8 100644 --- a/src/coreclr/jit/morphblock.cpp +++ b/src/coreclr/jit/morphblock.cpp @@ -1512,70 +1512,3 @@ GenTree* Compiler::fgMorphInitBlock(GenTree* tree) { return MorphInitBlockHelper::MorphInitBlock(this, tree); } - -//------------------------------------------------------------------------ -// fgMorphStoreDynBlock: Morph a dynamic block store (GT_STORE_DYN_BLK). -// -// Performs full (pre-order and post-order) morphing for a STORE_DYN_BLK. -// -// Arguments: -// tree - The GT_STORE_DYN_BLK tree to morph. -// -// Return Value: -// In case the size turns into a constant - the store, transformed -// into an "ordinary" STORE_BLK one, and further morphed by -// "fgMorphInitBlock"/"fgMorphCopyBlock". Otherwise, the original -// tree (fully morphed). -// -GenTree* Compiler::fgMorphStoreDynBlock(GenTreeStoreDynBlk* tree) -{ - if (!tree->Data()->OperIs(GT_CNS_INT, GT_INIT_VAL)) - { - // Data is a location and required to have GTF_DONT_CSE. - tree->Data()->gtFlags |= GTF_DONT_CSE; - } - - tree->Addr() = fgMorphTree(tree->Addr()); - tree->Data() = fgMorphTree(tree->Data()); - tree->gtDynamicSize = fgMorphTree(tree->gtDynamicSize); - - if (tree->gtDynamicSize->IsIntegralConst()) - { - int64_t size = tree->gtDynamicSize->AsIntConCommon()->IntegralValue(); - - if ((size != 0) && FitsIn(size)) - { - ClassLayout* layout = typGetBlkLayout(static_cast(size)); - GenTree* src = tree->Data(); - if (src->OperIs(GT_IND)) - { - assert(src->TypeIs(TYP_STRUCT)); - src->SetOper(GT_BLK); - src->AsBlk()->Initialize(layout); - } - - GenTree* store = gtNewStoreValueNode(layout, tree->Addr(), src, tree->gtFlags & GTF_IND_FLAGS); - store->AddAllEffectsFlags(tree); - INDEBUG(store->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED); - - JITDUMP("MorphStoreDynBlock: transformed STORE_DYN_BLK into STORE_BLK\n"); - - return tree->OperIsCopyBlkOp() ? fgMorphCopyBlock(store) : fgMorphInitBlock(store); - } - } - - tree->SetAllEffectsFlags(tree->Addr(), tree->Data(), tree->gtDynamicSize); - - if (tree->OperMayThrow(this)) - { - tree->gtFlags |= GTF_EXCEPT; - } - else - { - tree->gtFlags |= GTF_IND_NONFAULTING; - } - - tree->gtFlags |= GTF_ASG; - - return tree; -} diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index d9e9ee4969ed1..5f13e7a8c72af 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -5616,7 +5616,6 @@ void Compiler::optComputeLoopSideEffectsOfBlock(BasicBlock* blk, FlowGraphNatura case GT_XCHG: case GT_CMPXCHG: case GT_MEMORYBARRIER: - case GT_STORE_DYN_BLK: { memoryHavoc |= memoryKindSet(GcHeap, ByrefExposed); } diff --git a/src/coreclr/jit/sideeffects.cpp b/src/coreclr/jit/sideeffects.cpp index d2c1de6c749a5..a2dd47c994ef4 100644 --- a/src/coreclr/jit/sideeffects.cpp +++ b/src/coreclr/jit/sideeffects.cpp @@ -174,7 +174,7 @@ AliasSet::NodeInfo::NodeInfo(Compiler* compiler, GenTree* node) // Is the operation a write? If so, set `node` to the location that is being written to. bool isWrite = false; - if (node->OperIsStore() || node->OperIs(GT_STORE_DYN_BLK, GT_MEMORYBARRIER)) + if (node->OperIsStore() || node->OperIs(GT_MEMORYBARRIER)) { isWrite = true; } diff --git a/src/coreclr/jit/simd.cpp b/src/coreclr/jit/simd.cpp index d69730ad520ed..48c23eb646411 100644 --- a/src/coreclr/jit/simd.cpp +++ b/src/coreclr/jit/simd.cpp @@ -549,8 +549,6 @@ bool areFieldAddressesTheSame(GenTreeFieldAddr* op1, GenTreeFieldAddr* op2) bool Compiler::areFieldsContiguous(GenTreeIndir* op1, GenTreeIndir* op2) { assert(op1->isIndir() && op2->isIndir()); - // TODO-1stClassStructs: delete once IND nodes are no more. - assert(!op1->TypeIs(TYP_STRUCT) && !op2->TypeIs(TYP_STRUCT)); var_types op1Type = op1->TypeGet(); var_types op2Type = op2->TypeGet(); diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index e86b2aff6eb45..c7af200c3de60 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -9573,8 +9573,8 @@ const uint8_t ValueNumStore::s_vnfOpAttribs[VNF_COUNT] = { static genTreeOps genTreeOpsIllegalAsVNFunc[] = {GT_IND, // When we do heap memory. GT_NULLCHECK, GT_QMARK, GT_COLON, GT_LOCKADD, GT_XADD, GT_XCHG, - GT_CMPXCHG, GT_LCLHEAP, GT_BOX, GT_XORR, GT_XAND, GT_STORE_DYN_BLK, - GT_STORE_LCL_VAR, GT_STORE_LCL_FLD, GT_STOREIND, GT_STORE_BLK, + GT_CMPXCHG, GT_LCLHEAP, GT_BOX, GT_XORR, GT_XAND, GT_STORE_LCL_VAR, + GT_STORE_LCL_FLD, GT_STOREIND, GT_STORE_BLK, // These need special semantics: GT_COMMA, // == second argument (but with exception(s) from first). GT_ARR_ADDR, GT_BOUNDS_CHECK, @@ -11488,12 +11488,7 @@ void Compiler::fgValueNumberTree(GenTree* tree) unsigned loadSize = tree->AsIndir()->Size(); VNFuncApp funcApp{VNF_COUNT}; - // TODO-1stClassStructs: delete layout-less "IND(struct)" nodes and the "loadSize == 0" condition. - if (loadSize == 0) - { - tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, loadType)); - } - else if (fgValueNumberConstLoad(tree->AsIndir())) + if (fgValueNumberConstLoad(tree->AsIndir())) { // VN is assigned inside fgValueNumberConstLoad } @@ -11760,30 +11755,6 @@ void Compiler::fgValueNumberTree(GenTree* tree) break; #endif // FEATURE_HW_INTRINSICS - case GT_STORE_DYN_BLK: - { - // Conservatively, mutate the heaps - we don't analyze these rare stores. - // Likewise, any locals possibly defined by them we mark as address-exposed. - fgMutateGcHeap(tree DEBUGARG("dynamic block store")); - - GenTreeStoreDynBlk* store = tree->AsStoreDynBlk(); - ValueNumPair vnpExcSet = ValueNumStore::VNPForEmptyExcSet(); - - // Propagate the exceptions... - vnpExcSet = vnStore->VNPUnionExcSet(store->Addr()->gtVNPair, vnpExcSet); - vnpExcSet = vnStore->VNPUnionExcSet(store->Data()->gtVNPair, vnpExcSet); - vnpExcSet = vnStore->VNPUnionExcSet(store->gtDynamicSize->gtVNPair, vnpExcSet); - - // This is a store, it produces no value. Thus we use VNPForVoid(). - store->gtVNPair = vnStore->VNPWithExc(vnStore->VNPForVoid(), vnpExcSet); - - // Note that we are only adding the exception for the destination address. - // Currently, "Data()" is an explicit indirection in case this is a "cpblk". - assert(store->Data()->gtEffectiveVal()->OperIsIndir() || store->OperIsInitBlkOp()); - fgValueNumberAddExceptionSetForIndirection(store, store->Addr()); - break; - } - case GT_CMPXCHG: // Specialop { // For CMPXCHG and other intrinsics add an arbitrary side effect on GcHeap/ByrefExposed. diff --git a/src/coreclr/vm/callcounting.cpp b/src/coreclr/vm/callcounting.cpp index e7c70dccf4096..c464949f7aeee 100644 --- a/src/coreclr/vm/callcounting.cpp +++ b/src/coreclr/vm/callcounting.cpp @@ -660,7 +660,7 @@ bool CallCountingManager::SetCodeEntryPoint( CallCount callCountThreshold = g_pConfig->TieredCompilation_CallCountThreshold(); _ASSERTE(callCountThreshold != 0); - // Let's tier up all cast and runtime helpers faster than other methods. This is because we want to import them as + // Let's tier up all cast helpers faster than other methods. This is because we want to import them as // direct calls in codegen and they need to be promoted earlier than their callers. if (methodDesc->GetMethodTable() == g_pCastHelpers) { diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.ByteMemOps.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.ByteMemOps.cs index ed54c495d60d4..5429459209925 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.ByteMemOps.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.ByteMemOps.cs @@ -22,7 +22,6 @@ internal static partial class SpanHelpers // .ByteMemOps #else private const nuint MemmoveNativeThreshold = 2048; #endif - // TODO: Determine optimal value private const nuint ZeroMemoryNativeThreshold = 1024; diff --git a/src/tests/JIT/opt/Structs/MemsetMemcpyNullref.cs b/src/tests/JIT/opt/Structs/MemsetMemcpyNullref.cs index 9d7e4816522c7..0d18e7bf53514 100644 --- a/src/tests/JIT/opt/Structs/MemsetMemcpyNullref.cs +++ b/src/tests/JIT/opt/Structs/MemsetMemcpyNullref.cs @@ -39,6 +39,14 @@ public static void MemsetMemcpyThrowNullRefonNull() MemoryCopyByref(ref Unsafe.NullRef(), ref valid, 0); MemoryCopyByref(ref valid, ref Unsafe.NullRef(), 0); MemoryCopyByref(ref Unsafe.NullRef(), ref Unsafe.NullRef(), 0); + + byte valid2 = 0; + MemoryInitByrefZeroLen(ref valid); + MemoryInitByrefZeroLen(ref Unsafe.NullRef()); + MemoryCopyByrefZeroLen(ref valid, ref valid2); + MemoryCopyByrefZeroLen(ref valid, ref Unsafe.NullRef()); + MemoryCopyByrefZeroLen(ref Unsafe.NullRef(), ref valid2); + MemoryCopyByrefZeroLen(ref Unsafe.NullRef(), ref Unsafe.NullRef()); } [MethodImpl(MethodImplOptions.NoInlining)] @@ -61,4 +69,12 @@ private struct HugeStruct { public fixed byte Data[20_000]; } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void MemoryCopyByrefZeroLen(ref byte dst, ref byte src) => + Unsafe.CopyBlockUnaligned(ref dst, ref src, 0); + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void MemoryInitByrefZeroLen(ref byte dst) => + Unsafe.InitBlockUnaligned(ref dst, 42, 0); } diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 4fb0524c67cb2..2ab3b36bf3fb7 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -1163,16 +1163,6 @@ - - - - https://github.com/dotnet/runtime/issues/95517 - - - https://github.com/dotnet/runtime/issues/95517 - - -