@@ -6442,7 +6442,10 @@ GenTree* Compiler::impImportLdvirtftn(GenTree* thisPtr,
64426442// pResolvedToken is known to be a value type; ref type boxing
64436443// is handled in the CEE_BOX clause.
64446444
6445- int Compiler::impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken, const BYTE* codeAddr, const BYTE* codeEndp)
6445+ int Compiler::impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken,
6446+ const BYTE* codeAddr,
6447+ const BYTE* codeEndp,
6448+ bool makeInlineObservation)
64466449{
64476450 if (codeAddr >= codeEndp)
64486451 {
@@ -6455,6 +6458,12 @@ int Compiler::impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken, const B
64556458 // box + unbox.any
64566459 if (codeAddr + 1 + sizeof(mdToken) <= codeEndp)
64576460 {
6461+ if (makeInlineObservation)
6462+ {
6463+ compInlineResult->Note(InlineObservation::CALLEE_FOLDABLE_BOX);
6464+ return 1 + sizeof(mdToken);
6465+ }
6466+
64586467 CORINFO_RESOLVED_TOKEN unboxResolvedToken;
64596468
64606469 impResolveToken(codeAddr + 1, &unboxResolvedToken, CORINFO_TOKENKIND_Class);
@@ -6480,6 +6489,12 @@ int Compiler::impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken, const B
64806489 // box + br_true/false
64816490 if ((codeAddr + ((codeAddr[0] >= CEE_BRFALSE) ? 5 : 2)) <= codeEndp)
64826491 {
6492+ if (makeInlineObservation)
6493+ {
6494+ compInlineResult->Note(InlineObservation::CALLEE_FOLDABLE_BOX);
6495+ return 0;
6496+ }
6497+
64836498 GenTree* const treeToBox = impStackTop().val;
64846499 bool canOptimize = true;
64856500 GenTree* treeToNullcheck = nullptr;
@@ -6542,6 +6557,12 @@ int Compiler::impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken, const B
65426557 case CEE_BRFALSE_S:
65436558 if ((nextCodeAddr + ((nextCodeAddr[0] >= CEE_BRFALSE) ? 5 : 2)) <= codeEndp)
65446559 {
6560+ if (makeInlineObservation)
6561+ {
6562+ compInlineResult->Note(InlineObservation::CALLEE_FOLDABLE_BOX);
6563+ return 1 + sizeof(mdToken);
6564+ }
6565+
65456566 if (!(impStackTop().val->gtFlags & GTF_SIDE_EFFECT))
65466567 {
65476568 CorInfoHelpFunc boxHelper = info.compCompHnd->getBoxHelper(pResolvedToken->hClass);
@@ -6618,6 +6639,12 @@ int Compiler::impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken, const B
66186639 case CEE_UNBOX_ANY:
66196640 if ((nextCodeAddr + 1 + sizeof(mdToken)) <= codeEndp)
66206641 {
6642+ if (makeInlineObservation)
6643+ {
6644+ compInlineResult->Note(InlineObservation::CALLEE_FOLDABLE_BOX);
6645+ return 2 + sizeof(mdToken) * 2;
6646+ }
6647+
66216648 // See if the resolved tokens in box, isinst and unbox.any describe types that are equal.
66226649 CORINFO_RESOLVED_TOKEN isinstResolvedToken = {};
66236650 impResolveToken(codeAddr + 1, &isinstResolvedToken, CORINFO_TOKENKIND_Class);
@@ -18868,6 +18895,86 @@ void Compiler::impMakeDiscretionaryInlineObservations(InlineInfo* pInlineInfo, I
1886818895 }
1886918896 }
1887018897
18898+ bool callsiteIsGeneric = (rootCompiler->info.compMethodInfo->args.sigInst.methInstCount != 0) ||
18899+ (rootCompiler->info.compMethodInfo->args.sigInst.classInstCount != 0);
18900+
18901+ bool calleeIsGeneric = (info.compMethodInfo->args.sigInst.methInstCount != 0) ||
18902+ (info.compMethodInfo->args.sigInst.classInstCount != 0);
18903+
18904+ if (!callsiteIsGeneric && calleeIsGeneric)
18905+ {
18906+ inlineResult->Note(InlineObservation::CALLSITE_NONGENERIC_CALLS_GENERIC);
18907+ }
18908+
18909+ if (pInlineInfo != nullptr)
18910+ {
18911+ // Inspect callee's arguments (and the actual values at the callsite for them)
18912+ CORINFO_SIG_INFO sig = info.compMethodInfo->args;
18913+ CORINFO_ARG_LIST_HANDLE sigArg = sig.args;
18914+
18915+ GenTreeCall::Use* argUse = pInlineInfo->iciCall->AsCall()->gtCallArgs;
18916+
18917+ for (unsigned i = 0; i < info.compMethodInfo->args.numArgs; i++)
18918+ {
18919+ assert(argUse != nullptr);
18920+
18921+ CORINFO_CLASS_HANDLE sigClass;
18922+ CorInfoType corType = strip(info.compCompHnd->getArgType(&sig, sigArg, &sigClass));
18923+ GenTree* argNode = argUse->GetNode()->gtSkipPutArgType();
18924+
18925+ if (corType == CORINFO_TYPE_CLASS)
18926+ {
18927+ sigClass = info.compCompHnd->getArgClass(&sig, sigArg);
18928+ }
18929+ else if (corType == CORINFO_TYPE_VALUECLASS)
18930+ {
18931+ inlineResult->Note(InlineObservation::CALLEE_ARG_STRUCT);
18932+ }
18933+ else if (corType == CORINFO_TYPE_BYREF)
18934+ {
18935+ sigClass = info.compCompHnd->getArgClass(&sig, sigArg);
18936+ corType = info.compCompHnd->getChildType(sigClass, &sigClass);
18937+ }
18938+
18939+ bool isExact = false;
18940+ bool isNonNull = false;
18941+ CORINFO_CLASS_HANDLE argCls = gtGetClassHandle(argNode, &isExact, &isNonNull);
18942+ if (argCls != nullptr)
18943+ {
18944+ const bool isArgValueType = eeIsValueClass(argCls);
18945+ // Exact class of the arg is known
18946+ if (isExact && !isArgValueType)
18947+ {
18948+ inlineResult->Note(InlineObservation::CALLSITE_ARG_EXACT_CLS);
18949+ if ((argCls != sigClass) && (sigClass != nullptr))
18950+ {
18951+ // .. but the signature accepts a less concrete type.
18952+ inlineResult->Note(InlineObservation::CALLSITE_ARG_EXACT_CLS_SIG_IS_NOT);
18953+ }
18954+ }
18955+ // Arg is a reference type in the signature and a boxed value type was passed.
18956+ else if (isArgValueType && (corType == CORINFO_TYPE_CLASS))
18957+ {
18958+ inlineResult->Note(InlineObservation::CALLSITE_ARG_BOXED);
18959+ }
18960+ }
18961+
18962+ if (argNode->OperIsConst())
18963+ {
18964+ inlineResult->Note(InlineObservation::CALLSITE_ARG_CONST);
18965+ }
18966+
18967+ sigArg = info.compCompHnd->getArgNext(sigArg);
18968+ argUse = argUse->GetNext();
18969+ }
18970+ }
18971+
18972+ // Note if the callee's return type is a value type
18973+ if (info.compMethodInfo->args.retType == CORINFO_TYPE_VALUECLASS)
18974+ {
18975+ inlineResult->Note(InlineObservation::CALLEE_RETURNS_STRUCT);
18976+ }
18977+
1887118978 // Note if the callee's class is a promotable struct
1887218979 if ((info.compClassAttr & CORINFO_FLG_VALUECLASS) != 0)
1887318980 {
0 commit comments