Skip to content

Commit 968532c

Browse files
EgorBoAndyAyersMS
andauthored
Inliner: new observations (don't impact inlining for now) (#53670)
Co-authored-by: Andy Ayers <andya@microsoft.com>
1 parent fde3692 commit 968532c

File tree

10 files changed

+667
-40
lines changed

10 files changed

+667
-40
lines changed

src/coreclr/jit/compiler.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,7 +1466,19 @@ void Compiler::compShutdown()
14661466

14671467
#if defined(DEBUG) || defined(INLINE_DATA)
14681468
// Finish reading and/or writing inline xml
1469-
InlineStrategy::FinalizeXml();
1469+
if (JitConfig.JitInlineDumpXmlFile() != nullptr)
1470+
{
1471+
FILE* file = _wfopen(JitConfig.JitInlineDumpXmlFile(), W("a"));
1472+
if (file != nullptr)
1473+
{
1474+
InlineStrategy::FinalizeXml(file);
1475+
fclose(file);
1476+
}
1477+
else
1478+
{
1479+
InlineStrategy::FinalizeXml();
1480+
}
1481+
}
14701482
#endif // defined(DEBUG) || defined(INLINE_DATA)
14711483

14721484
#if defined(DEBUG) || MEASURE_NODE_SIZE || MEASURE_BLOCK_SIZE || DISPLAY_SIZES || CALL_ARG_STATS
@@ -5898,7 +5910,24 @@ void Compiler::compCompileFinish()
58985910
#if defined(DEBUG) || defined(INLINE_DATA)
58995911

59005912
m_inlineStrategy->DumpData();
5901-
m_inlineStrategy->DumpXml();
5913+
5914+
if (JitConfig.JitInlineDumpXmlFile() != nullptr)
5915+
{
5916+
FILE* file = _wfopen(JitConfig.JitInlineDumpXmlFile(), W("a"));
5917+
if (file != nullptr)
5918+
{
5919+
m_inlineStrategy->DumpXml(file);
5920+
fclose(file);
5921+
}
5922+
else
5923+
{
5924+
m_inlineStrategy->DumpXml();
5925+
}
5926+
}
5927+
else
5928+
{
5929+
m_inlineStrategy->DumpXml();
5930+
}
59025931

59035932
#endif
59045933

src/coreclr/jit/compiler.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3989,7 +3989,10 @@ class Compiler
39893989

39903990
GenTree* impImportLdvirtftn(GenTree* thisPtr, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_CALL_INFO* pCallInfo);
39913991

3992-
int impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken, const BYTE* codeAddr, const BYTE* codeEndp);
3992+
int impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken,
3993+
const BYTE* codeAddr,
3994+
const BYTE* codeEndp,
3995+
bool makeInlineObservation = false);
39933996
void impImportAndPushBox(CORINFO_RESOLVED_TOKEN* pResolvedToken);
39943997

39953998
void impImportNewObjArray(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_CALL_INFO* pCallInfo);

src/coreclr/jit/fgbasic.cpp

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,7 @@ class FgStack
764764
}
765765
void PushArgument(unsigned arg)
766766
{
767-
Push(SLOT_ARGUMENT + arg);
767+
Push(static_cast<FgSlot>(SLOT_ARGUMENT + arg));
768768
}
769769
unsigned GetSlot0() const
770770
{
@@ -807,7 +807,7 @@ class FgStack
807807
}
808808

809809
private:
810-
enum
810+
enum FgSlot
811811
{
812812
SLOT_INVALID = UINT_MAX,
813813
SLOT_UNKNOWN = 0,
@@ -816,7 +816,7 @@ class FgStack
816816
SLOT_ARGUMENT = 3
817817
};
818818

819-
void Push(int type)
819+
void Push(FgSlot type)
820820
{
821821
switch (depth)
822822
{
@@ -833,8 +833,8 @@ class FgStack
833833
}
834834
}
835835

836-
unsigned slot0;
837-
unsigned slot1;
836+
FgSlot slot0;
837+
FgSlot slot1;
838838
unsigned depth;
839839
};
840840

@@ -871,6 +871,12 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
871871
compInlineResult->Note(InlineObservation::CALLSITE_IN_TRY_REGION);
872872
}
873873

874+
// Determine if the call site is in a no-return block
875+
if (isInlining && (impInlineInfo->iciBlock->bbJumpKind == BBJ_THROW))
876+
{
877+
compInlineResult->Note(InlineObservation::CALLSITE_IN_NORETURN_REGION);
878+
}
879+
874880
// Determine if the call site is in a loop.
875881
if (isInlining && ((impInlineInfo->iciBlock->bbFlags & BBF_BACKWARD_JUMP) != 0))
876882
{
@@ -941,6 +947,32 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
941947
BADCODE3("Illegal opcode", ": %02X", (int)opcode);
942948
}
943949

950+
case CEE_THROW:
951+
{
952+
if (makeInlineObservations)
953+
{
954+
compInlineResult->Note(InlineObservation::CALLEE_THROW_BLOCK);
955+
}
956+
break;
957+
}
958+
959+
case CEE_BOX:
960+
{
961+
if (makeInlineObservations)
962+
{
963+
int toSkip = impBoxPatternMatch(nullptr, codeAddr + sz, codeEndp, true);
964+
if (toSkip > 0)
965+
{
966+
// toSkip > 0 means we most likely will hit a pattern (e.g. box+isinst+brtrue) that
967+
// will be folded into a const
968+
969+
// TODO: uncomment later
970+
// codeAddr += toSkip;
971+
}
972+
}
973+
break;
974+
}
975+
944976
case CEE_CALL:
945977
case CEE_CALLVIRT:
946978
{

src/coreclr/jit/importer.cpp

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)