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 27 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
33 changes: 31 additions & 2 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1466,7 +1466,19 @@ void Compiler::compShutdown()

#if defined(DEBUG) || defined(INLINE_DATA)
// Finish reading and/or writing inline xml
InlineStrategy::FinalizeXml();
if (JitConfig.JitInlineDumpXmlFile() != nullptr)
{
FILE* file = _wfopen(JitConfig.JitInlineDumpXmlFile(), W("a"));
if (file != nullptr)
{
InlineStrategy::FinalizeXml(file);
fclose(file);
}
else
{
InlineStrategy::FinalizeXml();
}
}
#endif // defined(DEBUG) || defined(INLINE_DATA)

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

m_inlineStrategy->DumpData();
m_inlineStrategy->DumpXml();

if (JitConfig.JitInlineDumpXmlFile() != nullptr)
{
FILE* file = _wfopen(JitConfig.JitInlineDumpXmlFile(), W("a"));
if (file != nullptr)
{
m_inlineStrategy->DumpXml(file);
fclose(file);
}
else
{
m_inlineStrategy->DumpXml();
}
}
else
{
m_inlineStrategy->DumpXml();
}

#endif

Expand Down
5 changes: 4 additions & 1 deletion src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -3988,7 +3988,10 @@ class Compiler

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

int impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken, const BYTE* codeAddr, const BYTE* codeEndp);
int impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken,
const BYTE* codeAddr,
const BYTE* codeEndp,
bool makeInlineObservation = false);
void impImportAndPushBox(CORINFO_RESOLVED_TOKEN* pResolvedToken);

void impImportNewObjArray(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_CALL_INFO* pCallInfo);
Expand Down
42 changes: 37 additions & 5 deletions src/coreclr/jit/fgbasic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,7 @@ class FgStack
}
void PushArgument(unsigned arg)
{
Push(SLOT_ARGUMENT + arg);
Push(static_cast<FgSlot>(SLOT_ARGUMENT + arg));
}
unsigned GetSlot0() const
{
Expand Down Expand Up @@ -814,7 +814,7 @@ class FgStack
}

private:
enum
enum FgSlot
{
SLOT_INVALID = UINT_MAX,
SLOT_UNKNOWN = 0,
Expand All @@ -823,7 +823,7 @@ class FgStack
SLOT_ARGUMENT = 3
};

void Push(int type)
void Push(FgSlot type)
{
switch (depth)
{
Expand All @@ -840,8 +840,8 @@ class FgStack
}
}

unsigned slot0;
unsigned slot1;
FgSlot slot0;
FgSlot slot1;
unsigned depth;
};

Expand Down Expand Up @@ -878,6 +878,12 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
compInlineResult->Note(InlineObservation::CALLSITE_IN_TRY_REGION);
}

// Determine if the call site is in a no-return block
if (isInlining && (impInlineInfo->iciBlock->bbJumpKind == BBJ_THROW))
{
compInlineResult->Note(InlineObservation::CALLSITE_IN_NORETURN_REGION);
}

// Determine if the call site is in a loop.
if (isInlining && ((impInlineInfo->iciBlock->bbFlags & BBF_BACKWARD_JUMP) != 0))
{
Expand Down Expand Up @@ -948,6 +954,32 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
BADCODE3("Illegal opcode", ": %02X", (int)opcode);
}

case CEE_THROW:
{
if (makeInlineObservations)
{
compInlineResult->Note(InlineObservation::CALLEE_THROW_BLOCK);
}
break;
}

case CEE_BOX:
{
if (makeInlineObservations)
{
int toSkip = impBoxPatternMatch(nullptr, codeAddr + sz, codeEndp, true);
if (toSkip > 0)
{
// toSkip > 0 means we most likely will hit a pattern (e.g. box+isinst+brtrue) that
// will be folded into a const

// TODO: uncomment later
// codeAddr += toSkip;
}
}
break;
}

case CEE_CALL:
case CEE_CALLVIRT:
{
Expand Down
109 changes: 108 additions & 1 deletion src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6442,7 +6442,10 @@ GenTree* Compiler::impImportLdvirtftn(GenTree* thisPtr,
// pResolvedToken is known to be a value type; ref type boxing
// is handled in the CEE_BOX clause.

int Compiler::impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken, const BYTE* codeAddr, const BYTE* codeEndp)
int Compiler::impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken,
const BYTE* codeAddr,
const BYTE* codeEndp,
bool makeInlineObservation)
{
if (codeAddr >= codeEndp)
{
Expand All @@ -6455,6 +6458,12 @@ int Compiler::impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken, const B
// box + unbox.any
if (codeAddr + 1 + sizeof(mdToken) <= codeEndp)
{
if (makeInlineObservation)
{
compInlineResult->Note(InlineObservation::CALLEE_FOLDABLE_BOX);
return 1 + sizeof(mdToken);
}

CORINFO_RESOLVED_TOKEN unboxResolvedToken;

impResolveToken(codeAddr + 1, &unboxResolvedToken, CORINFO_TOKENKIND_Class);
Expand All @@ -6480,6 +6489,12 @@ int Compiler::impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken, const B
// box + br_true/false
if ((codeAddr + ((codeAddr[0] >= CEE_BRFALSE) ? 5 : 2)) <= codeEndp)
{
if (makeInlineObservation)
{
compInlineResult->Note(InlineObservation::CALLEE_FOLDABLE_BOX);
return 0;
}

GenTree* const treeToBox = impStackTop().val;
bool canOptimize = true;
GenTree* treeToNullcheck = nullptr;
Expand Down Expand Up @@ -6542,6 +6557,12 @@ int Compiler::impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken, const B
case CEE_BRFALSE_S:
if ((nextCodeAddr + ((nextCodeAddr[0] >= CEE_BRFALSE) ? 5 : 2)) <= codeEndp)
{
if (makeInlineObservation)
{
compInlineResult->Note(InlineObservation::CALLEE_FOLDABLE_BOX);
return 1 + sizeof(mdToken);
}

if (!(impStackTop().val->gtFlags & GTF_SIDE_EFFECT))
{
CorInfoHelpFunc boxHelper = info.compCompHnd->getBoxHelper(pResolvedToken->hClass);
Expand Down Expand Up @@ -6618,6 +6639,12 @@ int Compiler::impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken, const B
case CEE_UNBOX_ANY:
if ((nextCodeAddr + 1 + sizeof(mdToken)) <= codeEndp)
{
if (makeInlineObservation)
{
compInlineResult->Note(InlineObservation::CALLEE_FOLDABLE_BOX);
return 2 + sizeof(mdToken) * 2;
}

// See if the resolved tokens in box, isinst and unbox.any describe types that are equal.
CORINFO_RESOLVED_TOKEN isinstResolvedToken = {};
impResolveToken(codeAddr + 1, &isinstResolvedToken, CORINFO_TOKENKIND_Class);
Expand Down Expand Up @@ -18885,6 +18912,86 @@ void Compiler::impMakeDiscretionaryInlineObservations(InlineInfo* pInlineInfo, I
}
}

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_NONGENERIC_CALLS_GENERIC);
}

if (pInlineInfo != nullptr)
{
// 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->iciCall->AsCall()->gtCallArgs;

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);
if (argCls != nullptr)
{
const bool isArgValueType = eeIsValueClass(argCls);
// Exact class of the arg is known
if (isExact && !isArgValueType)
{
inlineResult->Note(InlineObservation::CALLSITE_ARG_EXACT_CLS);
if ((argCls != sigClass) && (sigClass != nullptr))
{
// .. but the signature accepts a less concrete type.
inlineResult->Note(InlineObservation::CALLSITE_ARG_EXACT_CLS_SIG_IS_NOT);
}
}
// 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);
}
}

if (argNode->OperIsConst())
{
inlineResult->Note(InlineObservation::CALLSITE_ARG_CONST);
}

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

// Note if the callee's return type is a value type
if (info.compMethodInfo->args.retType == CORINFO_TYPE_VALUECLASS)
{
inlineResult->Note(InlineObservation::CALLEE_RETURNS_STRUCT);
}

// Note if the callee's class is a promotable struct
if ((info.compClassAttr & CORINFO_FLG_VALUECLASS) != 0)
{
Expand Down
Loading