summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/jit/compiler.cpp185
-rw-r--r--src/jit/compiler.h20
-rw-r--r--src/jit/flowgraph.cpp10
-rw-r--r--src/jit/inline.cpp55
-rw-r--r--src/jit/inline.h20
-rw-r--r--src/jit/inlinepolicy.cpp116
-rw-r--r--src/jit/inlinepolicy.h16
-rw-r--r--src/jit/jitconfigvalues.h9
-rw-r--r--src/jit/morph.cpp4
9 files changed, 273 insertions, 162 deletions
diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp
index 1c3946af7d..21014ce9e5 100644
--- a/src/jit/compiler.cpp
+++ b/src/jit/compiler.cpp
@@ -642,9 +642,12 @@ unsigned Compiler::s_compMethodsCount = 0; // to produce unique label
/* static */
bool Compiler::s_dspMemStats = false;
-bool Compiler::s_inlDumpDataHeader = false;
#endif
+#if defined(DEBUG) || defined(INLINE_DATA)
+bool Compiler::s_inlDumpDataHeader = false;
+#endif // if defined(DEBUG) || defined(INLINE_DATA)
+
#ifndef DEBUGGING_SUPPORT
/* static */
const bool Compiler::Options::compDbgCode = false;
@@ -1265,9 +1268,9 @@ void Compiler::compInit(ArenaAllocator * pAlloc, InlineInfo * inl
// Set the inline info.
impInlineInfo = inlineInfo;
-#ifdef DEBUG
+#if defined(DEBUG) || defined(INLINE_DATA)
inlLastSuccessfulPolicy = nullptr;
-#endif
+#endif // defined(DEBUG) || defined(INLINE_DATA)
eeInfoInitialized = false;
@@ -3969,9 +3972,7 @@ void Compiler::compCompile(void * * methodCodePtr,
pCompJitTimer->Terminate(this, CompTimeSummaryInfo::s_compTimeSummary);
#endif
-#ifdef FEATURE_CLRSQM
- RecordSqmStateAtEndOfCompilation();
-#endif // FEATURE_CLRSQM
+ RecordStateAtEndOfCompilation();
#ifdef FEATURE_TRACELOGGING
compJitTelemetry.NotifyEndOfCompilation();
@@ -4468,6 +4469,79 @@ void Compiler::compCompileFinish()
}
#endif // DEBUG
+#if defined(DEBUG) || defined(INLINE_DATA)
+
+ // Inliner data display
+ if (JitConfig.JitInlineDumpData() != 0)
+ {
+ // Don't dump anything if limiting is on and we didn't reach
+ // the limit while inlining.
+ //
+ // This serves to filter out duplicate data.
+ const int limit = JitConfig.JitInlineLimit();
+
+ if ((limit < 0) || (fgInlinedCount == static_cast<unsigned>(limit)))
+ {
+ // If there weren't any successful inlines (no limit, or
+ // limit=0 case), we won't have a successful policy, so
+ // fake one up.
+ if (inlLastSuccessfulPolicy == nullptr)
+ {
+ assert(limit <= 0);
+ const bool isPrejitRoot = (opts.eeFlags & CORJIT_FLG_PREJIT) != 0;
+ inlLastSuccessfulPolicy = InlinePolicy::GetPolicy(this, isPrejitRoot);
+
+ // Add in a bit of data....
+ const bool isForceInline = (info.compFlags & CORINFO_FLG_FORCEINLINE) != 0;
+ inlLastSuccessfulPolicy->NoteBool(InlineObservation::CALLEE_IS_FORCE_INLINE, isForceInline);
+ inlLastSuccessfulPolicy->NoteInt(InlineObservation::CALLEE_IL_CODE_SIZE, info.compMethodInfo->ILCodeSize);
+ }
+
+ if (!s_inlDumpDataHeader)
+ {
+ if (limit == 0)
+ {
+ fprintf(stderr, "*** Inline Data: Policy=%s JitInlineLimit=%d ***\n",
+ inlLastSuccessfulPolicy->GetName(),
+ limit);
+ fprintf(stderr, "Method,Version,HotSize,ColdSize,JitTime");
+ inlLastSuccessfulPolicy->DumpSchema(stderr);
+ fprintf(stderr, "\n");
+ }
+
+ s_inlDumpDataHeader = true;
+ }
+
+ // We'd really like the method identifier to be unique and
+ // durable across crossgen invocations. Not clear how to
+ // accomplish this, so we'll use the token for now.
+ //
+ // Post processing will have to filter out all data from
+ // methods where the root entry appears multiple times.
+ mdMethodDef currentMethodToken = info.compCompHnd->getMethodDefFromMethod(info.compMethodHnd);
+
+ // Convert time spent jitting into milliseconds
+ unsigned microsecondsSpentJitting = 0;
+ if (m_compCycles > 0)
+ {
+ double countsPerSec = CycleTimer::CyclesPerSecond();
+ double counts = (double) m_compCycles;
+ microsecondsSpentJitting = (unsigned) ((counts / countsPerSec) * 1000 * 1000);
+ }
+
+ fprintf(stderr, "%08X,%u,%u,%u,%u",
+ currentMethodToken,
+ fgInlinedCount,
+ info.compTotalHotCodeSize,
+ info.compTotalColdCodeSize,
+ microsecondsSpentJitting);
+ inlLastSuccessfulPolicy->DumpData(stderr);
+ fprintf(stderr, "\n");
+ }
+ }
+
+#endif // defined(DEBUG) || defined(INLINE_DATA)
+
#ifdef DEBUG
if (opts.dspOrder)
{
@@ -4576,61 +4650,6 @@ void Compiler::compCompileFinish()
printf(""); // in our logic this causes a flush
}
- // Inliner data display
- if (JitConfig.JitInlineDumpData() != 0)
- {
- // Don't dump anything if limiting is on and we didn't reach
- // the limit while inlining.
- //
- // This serves to filter out duplicate data.
- const int limit = JitConfig.JitInlineLimit();
-
- if ((limit < 0) || (fgInlinedCount == static_cast<unsigned>(limit)))
- {
- // If there weren't any successful inlines (no limit, or
- // limit=0 case), we won't have a successful policy, so
- // fake one up.
- if (inlLastSuccessfulPolicy == nullptr)
- {
- assert(limit <= 0);
- const bool isPrejitRoot = (opts.eeFlags & CORJIT_FLG_PREJIT) != 0;
- inlLastSuccessfulPolicy = InlinePolicy::GetPolicy(this, isPrejitRoot);
- }
-
- if (!s_inlDumpDataHeader)
- {
- if (limit == 0)
- {
- printf("*** Inline Data: Policy=%s JitInlineLimit=%d ***\n",
- inlLastSuccessfulPolicy->GetName(),
- limit);
- printf("Method,Version,HotSize,ColdSize,JitTime");
- inlLastSuccessfulPolicy->DumpSchema();
- printf("\n");
- }
-
- s_inlDumpDataHeader = true;
- }
-
- // We'd really like the method identifier to be unique and
- // durable across crossgen invocations. Not clear how to
- // accomplish this, so we'll use the token for now.
- //
- // Post processing will have to filter out all data from
- // methods where the root entry appears multiple times.
- mdMethodDef currentMethodToken = info.compCompHnd->getMethodDefFromMethod(info.compMethodHnd);
-
- printf("%08X,%u,%u,%u,%u",
- currentMethodToken,
- fgInlinedCount,
- info.compTotalHotCodeSize,
- info.compTotalColdCodeSize,
- 0);
- inlLastSuccessfulPolicy->DumpData();
- printf("\n");
- }
- }
-
// Only call _DbgBreakCheck when we are jitting, not when we are ngen-ing
// For ngen the int3 or breakpoint instruction will be right at the
// start of the ngen method and we will stop when we execute it.
@@ -6826,26 +6845,53 @@ void Compiler::PrintPerMethodLoopHoistStats()
}
#endif // LOOP_HOIST_STATS
-#ifdef FEATURE_CLRSQM
-void Compiler::RecordSqmStateAtEndOfInlining()
+//------------------------------------------------------------------------
+// RecordStateAtEndOfInlining: capture timing data (if enabled) after
+// inlining as completed.
+//
+// Note:
+// Records data needed for SQM and inlining data dumps. Should be
+// called after inlining is complete. (We do this after inlining
+// because this marks the last point at which the JIT is likely to
+// cause type-loading and class initialization).
+
+void Compiler::RecordStateAtEndOfInlining()
{
- m_compCyclesAtEndOfInlining;
+#if defined(DEBUG) || defined(INLINE_DATA) || defined(FEATURE_CLRSQM)
+
+ m_compCyclesAtEndOfInlining = 0;
+ m_compTickCountAtEndOfInlining = 0;
bool b = CycleTimer::GetThreadCyclesS(&m_compCyclesAtEndOfInlining);
if (!b) return; // We don't have a thread cycle counter.
m_compTickCountAtEndOfInlining = GetTickCount();
+
+#endif // defined(DEBUG) || defined(INLINE_DATA) || defined(FEATURE_CLRSQM)
}
+//------------------------------------------------------------------------
+// RecordStateAtEndOfCompilation: capture timing data (if enabled) after
+// compilation is completed.
-void Compiler::RecordSqmStateAtEndOfCompilation()
+void Compiler::RecordStateAtEndOfCompilation()
{
+#if defined(DEBUG) || defined(INLINE_DATA) || defined(FEATURE_CLRSQM)
+
+ // Common portion
+ m_compCycles = 0;
unsigned __int64 compCyclesAtEnd;
bool b = CycleTimer::GetThreadCyclesS(&compCyclesAtEnd);
if (!b) return; // We don't have a thread cycle counter.
assert(compCyclesAtEnd >= m_compCyclesAtEndOfInlining);
- unsigned __int64 compCycles = compCyclesAtEnd - m_compCyclesAtEndOfInlining;
- unsigned __int64 mcycles64 = compCycles / ((unsigned __int64)1000000);
- unsigned mcycles = 0;
+ m_compCycles = compCyclesAtEnd - m_compCyclesAtEndOfInlining;
+
+#endif // defined(DEBUG) || defined(INLINE_DATA) || defined(FEATURE_CLRSQM)
+
+#ifdef FEATURE_CLRSQM
+
+ // SQM only portion
+ unsigned __int64 mcycles64 = m_compCycles / ((unsigned __int64)1000000);
+ unsigned mcycles;
if (mcycles64 > UINT32_MAX)
{
mcycles = UINT32_MAX;
@@ -6854,6 +6900,7 @@ void Compiler::RecordSqmStateAtEndOfCompilation()
{
mcycles = (unsigned)mcycles64;
}
+
DWORD ticksAtEnd = GetTickCount();
assert(ticksAtEnd >= m_compTickCountAtEndOfInlining);
DWORD compTicks = ticksAtEnd - m_compTickCountAtEndOfInlining;
@@ -6867,9 +6914,9 @@ void Compiler::RecordSqmStateAtEndOfCompilation()
opts.MinOpts(),
info.compMethodHnd);
}
-};
#endif // FEATURE_CLRSQM
+}
#if FUNC_INFO_LOGGING
// static
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index 1e58ee989d..6fe376902b 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -2526,10 +2526,11 @@ public :
// Get the maximum IL size allowed for an inline
unsigned getImpInlineSize() const { return impInlineSize; }
-#ifdef DEBUG
- unsigned getInlinedCount() const { return fgInlinedCount; }
- InlinePolicy* inlLastSuccessfulPolicy;
-#endif
+#if defined(DEBUG) || defined(INLINE_DATA)
+ unsigned fgInlinedCount; // Number of successful inline expansion of this method.
+ InlinePolicy* inlLastSuccessfulPolicy; // Policy used in last successful inline.
+ static bool s_inlDumpDataHeader; // Print header schema for inline data
+#endif // defined(DEBUG) || defined(INLINE_DATA)
// The Compiler* that is the root of the inlining tree of which "this" is a member.
Compiler* impInlineRoot();
@@ -4697,7 +4698,6 @@ private:
bool gtIsActiveCSE_Candidate(GenTreePtr tree);
#ifdef DEBUG
- unsigned fgInlinedCount; // Number of successful inline expansion of this method.
bool fgPrintInlinedMethods;
#endif
@@ -7570,7 +7570,6 @@ public :
#ifdef DEBUG
static bool s_dspMemStats; // Display per-phase memory statistics for every function
- static bool s_inlDumpDataHeader; // Print header schema for inline data
template<typename T>
T dspPtr(T p)
@@ -8595,18 +8594,21 @@ private:
#endif
inline void EndPhase(Phases phase); // Indicate the end of the given phase.
-#ifdef FEATURE_CLRSQM
+#if defined(DEBUG) || defined(INLINE_DATA) || defined(FEATURE_CLRSQM)
// These variables are associated with maintaining SQM data about compile time.
unsigned __int64 m_compCyclesAtEndOfInlining; // The thread-virtualized cycle count at the end of the inlining phase in the current compilation.
+ unsigned __int64 m_compCycles; // Net cycle count for current compilation
DWORD m_compTickCountAtEndOfInlining; // The result of GetTickCount() (# ms since some epoch marker) at the end of the inlining phase in the current compilation.
+#endif // defined(DEBUG) || defined(INLINE_DATA) || defined(FEATURE_CLRSQM)
// Records the SQM-relevant (cycles and tick count). Should be called after inlining is complete.
// (We do this after inlining because this marks the last point at which the JIT is likely to cause
// type-loading and class initialization).
- void RecordSqmStateAtEndOfInlining();
+ void RecordStateAtEndOfInlining();
// Assumes being called at the end of compilation. Update the SQM state.
- void RecordSqmStateAtEndOfCompilation();
+ void RecordStateAtEndOfCompilation();
+#ifdef FEATURE_CLRSQM
// Does anything SQM related necessary at process shutdown time.
static void ProcessShutdownSQMWork(ICorStaticInfo* statInfo);
#endif // FEATURE_CLRSQM
diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp
index 583a93be2b..d7cac71b51 100644
--- a/src/jit/flowgraph.cpp
+++ b/src/jit/flowgraph.cpp
@@ -29,8 +29,11 @@ void Compiler::fgInit()
fgFirstBBScratch = nullptr;
-#ifdef DEBUG
+#if defined(DEBUG) || defined(INLINE_DATA)
fgInlinedCount = 0;
+#endif // defined(DEBUG) || defined(INLINE_DATA)
+
+#ifdef DEBUG
fgPrintInlinedMethods = JitConfig.JitPrintInlinedMethods() == 1;
#endif // DEBUG
@@ -21971,8 +21974,11 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call,
// Let's insert it to inliner's basic block list.
fgInsertInlineeBlocks(&inlineInfo);
-#ifdef DEBUG
+#if defined(DEBUG) || defined(INLINE_DATA)
++fgInlinedCount;
+#endif // defined(DEBUG) || defined(INLINE_DATA)
+
+#ifdef DEBUG
if (verbose || fgPrintInlinedMethods)
{
diff --git a/src/jit/inline.cpp b/src/jit/inline.cpp
index bb321032e1..81271e5498 100644
--- a/src/jit/inline.cpp
+++ b/src/jit/inline.cpp
@@ -328,13 +328,13 @@ InlineContext::InlineContext()
, m_Offset(BAD_IL_OFFSET)
, m_Code(nullptr)
, m_Observation(InlineObservation::CALLEE_UNUSED_INITIAL)
-#ifdef DEBUG
+#if defined(DEBUG) || defined(INLINE_DATA)
, m_Policy(nullptr)
, m_Callee(nullptr)
, m_TreeID(0)
, m_Ordinal(0)
, m_Success(true)
-#endif
+#endif // defined(DEBUG) || defined(INLINE_DATA)
{
// Empty
}
@@ -357,9 +357,11 @@ InlineContext* InlineContext::NewRoot(Compiler* compiler)
{
InlineContext* rootContext = new (compiler, CMK_Inlining) InlineContext;
-#if defined(DEBUG)
+#if defined(DEBUG) || defined(INLINE_DATA)
+
rootContext->m_Callee = compiler->info.compMethodHnd;
-#endif
+
+#endif // defined(DEBUG) || defined(INLINE_DATA)
return rootContext;
}
@@ -397,17 +399,28 @@ InlineContext* InlineContext::NewSuccess(Compiler* compiler,
calleeContext->m_Child = nullptr;
calleeContext->m_Offset = stmt->AsStmt()->gtStmtILoffsx;
calleeContext->m_Observation = inlineInfo->inlineResult->GetObservation();
-#ifdef DEBUG
+
+#if defined(DEBUG) || defined(INLINE_DATA)
+
calleeContext->m_Policy = inlineInfo->inlineResult->GetPolicy();
calleeContext->m_Callee = inlineInfo->fncHandle;
+ // +1 here since we construct this context when we know the inline
+ // will happen -- but it hasn't actually happened yet, so the count
+ // reflects the number of inlines before this one.
+ calleeContext->m_Ordinal = compiler->fgInlinedCount + 1;
+
+#endif // defined(DEBUG) || defined(INLINE_DATA)
+
+#if defined(DEBUG)
+
calleeContext->m_TreeID = inlineInfo->inlineResult->GetCall()->gtTreeID;
- calleeContext->m_Ordinal = compiler->getInlinedCount();
-#endif
+
+#endif // defined(DEBUG)
return calleeContext;
}
-#ifdef DEBUG
+#if defined(DEBUG) || defined(INLINE_DATA)
//------------------------------------------------------------------------
// NewFailure: construct an InlineContext for a failing inline
@@ -456,8 +469,13 @@ InlineContext* InlineContext::NewFailure(Compiler* compiler,
failedContext->m_Observation = inlineResult->GetObservation();
failedContext->m_Callee = inlineResult->GetCallee();
failedContext->m_Success = false;
+
+#if defined(DEBUG)
+
failedContext->m_TreeID = inlineResult->GetCall()->gtTreeID;
+#endif // defined(DEBUG)
+
return failedContext;
}
@@ -486,7 +504,13 @@ void InlineContext::Dump(Compiler* compiler, int indent)
}
else
{
+
+#if defined(DEBUG)
calleeName = compiler->eeGetMethodFullName(m_Callee);
+#else
+ calleeName = "callee";
+#endif // defined(DEBUG)
+
}
mdMethodDef calleeToken =
@@ -545,13 +569,17 @@ void InlineContext::DumpData(Compiler* compiler, int indent)
m_Sibling->DumpData(compiler, indent);
}
+#if defined(DEBUG)
const char* calleeName = compiler->eeGetMethodFullName(m_Callee);
+#else
+ const char* calleeName = "callee";
+#endif // defined(DEBUG)
if (m_Parent == nullptr)
{
// Root method... cons up a policy so we can display the name
InlinePolicy* policy = InlinePolicy::GetPolicy(compiler, true);
- printf("\nInlines [%u] into \"%s\" [%s]\n", compiler->getInlinedCount(), calleeName, policy->GetName());
+ printf("\nInlines [%u] into \"%s\" [%s]\n", compiler->fgInlinedCount, calleeName, policy->GetName());
}
else if (m_Success)
{
@@ -563,7 +591,7 @@ void InlineContext::DumpData(Compiler* compiler, int indent)
}
printf("%u,\"%s\",\"%s\"", m_Ordinal, inlineReason, calleeName);
- m_Policy->DumpData();
+ m_Policy->DumpData(stdout);
printf("\n");
}
@@ -574,7 +602,7 @@ void InlineContext::DumpData(Compiler* compiler, int indent)
}
}
-#endif // DEBUG
+#endif // defined(DEBUG) || defined(INLINE_DATA)
//------------------------------------------------------------------------
// InlineResult: Construct an InlineResult to evaluate a particular call
@@ -674,7 +702,7 @@ void InlineResult::Report()
m_Reported = true;
-#ifdef DEBUG
+#if defined(DEBUG) || defined(INLINE_DATA)
// Stash a pointer to the latest successful policy for later stats
// reporting.
@@ -683,6 +711,9 @@ void InlineResult::Report()
m_RootCompiler->inlLastSuccessfulPolicy = GetPolicy();
}
+#endif // defined(DEBUG) || defined(INLINE_DATA)
+
+#ifdef DEBUG
const char* callee = nullptr;
// Optionally dump the result
diff --git a/src/jit/inline.h b/src/jit/inline.h
index 679218446b..14a3a8ea0e 100644
--- a/src/jit/inline.h
+++ b/src/jit/inline.h
@@ -245,14 +245,16 @@ public:
// Policy policies
virtual bool PropagateNeverToRuntime() const = 0;
-#ifdef DEBUG
+#if defined(DEBUG) || defined(INLINE_DATA)
+
// Name of the policy
virtual const char* GetName() const = 0;
// Detailed data value dump
- virtual void DumpData() const { }
+ virtual void DumpData(FILE* file) const { }
// Detailed data name dump
- virtual void DumpSchema() const { }
-#endif
+ virtual void DumpSchema(FILE* file) const { }
+
+#endif // defined(DEBUG) || defined(INLINE_DATA)
protected:
@@ -562,7 +564,7 @@ public:
static InlineContext* NewSuccess(Compiler* compiler,
InlineInfo* inlineInfo);
-#ifdef DEBUG
+#if defined(DEBUG) || defined(INLINE_DATA)
// New context for a failing inline
static InlineContext* NewFailure(Compiler * compiler,
@@ -575,7 +577,7 @@ public:
// Dump only the success subtree, with rich data
void DumpData(Compiler* compiler, int indent = 0);
-#endif
+#endif // defined(DEBUG) || defined(INLINE_DATA)
// Get the parent context for this context.
InlineContext* GetParent() const
@@ -602,13 +604,15 @@ private:
BYTE* m_Code; // address of IL buffer for the method
InlineObservation m_Observation; // what lead to this inline
-#ifdef DEBUG
+#if defined(DEBUG) || defined(INLINE_DATA)
+
InlinePolicy* m_Policy; // policy that evaluated this inline
CORINFO_METHOD_HANDLE m_Callee; // handle to the method
unsigned m_TreeID; // ID of the GenTreeCall
unsigned m_Ordinal; // Ordinal number of this inline
bool m_Success; // true if this was a successful inline
-#endif
+
+#endif // defined(DEBUG) || defined(INLINE_DATA)
};
diff --git a/src/jit/inlinepolicy.cpp b/src/jit/inlinepolicy.cpp
index 90564296db..a53b3cd68e 100644
--- a/src/jit/inlinepolicy.cpp
+++ b/src/jit/inlinepolicy.cpp
@@ -39,6 +39,10 @@ InlinePolicy* InlinePolicy::GetPolicy(Compiler* compiler, bool isPrejitRoot)
return new (compiler, CMK_Inlining) RandomPolicy(compiler, isPrejitRoot, seed);
}
+#endif // DEBUG
+
+#if defined(DEBUG) || defined(INLINE_DATA)
+
// Optionally install the DiscretionaryPolicy.
bool useDiscretionaryPolicy = JitConfig.JitInlinePolicyDiscretionary() != 0;
@@ -47,7 +51,7 @@ InlinePolicy* InlinePolicy::GetPolicy(Compiler* compiler, bool isPrejitRoot)
return new (compiler, CMK_Inlining) DiscretionaryPolicy(compiler, isPrejitRoot);
}
-#endif // DEBUG
+#endif // defined(DEBUG) || defined(INLINE_DATA)
// Use the legacy policy
InlinePolicy* policy = new (compiler, CMK_Inlining) LegacyPolicy(compiler, isPrejitRoot);
@@ -1076,6 +1080,10 @@ void RandomPolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo)
}
}
+#endif // DEBUG
+
+#if defined(DEBUG) || defined(INLINE_DATA)
+
//------------------------------------------------------------------------
// DiscretionaryPolicy: construct a new DiscretionaryPolicy
//
@@ -1223,7 +1231,7 @@ void DiscretionaryPolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo
if (!m_IsPrejitRoot &&
(limit >= 0) &&
- (m_RootCompiler->getInlinedCount() >= static_cast<unsigned>(limit)))
+ (m_RootCompiler->fgInlinedCount >= static_cast<unsigned>(limit)))
{
SetFailure(InlineObservation::CALLSITE_OVER_INLINE_LIMIT);
return;
@@ -1241,63 +1249,69 @@ void DiscretionaryPolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo
//------------------------------------------------------------------------
// DumpSchema: dump names for all the supporting data for the
// inline decision in CSV format.
+//
+// Arguments:
+// file -- file to write to
-void DiscretionaryPolicy::DumpSchema() const
+void DiscretionaryPolicy::DumpSchema(FILE* file) const
{
- printf(",Codesize");
- printf(",CallsiteFrequency");
- printf(",InstructionCount");
- printf(",LoadStoreCount");
- printf(",Depth");
- printf(",BlockCount");
- printf(",Maxstack");
- printf(",ArgCount");
- printf(",LocalCount");
- printf(",ReturnType");
- printf(",ThrowCount");
- printf(",CallCount");
- printf(",IsForceInline");
- printf(",IsInstanceCtor");
- printf(",IsFromPromotableValueClass");
- printf(",HasSimd");
- printf(",LooksLikeWrapperMethod");
- printf(",ArgFeedsConstantTest");
- printf(",IsMostlyLoadStore");
- printf(",ArgFeedsRangeCheck");
- printf(",ConstantFeedsConstantTest");
- printf(",CalleeNativeSizeEstimate");
- printf(",CallsiteNativeSizeEstimate");
+ fprintf(file, ",ILSize");
+ fprintf(file, ",CallsiteFrequency");
+ fprintf(file, ",InstructionCount");
+ fprintf(file, ",LoadStoreCount");
+ fprintf(file, ",Depth");
+ fprintf(file, ",BlockCount");
+ fprintf(file, ",Maxstack");
+ fprintf(file, ",ArgCount");
+ fprintf(file, ",LocalCount");
+ fprintf(file, ",ReturnType");
+ fprintf(file, ",ThrowCount");
+ fprintf(file, ",CallCount");
+ fprintf(file, ",IsForceInline");
+ fprintf(file, ",IsInstanceCtor");
+ fprintf(file, ",IsFromPromotableValueClass");
+ fprintf(file, ",HasSimd");
+ fprintf(file, ",LooksLikeWrapperMethod");
+ fprintf(file, ",ArgFeedsConstantTest");
+ fprintf(file, ",IsMostlyLoadStore");
+ fprintf(file, ",ArgFeedsRangeCheck");
+ fprintf(file, ",ConstantFeedsConstantTest");
+ fprintf(file, ",CalleeNativeSizeEstimate");
+ fprintf(file, ",CallsiteNativeSizeEstimate");
}
//------------------------------------------------------------------------
// DumpData: dump all the supporting data for the inline decision
// in CSV format.
+//
+// Arguments:
+// file -- file to write to
-void DiscretionaryPolicy::DumpData() const
+void DiscretionaryPolicy::DumpData(FILE* file) const
{
- printf(",%u", m_CodeSize);
- printf(",%u", m_CallsiteFrequency);
- printf(",%u", m_InstructionCount);
- printf(",%u", m_LoadStoreCount);
- printf(",%u", m_Depth);
- printf(",%u", m_BlockCount);
- printf(",%u", m_Maxstack);
- printf(",%u", m_ArgCount);
- printf(",%u", m_LocalCount);
- printf(",%u", m_ReturnType);
- printf(",%u", m_ThrowCount);
- printf(",%u", m_CallCount);
- printf(",%u", m_IsForceInline ? 1 : 0);
- printf(",%u", m_IsInstanceCtor ? 1 : 0);
- printf(",%u", m_IsFromPromotableValueClass ? 1 : 0);
- printf(",%u", m_HasSimd ? 1 : 0);
- printf(",%u", m_LooksLikeWrapperMethod ? 1 : 0);
- printf(",%u", m_ArgFeedsConstantTest ? 1 : 0);
- printf(",%u", m_MethodIsMostlyLoadStore ? 1 : 0);
- printf(",%u", m_ArgFeedsRangeCheck ? 1 : 0);
- printf(",%u", m_ConstantFeedsConstantTest ? 1 : 0);
- printf(",%d", m_CalleeNativeSizeEstimate);
- printf(",%d", m_CallsiteNativeSizeEstimate);
+ fprintf(file, ",%u", m_CodeSize);
+ fprintf(file, ",%u", m_CallsiteFrequency);
+ fprintf(file, ",%u", m_InstructionCount);
+ fprintf(file, ",%u", m_LoadStoreCount);
+ fprintf(file, ",%u", m_Depth);
+ fprintf(file, ",%u", m_BlockCount);
+ fprintf(file, ",%u", m_Maxstack);
+ fprintf(file, ",%u", m_ArgCount);
+ fprintf(file, ",%u", m_LocalCount);
+ fprintf(file, ",%u", m_ReturnType);
+ fprintf(file, ",%u", m_ThrowCount);
+ fprintf(file, ",%u", m_CallCount);
+ fprintf(file, ",%u", m_IsForceInline ? 1 : 0);
+ fprintf(file, ",%u", m_IsInstanceCtor ? 1 : 0);
+ fprintf(file, ",%u", m_IsFromPromotableValueClass ? 1 : 0);
+ fprintf(file, ",%u", m_HasSimd ? 1 : 0);
+ fprintf(file, ",%u", m_LooksLikeWrapperMethod ? 1 : 0);
+ fprintf(file, ",%u", m_ArgFeedsConstantTest ? 1 : 0);
+ fprintf(file, ",%u", m_MethodIsMostlyLoadStore ? 1 : 0);
+ fprintf(file, ",%u", m_ArgFeedsRangeCheck ? 1 : 0);
+ fprintf(file, ",%u", m_ConstantFeedsConstantTest ? 1 : 0);
+ fprintf(file, ",%d", m_CalleeNativeSizeEstimate);
+ fprintf(file, ",%d", m_CallsiteNativeSizeEstimate);
}
-#endif // DEBUG
+#endif // defined(DEBUG) || defined(INLINE_DATA)
diff --git a/src/jit/inlinepolicy.h b/src/jit/inlinepolicy.h
index 99e0c05c01..13673bcc3e 100644
--- a/src/jit/inlinepolicy.h
+++ b/src/jit/inlinepolicy.h
@@ -77,9 +77,11 @@ public:
// Policy policies
bool PropagateNeverToRuntime() const override { return true; }
-#ifdef DEBUG
+#if defined(DEBUG) || defined(INLINE_DATA)
+
const char* GetName() const override { return "LegacyPolicy"; }
-#endif
+
+#endif // (DEBUG) || defined(INLINE_DATA)
protected:
@@ -159,6 +161,10 @@ private:
bool m_IsForceInlineKnown :1;
};
+#endif // DEBUG
+
+#if defined(DEBUG) || defined(INLINE_DATA)
+
// DiscretionaryPolicy is a variant of the legacy policy. It differs
// in that there is no ALWAYS_INLINE class, there is no IL size limit,
// and in prejit mode, discretionary failures do not set the "NEVER"
@@ -184,8 +190,8 @@ public:
void DetermineProfitability(CORINFO_METHOD_INFO* methodInfo) override;
// Externalize data
- void DumpData() const override;
- void DumpSchema() const override;
+ void DumpData(FILE* file) const override;
+ void DumpSchema(FILE* file) const override;
// Miscellaneous
const char* GetName() const override { return "DiscretionaryPolicy"; }
@@ -202,6 +208,6 @@ private:
unsigned m_CallCount;
};
-#endif // DEBUG
+#endif // defined(DEBUG) || defined(INLINE_DATA)
#endif // _INLINE_POLICY_H_
diff --git a/src/jit/jitconfigvalues.h b/src/jit/jitconfigvalues.h
index b5be9fd8a0..87330c1169 100644
--- a/src/jit/jitconfigvalues.h
+++ b/src/jit/jitconfigvalues.h
@@ -55,9 +55,6 @@ CONFIG_INTEGER(JitHashDump, W("JitHashDump"), -1) // Same as JitDump, but for a
CONFIG_INTEGER(JitHashDumpIR, W("JitHashDumpIR"), -1) // Same as JitDumpIR, but for a method hash
CONFIG_INTEGER(JitHashHalt, W("JitHashHalt"), -1) // Same as JitHalt, but for a method hash
CONFIG_INTEGER(JitInlineAdditionalMultiplier, W("JitInlineAdditionalMultiplier"), 0)
-CONFIG_INTEGER(JitInlineDumpData, W("JitInlineDumpData"), 0)
-CONFIG_INTEGER(JitInlineLimit, W("JitInlineLimit"), -1)
-CONFIG_INTEGER(JitInlinePolicyDiscretionary, W("JitInlinePolicyDiscretionary"), 0)
CONFIG_INTEGER(JitInlinePrintStats, W("JitInlinePrintStats"), 0)
CONFIG_INTEGER(JitInlineSize, W("JITInlineSize"), DEFAULT_MAX_INLINE_SIZE)
CONFIG_INTEGER(JitLargeBranches, W("JitLargeBranches"), 0) // Force using the largest conditional branch format
@@ -192,6 +189,12 @@ CONFIG_STRING(JitFuncInfoFile, W("JitFuncInfoLogFile")) // If set, gather JIT fu
CONFIG_STRING(JitTimeLogCsv, W("JitTimeLogCsv")) // If set, gather JIT throughput data and write to a CSV file. This mode must be used in internal retail builds.
CONFIG_STRING(TailCallOpt, W("TailCallOpt"))
+#if defined(DEBUG) || defined(INLINE_DATA)
+CONFIG_INTEGER(JitInlineDumpData, W("JitInlineDumpData"), 0)
+CONFIG_INTEGER(JitInlineLimit, W("JitInlineLimit"), -1)
+CONFIG_INTEGER(JitInlinePolicyDiscretionary, W("JitInlinePolicyDiscretionary"), 0)
+#endif // defined(DEBUG) || defined(INLINE_DATA)
+
#undef CONFIG_INTEGER
#undef CONFIG_STRING
#undef CONFIG_METHODSET
diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp
index fb9585a38c..e163c7e860 100644
--- a/src/jit/morph.cpp
+++ b/src/jit/morph.cpp
@@ -15084,9 +15084,7 @@ void Compiler::fgMorph()
DBEXEC(VERBOSE, fgDispBasicBlocks(true));
#endif
-#ifdef FEATURE_CLRSQM
- RecordSqmStateAtEndOfInlining(); // Record "start" values for post-inlining cycles and elapsed time.
-#endif // FEATURE_CLRSQM
+ RecordStateAtEndOfInlining(); // Record "start" values for post-inlining cycles and elapsed time.
#ifdef DEBUG
/* Inliner could add basic blocks. Check that the flowgraph data is up-to-date */