Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inliner: new observations (don't impact inlining for now) #53670

Merged
merged 29 commits into from
Jun 9, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
44d2469
Infrastructure changes (don't impact performance)
EgorBo Jun 3, 2021
4d083c7
Infrastructure changes (don't impact performance)
EgorBo Jun 3, 2021
9480fe9
Formatting
EgorBo Jun 3, 2021
4eb5eb0
Formatting
EgorBo Jun 3, 2021
d12eed8
Allow logging under Release
EgorBo Jun 3, 2021
2c8cc7f
Improve InlineStrategy.DumpXml
EgorBo Jun 3, 2021
5b86cf9
Bring back JitConfig.JitInlineDumpXml check
EgorBo Jun 3, 2021
d57b654
Introduce DOTNET_JitInlineDumpXmlFile variable
EgorBo Jun 3, 2021
5a5a3e6
Fix FinalizeXml
EgorBo Jun 3, 2021
0157820
Add DefaultPolicyData
EgorBo Jun 3, 2021
ad3aa34
Print all fields of DefaultPolicy
EgorBo Jun 3, 2021
e77c508
Refactor DumpXml for InlinePolicy
EgorBo Jun 3, 2021
1918b6e
Fix CI
EgorBo Jun 3, 2021
8e0425b
Fix XATTR_R8
EgorBo Jun 3, 2021
fe66534
fix all XATTR*
EgorBo Jun 3, 2021
8e982b0
Formatting
EgorBo Jun 3, 2021
acb4abd
Fix XML format (to be the same)
EgorBo Jun 3, 2021
273abdb
Formatting
EgorBo Jun 3, 2021
df735c8
Address feedback
EgorBo Jun 6, 2021
2839fc7
Address feedback
EgorBo Jun 6, 2021
53505b8
Fix "arg is boxed"
EgorBo Jun 6, 2021
4dedb97
Clean up
EgorBo Jun 7, 2021
fc967d4
Add CALEE_ARG_STRUCT_FIELD_ACCESS
EgorBo Jun 7, 2021
7b986fc
Clean up
EgorBo Jun 7, 2021
c2a94a2
Merge branch 'main' of https://github.com/dotnet/runtime into inliner…
EgorBo Jun 7, 2021
4b95db2
Apply suggestions from code review
EgorBo Jun 8, 2021
d986965
Address feedback
EgorBo Jun 8, 2021
29a14a2
Change to "sigInst.methInstCount != 0"
EgorBo Jun 8, 2021
40875b9
use classInstCount to detect generic classes
EgorBo Jun 8, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 38 additions & 31 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18912,40 +18912,47 @@ void Compiler::impMakeDiscretionaryInlineObservations(InlineInfo* pInlineInfo, I
}
}

if ((info.compMethodInfo->args.callConv & CORINFO_CALLCONV_GENERIC) ||
(info.compClassAttr & CORINFO_FLG_SHAREDINST))
{
inlineResult->Note(InlineObservation::CALLEE_GENERIC);
}
else if ((rootCompiler->info.compMethodInfo->args.callConv & CORINFO_CALLCONV_GENERIC) ||
(rootCompiler->info.compClassAttr & CORINFO_FLG_SHAREDINST))
bool callsiteIsGeneric = (rootCompiler->info.compMethodInfo->args.callConv & CORINFO_CALLCONV_GENERIC) ||
(rootCompiler->info.compClassAttr & CORINFO_FLG_SHAREDINST);
EgorBo marked this conversation as resolved.
Show resolved Hide resolved

bool calleeIsGeneric = (info.compMethodInfo->args.callConv & CORINFO_CALLCONV_GENERIC) ||
EgorBo marked this conversation as resolved.
Show resolved Hide resolved
(info.compClassAttr & CORINFO_FLG_SHAREDINST);

if (!callsiteIsGeneric && calleeIsGeneric)
{
inlineResult->Note(InlineObservation::CALLSITE_GENERIC);
inlineResult->Note(InlineObservation::CALLSITE_NONGENERIC_CALLS_GENERIC);
}

// Inspect callee's arguments (and the actual values at the callsite for them)
CORINFO_SIG_INFO sig = info.compMethodInfo->args;
CORINFO_ARG_LIST_HANDLE sigArg = sig.args;

GenTreeCall::Use* argUse = pInlineInfo == nullptr ? nullptr : pInlineInfo->iciCall->AsCall()->gtCallArgs;
for (unsigned i = 0; i < info.compMethodInfo->args.numArgs; i++)
if (pInlineInfo != nullptr)
{
CORINFO_CLASS_HANDLE sigClass;
CorInfoType corType = strip(info.compCompHnd->getArgType(&sig, sigArg, &sigClass));
sigClass = info.compCompHnd->getArgClass(&sig, sigArg);
GenTree* argNode = argUse == nullptr ? nullptr : argUse->GetNode()->gtSkipPutArgType();
// Inspect callee's arguments (and the actual values at the callsite for them)
CORINFO_SIG_INFO sig = info.compMethodInfo->args;
CORINFO_ARG_LIST_HANDLE sigArg = sig.args;

if (corType == CORINFO_TYPE_VALUECLASS)
{
inlineResult->Note(InlineObservation::CALLEE_ARG_STRUCT);
}
else if (corType == CORINFO_TYPE_BYREF)
{
corType = info.compCompHnd->getChildType(sigClass, &sigClass);
}
GenTreeCall::Use* argUse = pInlineInfo->iciCall->AsCall()->gtCallArgs;

if (argNode != nullptr)
for (unsigned i = 0; i < info.compMethodInfo->args.numArgs; i++)
{
assert(argUse != nullptr);

CORINFO_CLASS_HANDLE sigClass;
CorInfoType corType = strip(info.compCompHnd->getArgType(&sig, sigArg, &sigClass));
GenTree* argNode = argUse->GetNode()->gtSkipPutArgType();

if (corType == CORINFO_TYPE_CLASS)
{
sigClass = info.compCompHnd->getArgClass(&sig, sigArg);
}
else if (corType == CORINFO_TYPE_VALUECLASS)
{
inlineResult->Note(InlineObservation::CALLEE_ARG_STRUCT);
}
else if (corType == CORINFO_TYPE_BYREF)
{
sigClass = info.compCompHnd->getArgClass(&sig, sigArg);
corType = info.compCompHnd->getChildType(sigClass, &sigClass);
}

bool isExact = false;
bool isNonNull = false;
CORINFO_CLASS_HANDLE argCls = gtGetClassHandle(argNode, &isExact, &isNonNull);
Expand All @@ -18962,7 +18969,7 @@ void Compiler::impMakeDiscretionaryInlineObservations(InlineInfo* pInlineInfo, I
inlineResult->Note(InlineObservation::CALLSITE_ARG_EXACT_CLS_SIG_IS_NOT);
}
}
// Arg is a reference type in the signature, but a value type was passed.
// Arg is a reference type in the signature and a boxed value type was passed.
else if (isArgValueType && (corType == CORINFO_TYPE_CLASS))
{
inlineResult->Note(InlineObservation::CALLSITE_ARG_BOXED);
Expand All @@ -18973,10 +18980,10 @@ void Compiler::impMakeDiscretionaryInlineObservations(InlineInfo* pInlineInfo, I
{
inlineResult->Note(InlineObservation::CALLSITE_ARG_CONST);
}
}

sigArg = info.compCompHnd->getArgNext(sigArg);
argUse = argUse == nullptr ? nullptr : argUse->GetNext();
sigArg = info.compCompHnd->getArgNext(sigArg);
argUse = argUse->GetNext();
}
}

// Note if the callee's return type is a value type
Expand Down
3 changes: 1 addition & 2 deletions src/coreclr/jit/inline.def
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ INLINE_OBSERVATION(ARG_STRUCT, int, "arg is a struct passed by
INLINE_OBSERVATION(RETURNS_STRUCT, bool, "returns a struct by value", INFORMATION, CALLEE)
INLINE_OBSERVATION(ARG_STRUCT_FIELD_ACCESS, int, "ldfld/stfld over arg (struct)", INFORMATION, CALLEE)
INLINE_OBSERVATION(BINARY_EXRP_WITH_CNS, int, "'X op CNS' pattern", INFORMATION, CALLEE)
INLINE_OBSERVATION(GENERIC, bool, "callee is generic", INFORMATION, CALLEE)
INLINE_OBSERVATION(BEGIN_OPCODE_SCAN, bool, "prepare to look at opcodes", INFORMATION, CALLEE)
INLINE_OBSERVATION(BELOW_ALWAYS_INLINE_SIZE, bool, "below ALWAYS_INLINE size", INFORMATION, CALLEE)
INLINE_OBSERVATION(CLASS_PROMOTABLE, bool, "promotable value class", INFORMATION, CALLEE)
Expand Down Expand Up @@ -173,7 +172,7 @@ INLINE_OBSERVATION(RARE_GC_STRUCT, bool, "rarely called, has gc str

// ------ Call Site Information -------

INLINE_OBSERVATION(GENERIC, bool, "caller is generic", INFORMATION, CALLSITE)
INLINE_OBSERVATION(NONGENERIC_CALLS_GENERIC, bool, "callee is generic and caller is not", INFORMATION, CALLSITE)
INLINE_OBSERVATION(ARG_EXACT_CLS, int, "arg is of an exact class", INFORMATION, CALLSITE)
INLINE_OBSERVATION(ARG_EXACT_CLS_SIG_IS_NOT, int, "arg is more concrete than in sig.", INFORMATION, CALLSITE)
INLINE_OBSERVATION(ARG_CONST, int, "arg is a constant", INFORMATION, CALLSITE)
Expand Down
21 changes: 5 additions & 16 deletions src/coreclr/jit/inlinepolicy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,12 +296,8 @@ void DefaultPolicy::NoteBool(InlineObservation obs, bool value)
m_IsFromValueClass = value;
break;

case InlineObservation::CALLEE_GENERIC:
m_IsCalleeGeneric = value;
break;

case InlineObservation::CALLSITE_GENERIC:
m_IsCallerGeneric = value;
case InlineObservation::CALLSITE_NONGENERIC_CALLS_GENERIC:
m_NonGenericCallsGeneric = value;
break;

case InlineObservation::CALLEE_CLASS_PROMOTABLE:
Expand Down Expand Up @@ -613,8 +609,7 @@ void DefaultPolicy::DumpXml(FILE* file, unsigned indent) const
XATTR_B(m_IsNoReturnKnown);
XATTR_B(m_ReturnsStructByValue);
XATTR_B(m_IsFromValueClass);
XATTR_B(m_IsCalleeGeneric);
XATTR_B(m_IsCallerGeneric);
XATTR_B(m_NonGenericCallsGeneric);
XATTR_B(m_IsCallsiteInNoReturnRegion);
XATTR_B(m_HasProfile);
fprintf(file, " />\n");
Expand Down Expand Up @@ -932,7 +927,6 @@ double DefaultPolicy::DetermineMultiplier()
break;
}


if (m_ReturnsStructByValue)
{
// For structs-passed-by-value we might avoid expensive copy operations if we inline
Expand All @@ -945,15 +939,11 @@ double DefaultPolicy::DetermineMultiplier()
JITDUMP("\n%d arguments are structs passed by value.", m_ArgIsStructByValue);
}

if (m_IsCalleeGeneric && !m_IsCallerGeneric)
if (m_NonGenericCallsGeneric)
{
// Especially, if such a callee has many foldable branches like 'typeof(T) == typeof(T2)'
JITDUMP("\nInline candidate is generic and caller is not.");
}
else if (m_IsCalleeGeneric && m_IsCallerGeneric)
{
JITDUMP("\nInline candidate and its caller are generic.");
}

if (m_IsCallsiteInNoReturnRegion)
{
Expand Down Expand Up @@ -2391,8 +2381,7 @@ void DiscretionaryPolicy::DumpData(FILE* file) const
fprintf(file, ",%u", m_DivByCns);
fprintf(file, ",%u", m_ReturnsStructByValue ? 1 : 0);
fprintf(file, ",%u", m_IsFromValueClass ? 1 : 0);
fprintf(file, ",%u", m_IsCalleeGeneric ? 1 : 0);
fprintf(file, ",%u", m_IsCallerGeneric ? 1 : 0);
fprintf(file, ",%u", m_NonGenericCallsGeneric ? 1 : 0);
fprintf(file, ",%u", m_IsCallsiteInNoReturnRegion ? 1 : 0);
fprintf(file, ",%u", m_HasProfile ? 1 : 0);
}
Expand Down
6 changes: 2 additions & 4 deletions src/coreclr/jit/inlinepolicy.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,7 @@ class DefaultPolicy : public LegalPolicy
, m_IsNoReturnKnown(false)
, m_ReturnsStructByValue(false)
, m_IsFromValueClass(false)
, m_IsCalleeGeneric(false)
, m_IsCallerGeneric(false)
, m_NonGenericCallsGeneric(false)
, m_IsCallsiteInNoReturnRegion(false)
, m_HasProfile(false)
{
Expand Down Expand Up @@ -223,8 +222,7 @@ class DefaultPolicy : public LegalPolicy
bool m_IsNoReturnKnown : 1;
bool m_ReturnsStructByValue : 1;
bool m_IsFromValueClass : 1;
bool m_IsCalleeGeneric : 1;
bool m_IsCallerGeneric : 1;
bool m_NonGenericCallsGeneric : 1;
bool m_IsCallsiteInNoReturnRegion : 1;
bool m_HasProfile : 1;
};
Expand Down