diff options
-rw-r--r-- | src/jit/compiler.cpp | 185 | ||||
-rw-r--r-- | src/jit/compiler.h | 20 | ||||
-rw-r--r-- | src/jit/flowgraph.cpp | 10 | ||||
-rw-r--r-- | src/jit/inline.cpp | 55 | ||||
-rw-r--r-- | src/jit/inline.h | 20 | ||||
-rw-r--r-- | src/jit/inlinepolicy.cpp | 116 | ||||
-rw-r--r-- | src/jit/inlinepolicy.h | 16 | ||||
-rw-r--r-- | src/jit/jitconfigvalues.h | 9 | ||||
-rw-r--r-- | src/jit/morph.cpp | 4 |
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 */ |