diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index f72fa678135d22..7da821b6119c80 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -482,13 +482,14 @@ enum GenTreeFlags : unsigned int GTF_IND_REQ_ADDR_IN_REG = 0x08000000, // GT_IND -- requires its addr operand to be evaluated into a register. // This flag is useful in cases where it is required to generate register // indirect addressing mode. One such case is virtual stub calls on xarch. + GTF_IND_DELEGATE = 0x04000000, // GT_IND -- the target is a delegate (used for inlining heuristics) GTF_IND_UNALIGNED = 0x02000000, // OperIsIndir() -- the load or store is unaligned (we assume worst case alignment of 1 byte) GTF_IND_INVARIANT = 0x01000000, // GT_IND -- the target is invariant (a prejit indirection) GTF_IND_NONNULL = 0x00400000, // GT_IND -- the indirection never returns null (zero) GTF_IND_INITCLASS = 0x00200000, // OperIsIndir() -- the indirection requires preceding static cctor GTF_IND_ALLOW_NON_ATOMIC = 0x00100000, // GT_IND -- this memory access does not need to be atomic - GTF_IND_COPYABLE_FLAGS = GTF_IND_VOLATILE | GTF_IND_NONFAULTING | GTF_IND_UNALIGNED | GTF_IND_INITCLASS, + GTF_IND_COPYABLE_FLAGS = GTF_IND_VOLATILE | GTF_IND_NONFAULTING | GTF_IND_UNALIGNED | GTF_IND_DELEGATE | GTF_IND_INITCLASS, GTF_IND_FLAGS = GTF_IND_COPYABLE_FLAGS | GTF_IND_NONNULL | GTF_IND_TGT_NOT_HEAP | GTF_IND_TGT_HEAP | GTF_IND_INVARIANT | GTF_IND_ALLOW_NON_ATOMIC, GTF_ADDRMODE_NO_CSE = 0x80000000, // GT_ADD/GT_MUL/GT_LSH -- Do not CSE this node only, forms complex diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 564d3560109859..876fc5f25691ed 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -4141,11 +4141,17 @@ GenTree* Compiler::impImportStaticFieldAddress(CORINFO_RESOLVED_TOKEN* pResolved if (!isBoxedStatic && (lclTyp == TYP_REF) && ((access & CORINFO_ACCESS_GET) != 0) && ((*pIndirFlags & GTF_IND_VOLATILE) == 0)) { - bool isSpeculative = true; - if ((info.compCompHnd->getStaticFieldCurrentClass(pResolvedToken->hField, &isSpeculative) != - NO_CLASS_HANDLE)) + bool isSpeculative = true; + CORINFO_CLASS_HANDLE classHandle = + info.compCompHnd->getStaticFieldCurrentClass(pResolvedToken->hField, &isSpeculative); + if (classHandle != NO_CLASS_HANDLE) { isStaticReadOnlyInitedRef = !isSpeculative; + unsigned attribs = info.compCompHnd->getClassAttribs(classHandle); + if ((attribs & CORINFO_FLG_DELEGATE) != 0) + { + indirFlags |= GTF_IND_DELEGATE; + } } } #endif // TARGET_64BIT @@ -12545,7 +12551,9 @@ void Compiler::impFixPredLists() // bool Compiler::impIsInvariant(const GenTree* tree) { - return tree->OperIsConst() || impIsAddressInLocal(tree) || tree->OperIs(GT_FTN_ADDR); + return tree->OperIsConst() || impIsAddressInLocal(tree) || tree->OperIs(GT_FTN_ADDR) || + (tree->OperIs(GT_IND) && tree->AsIndir()->IsInvariantLoad() && + ((tree->AsIndir()->gtFlags & (GTF_SIDE_EFFECT | GTF_IND_DELEGATE)) == GTF_IND_DELEGATE)); } //------------------------------------------------------------------------