@@ -4154,6 +4154,8 @@ GenTree* Compiler::impImportStaticReadOnlyField(CORINFO_FIELD_HANDLE field, CORI
41544154 return nullptr;
41554155 }
41564156
4157+ JITDUMP("\nChecking if we can import 'static readonly' as a jit-time constant... ")
4158+
41574159 CORINFO_CLASS_HANDLE fieldClsHnd;
41584160 var_types fieldType = JITtype2varType(info.compCompHnd->getFieldType(field, &fieldClsHnd, ownerCls));
41594161
@@ -4167,20 +4169,64 @@ GenTree* Compiler::impImportStaticReadOnlyField(CORINFO_FIELD_HANDLE field, CORI
41674169 GenTree* cnsValue = impImportCnsTreeFromBuffer(buffer, fieldType);
41684170 if (cnsValue != nullptr)
41694171 {
4172+ JITDUMP("... success! The value is:\n");
4173+ DISPTREE(cnsValue);
41704174 return cnsValue;
41714175 }
41724176 }
41734177 }
41744178 else if (fieldType == TYP_STRUCT)
41754179 {
4180+ unsigned totalSize = info.compCompHnd->getClassSize(fieldClsHnd);
4181+ unsigned fieldsCnt = info.compCompHnd->getClassNumInstanceFields(fieldClsHnd);
41764182
4177- if (info.compCompHnd->getClassNumInstanceFields(fieldClsHnd) != 1)
4183+ // For large structs we only want to handle "initialized with zero" case
4184+ // e.g. Guid.Empty and decimal.Zero static readonly fields.
4185+ if ((totalSize > TARGET_POINTER_SIZE) || (fieldsCnt != 1))
41784186 {
4179- // Only single-field structs are supported here to avoid potential regressions where
4180- // Metadata-driven struct promotion leads to regressions.
4187+ JITDUMP("checking if we can do anything for a large struct ...");
4188+ const int MaxStructSize = 64;
4189+ if ((totalSize == 0) || (totalSize > MaxStructSize))
4190+ {
4191+ // Limit to 64 bytes for better throughput
4192+ JITDUMP("struct is larger than 64 bytes - bail out.");
4193+ return nullptr;
4194+ }
4195+
4196+ uint8_t buffer[MaxStructSize] = {0};
4197+ if (info.compCompHnd->getReadonlyStaticFieldValue(field, buffer, totalSize))
4198+ {
4199+ for (unsigned i = 0; i < totalSize; i++)
4200+ {
4201+ if (buffer[i] != 0)
4202+ {
4203+ // Value is not all zeroes - bail out.
4204+ // Although, We might eventually support that too.
4205+ JITDUMP("value is not all zeros - bail out.");
4206+ return nullptr;
4207+ }
4208+ }
4209+
4210+ JITDUMP("success! Optimizing to ASG(struct, 0).");
4211+ unsigned structTempNum = lvaGrabTemp(true DEBUGARG("folding static ro fld empty struct"));
4212+ lvaSetStruct(structTempNum, fieldClsHnd, false);
4213+
4214+ // realType is either struct or SIMD
4215+ var_types realType = lvaGetRealType(structTempNum);
4216+ GenTreeLclVar* structLcl = gtNewLclvNode(structTempNum, realType);
4217+ impAppendTree(gtNewBlkOpNode(structLcl, gtNewIconNode(0), false, false), CHECK_SPILL_NONE,
4218+ impCurStmtDI);
4219+
4220+ return gtNewLclvNode(structTempNum, realType);
4221+ }
4222+
4223+ JITDUMP("getReadonlyStaticFieldValue returned false - bail out.");
41814224 return nullptr;
41824225 }
41834226
4227+ // Only single-field structs are supported here to avoid potential regressions where
4228+ // Metadata-driven struct promotion leads to regressions.
4229+
41844230 CORINFO_FIELD_HANDLE innerField = info.compCompHnd->getFieldInClass(fieldClsHnd, 0);
41854231 CORINFO_CLASS_HANDLE innerFieldClsHnd;
41864232 var_types fieldVarType =
@@ -4189,15 +4235,16 @@ GenTree* Compiler::impImportStaticReadOnlyField(CORINFO_FIELD_HANDLE field, CORI
41894235 // Technically, we can support frozen gc refs here and maybe floating point in future
41904236 if (!varTypeIsIntegral(fieldVarType))
41914237 {
4238+ JITDUMP("struct has non-primitive fields - bail out.");
41924239 return nullptr;
41934240 }
41944241
4195- unsigned totalSize = info.compCompHnd->getClassSize(fieldClsHnd);
41964242 unsigned fldOffset = info.compCompHnd->getFieldOffset(innerField);
41974243
4198- if ((fldOffset != 0) || (totalSize != info.compCompHnd->getClassSize(fieldClsHnd )) || (totalSize == 0))
4244+ if ((fldOffset != 0) || (totalSize != genTypeSize(fieldVarType )) || (totalSize == 0))
41994245 {
42004246 // The field is expected to be of the exact size as the struct with 0 offset
4247+ JITDUMP("struct has complex layout - bail out.");
42014248 return nullptr;
42024249 }
42034250
0 commit comments