diff --git a/src/coreclr/src/jit/lsra.cpp b/src/coreclr/src/jit/lsra.cpp index da44c5961a9471..e468377f56f82c 100644 --- a/src/coreclr/src/jit/lsra.cpp +++ b/src/coreclr/src/jit/lsra.cpp @@ -2733,8 +2733,10 @@ bool LinearScan::isMatchingConstant(RegRecord* physRegRecord, RefPosition* refPo switch (otherTreeNode->OperGet()) { case GT_CNS_INT: - if ((refPosition->treeNode->AsIntCon()->IconValue() == otherTreeNode->AsIntCon()->IconValue()) && - (varTypeGCtype(refPosition->treeNode) == varTypeGCtype(otherTreeNode))) + { + ssize_t v1 = refPosition->treeNode->AsIntCon()->IconValue(); + ssize_t v2 = otherTreeNode->AsIntCon()->IconValue(); + if ((v1 == v2) && (varTypeGCtype(refPosition->treeNode) == varTypeGCtype(otherTreeNode) || v1 == 0)) { #ifdef TARGET_64BIT // If the constant is negative, only reuse registers of the same type. @@ -2743,14 +2745,14 @@ bool LinearScan::isMatchingConstant(RegRecord* physRegRecord, RefPosition* refPo // This doesn't apply to a 32-bit system, on which long values occupy multiple registers. // (We could sign-extend, but we would have to always sign-extend, because if we reuse more // than once, we won't have access to the instruction that originally defines the constant). - if ((refPosition->treeNode->TypeGet() == otherTreeNode->TypeGet()) || - (refPosition->treeNode->AsIntCon()->IconValue() >= 0)) + if ((refPosition->treeNode->TypeGet() == otherTreeNode->TypeGet()) || (v1 >= 0)) #endif // TARGET_64BIT { return true; } } break; + } case GT_CNS_DBL: { // For floating point constants, the values must be identical, not simply compare diff --git a/src/coreclr/src/jit/morph.cpp b/src/coreclr/src/jit/morph.cpp index e8ce24c9ce889a..49bc83a4ce23b7 100644 --- a/src/coreclr/src/jit/morph.cpp +++ b/src/coreclr/src/jit/morph.cpp @@ -10600,8 +10600,20 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree) // If we passed the above checks, then we will check these two if (!requiresCopyBlock) { + // It is not always profitable to do field by field init for structs that are allocated to memory. + // A struct with 8 bool fields will require 8 moves instead of one if we do this transformation. + // A simple heuristic when field by field copy is prefered: + // - if fields can be enregistered; + // - if the struct has GCPtrs (block copy would be done via helper that is expensive); + // - if the struct has only one field. + bool dstFldIsProfitable = + ((destLclVar != nullptr) && + (!destLclVar->lvDoNotEnregister || destLclVar->HasGCPtr() || (destLclVar->lvFieldCnt == 1))); + bool srcFldIsProfitable = + ((srcLclVar != nullptr) && + (!srcLclVar->lvDoNotEnregister || srcLclVar->HasGCPtr() || (srcLclVar->lvFieldCnt == 1))); // Are both dest and src promoted structs? - if (destDoFldAsg && srcDoFldAsg) + if (destDoFldAsg && srcDoFldAsg && (dstFldIsProfitable || srcFldIsProfitable)) { // Both structs should be of the same type, or have the same number of fields of the same type. // If not we will use a copy block. @@ -10633,13 +10645,7 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree) } } } - // Are neither dest or src promoted structs? - else if (!destDoFldAsg && !srcDoFldAsg) - { - requiresCopyBlock = true; // Leave as a CopyBlock - JITDUMP(" with no promoted structs"); - } - else if (destDoFldAsg) + else if (destDoFldAsg && dstFldIsProfitable) { // Match the following kinds of trees: // fgMorphTree BB01, stmt 9 (before) @@ -10683,9 +10689,8 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree) } } } - else + else if (srcDoFldAsg && srcFldIsProfitable) { - assert(srcDoFldAsg); // Check for the symmetric case (which happens for the _pointer field of promoted spans): // // [000240] -----+------ /--* lclVar struct(P) V18 tmp9 @@ -10707,6 +10712,13 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree) } } } + // Are neither dest or src promoted structs? + else + { + assert(!(destDoFldAsg && dstFldIsProfitable) && !(srcDoFldAsg && srcFldIsProfitable)); + requiresCopyBlock = true; // Leave as a CopyBlock + JITDUMP(" with no promoted structs"); + } } // If we require a copy block the set both of the field assign bools to false