Skip to content

Commit

Permalink
Inliner: new observations (don't impact inlining for now) (#53670)
Browse files Browse the repository at this point in the history
Co-authored-by: Andy Ayers <[email protected]>
  • Loading branch information
EgorBo and AndyAyersMS authored Jun 9, 2021
1 parent fde3692 commit 968532c
Show file tree
Hide file tree
Showing 10 changed files with 667 additions and 40 deletions.
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 @@ -3989,7 +3989,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 @@ -764,7 +764,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 @@ -807,7 +807,7 @@ class FgStack
}

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

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

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

Expand Down Expand Up @@ -871,6 +871,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 @@ -941,6 +947,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 @@ -18868,6 +18895,86 @@ void Compiler::impMakeDiscretionaryInlineObservations(InlineInfo* pInlineInfo, I
}
}

bool callsiteIsGeneric = (rootCompiler->info.compMethodInfo->args.sigInst.methInstCount != 0) ||
(rootCompiler->info.compMethodInfo->args.sigInst.classInstCount != 0);

bool calleeIsGeneric = (info.compMethodInfo->args.sigInst.methInstCount != 0) ||
(info.compMethodInfo->args.sigInst.classInstCount != 0);

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

0 comments on commit 968532c

Please sign in to comment.