diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 7e8a99087a833..200c31cd60524 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -2082,9 +2082,9 @@ void Compiler::compDoComponentUnitTestsOnce() // compGetJitDefaultFill: // // Return Value: -// An unsigned char value used to initizalize memory allocated by the JIT. -// The default value is taken from DOTNET_JitDefaultFill, if is not set -// the value will be 0xdd. When JitStress is active a random value based +// An unsigned char value used to initialize memory allocated by the JIT. +// The default value is taken from DOTNET_JitDefaultFill. If it is not set +// the value will be 0xdd. When JitStress is active a random value based // on the method hash is used. // // Notes: @@ -3597,6 +3597,14 @@ bool Compiler::compStressCompileHelper(compStressArea stressArea, unsigned weigh return false; } + // Does user allow using this STRESS_MODE through the command line? + const WCHAR* strStressModeNamesAllow = JitConfig.JitStressModeNamesAllow(); + if ((strStressModeNamesAllow != nullptr) && + (u16_strstr(strStressModeNamesAllow, s_compStressModeNamesW[stressArea]) == nullptr)) + { + return false; + } + // Does user explicitly set this STRESS_MODE through the command line? const WCHAR* strStressModeNames = JitConfig.JitStressModeNames(); if (strStressModeNames != nullptr) diff --git a/src/coreclr/jit/eeinterface.cpp b/src/coreclr/jit/eeinterface.cpp index d9852afb9e537..0578dee4109ef 100644 --- a/src/coreclr/jit/eeinterface.cpp +++ b/src/coreclr/jit/eeinterface.cpp @@ -614,5 +614,5 @@ void Compiler::eePrintObjectDescription(const char* prefix, CORINFO_OBJECT_HANDL } } - printf("%s '%s'\n", prefix, str); + printf("%s '%s'", prefix, str); } diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index c9f852d94a0ad..df2ed84809ea7 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -1393,7 +1393,7 @@ var_types Compiler::impImportCall(OPCODE opcode, if (origCall->IsVirtual() && (origCall->gtCallType != CT_INDIRECT) && (exactContextHnd != nullptr) && (origCall->gtHandleHistogramProfileCandidateInfo == nullptr)) { - JITDUMP("\nSaving context %p for call [%06u]\n", exactContextHnd, dspTreeID(origCall)); + JITDUMP("\nSaving context %p for call [%06u]\n", dspPtr(exactContextHnd), dspTreeID(origCall)); origCall->gtCallMoreFlags |= GTF_CALL_M_HAS_LATE_DEVIRT_INFO; LateDevirtualizationInfo* const info = new (this, CMK_Inlining) LateDevirtualizationInfo; info->exactContextHnd = exactContextHnd; @@ -8449,8 +8449,9 @@ void Compiler::impCheckCanInline(GenTreeCall* call, return; } #endif + JITDUMP("\nCheckCanInline: fetching method info for inline candidate %s -- context %p\n", - compiler->eeGetMethodName(ftn), pParam->exactContextHnd); + compiler->eeGetMethodName(ftn), compiler->dspPtr(pParam->exactContextHnd)); if (pParam->exactContextHnd == METHOD_BEING_COMPILED_CONTEXT()) { diff --git a/src/coreclr/jit/inlinepolicy.cpp b/src/coreclr/jit/inlinepolicy.cpp index 9a4086dc5af89..d057ccd09ed0d 100644 --- a/src/coreclr/jit/inlinepolicy.cpp +++ b/src/coreclr/jit/inlinepolicy.cpp @@ -1122,7 +1122,7 @@ void RandomPolicy::NoteInt(InlineObservation obs, int value) // methodInfo -- method info for the callee // // Notes: -// The random policy makes random decisions about profitablity. +// The random policy makes random decisions about profitability. // Generally we aspire to inline differently, not necessarily to // inline more. @@ -1131,6 +1131,20 @@ void RandomPolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo) assert(InlDecisionIsCandidate(m_Decision)); assert(m_Observation == InlineObservation::CALLEE_IS_DISCRETIONARY_INLINE); +#if defined(DEBUG) + + // Punt if we're inlining and we've reached the acceptance limit. + int limit = JitConfig.JitInlineLimit(); + unsigned current = m_RootCompiler->m_inlineStrategy->GetInlineCount(); + + if (!m_IsPrejitRoot && (limit >= 0) && (current >= static_cast(limit))) + { + SetFailure(InlineObservation::CALLSITE_OVER_INLINE_LIMIT); + return; + } + +#endif // defined(DEBUG) + // Budget check. const bool overBudget = this->BudgetCheck(); if (overBudget) diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h index 5d6173e7973ed..4bf034439e3e6 100644 --- a/src/coreclr/jit/jitconfigvalues.h +++ b/src/coreclr/jit/jitconfigvalues.h @@ -137,6 +137,8 @@ CONFIG_INTEGER(JitReportFastTailCallDecisions, W("JitReportFastTailCallDecisions CONFIG_INTEGER(JitPInvokeCheckEnabled, W("JITPInvokeCheckEnabled"), 0) CONFIG_INTEGER(JitPInvokeEnabled, W("JITPInvokeEnabled"), 1) +CONFIG_INTEGER(JitHoistLimit, W("JitHoistLimit"), -1) // Specifies the maximum number of hoist candidates to hoist + // Controls verbosity for JitPrintInlinedMethods. Ignored for JitDump where // it's always set. CONFIG_INTEGER(JitPrintInlinedMethodsVerbose, W("JitPrintInlinedMethodsVerboseLevel"), 0) @@ -162,9 +164,7 @@ CONFIG_INTEGER(JitSsaStress, W("JitSsaStress"), 0) // Perturb order of processin CONFIG_INTEGER(JitStackChecks, W("JitStackChecks"), 0) CONFIG_INTEGER(JitStress, W("JitStress"), 0) // Internal Jit stress mode: 0 = no stress, 2 = all stress, other = vary // stress based on a hash of the method and this value -CONFIG_INTEGER(JitStressBBProf, W("JitStressBBProf"), 0) // Internal Jit stress mode -CONFIG_INTEGER(JitStressModeNamesOnly, W("JitStressModeNamesOnly"), 0) // Internal Jit stress: if nonzero, only enable - // stress modes listed in JitStressModeNames +CONFIG_INTEGER(JitStressBBProf, W("JitStressBBProf"), 0) // Internal Jit stress mode CONFIG_INTEGER(JitStressProcedureSplitting, W("JitStressProcedureSplitting"), 0) // Always split after the first basic // block. CONFIG_INTEGER(JitStressRegs, W("JitStressRegs"), 0) @@ -242,12 +242,24 @@ CONFIG_INTEGER(JitDumpFgBlockOrder, W("JitDumpFgBlockOrder"), 0) // 0 == bbNext CONFIG_INTEGER(JitDumpFgMemorySsa, W("JitDumpFgMemorySsa"), 0) // non-zero: show memory phis + SSA/VNs CONFIG_STRING(JitRange, W("JitRange")) -CONFIG_STRING(JitStressModeNames, W("JitStressModeNames")) // Internal Jit stress mode: stress using the given set of - // stress mode names, e.g. STRESS_REGS, STRESS_TAILCALL -CONFIG_STRING(JitStressModeNamesNot, W("JitStressModeNamesNot")) // Internal Jit stress mode: do NOT stress using the - // given set of stress mode names, e.g. STRESS_REGS, - // STRESS_TAILCALL -CONFIG_STRING(JitStressRange, W("JitStressRange")) // Internal Jit stress mode + +// Internal Jit stress mode: stress using the given set of stress mode names, e.g. STRESS_REGS, STRESS_TAILCALL. +// Unless JitStressModeNamesOnly is non-zero, other stress modes from a JitStress setting may also be invoked. +CONFIG_STRING(JitStressModeNames, W("JitStressModeNames")) + +// Internal Jit stress: if nonzero, only enable stress modes listed in JitStressModeNames. +CONFIG_INTEGER(JitStressModeNamesOnly, W("JitStressModeNamesOnly"), 0) + +// Internal Jit stress mode: only allow stress using the given set of stress mode names, e.g. STRESS_REGS, +// STRESS_TAILCALL. Note that JitStress must be enabled first, and then only the mentioned stress modes are allowed +// to be used, at the same percentage weighting as with JitStress -- the stress modes mentioned are NOT +// unconditionally true for a call to `compStressCompile`. This is basically the opposite of JitStressModeNamesNot. +CONFIG_STRING(JitStressModeNamesAllow, W("JitStressModeNamesAllow")) + +// Internal Jit stress mode: do NOT stress using the given set of stress mode names, e.g. STRESS_REGS, STRESS_TAILCALL +CONFIG_STRING(JitStressModeNamesNot, W("JitStressModeNamesNot")) + +CONFIG_STRING(JitStressRange, W("JitStressRange")) // Internal Jit stress mode CONFIG_METHODSET(JitEmitUnitTests, W("JitEmitUnitTests")) // Generate emitter unit tests in the specified functions CONFIG_STRING(JitEmitUnitTestsSections, W("JitEmitUnitTestsSections")) // Generate this set of unit tests @@ -255,7 +267,8 @@ CONFIG_STRING(JitEmitUnitTestsSections, W("JitEmitUnitTestsSections")) // Genera /// JIT Hardware Intrinsics /// CONFIG_INTEGER(EnableIncompleteISAClass, W("EnableIncompleteISAClass"), 0) // Enable testing not-yet-implemented -#endif // defined(DEBUG) + +#endif // defined(DEBUG) CONFIG_METHODSET(JitDisasm, W("JitDisasm")) // Print codegen for given methods CONFIG_INTEGER(JitDisasmTesting, W("JitDisasmTesting"), 0) // Display BEGIN METHOD/END METHOD anchors for disasm testing @@ -389,6 +402,7 @@ CONFIG_INTEGER(JitRLCSEGreedy, W("JitRLCSEGreedy"), 0) CONFIG_INTEGER(JitRLCSEVerbose, W("JitRLCSEVerbose"), 0) #if defined(DEBUG) + // Allow fine-grained controls of CSEs done in a particular method // // Specify method that will respond to the CSEMask. @@ -440,7 +454,7 @@ CONFIG_STRING(JitRLCSEAlpha, W("JitRLCSEAlpha")) // If nonzero, dump candidate feature values CONFIG_INTEGER(JitRLCSECandidateFeatures, W("JitRLCSECandidateFeatures"), 0) -#endif +#endif // DEBUG /// /// JIT @@ -483,6 +497,7 @@ CONFIG_INTEGER(JitNoRngChks, W("JitNoRngChks"), 0) // If 1, don't generate range #endif // defined(FEATURE_ENABLE_NO_RANGE_CHECKS) #if defined(OPT_CONFIG) + CONFIG_INTEGER(JitDoAssertionProp, W("JitDoAssertionProp"), 1) // Perform assertion propagation optimization CONFIG_INTEGER(JitDoCopyProp, W("JitDoCopyProp"), 1) // Perform copy propagation on variables that appear redundant CONFIG_INTEGER(JitDoOptimizeIVs, W("JitDoOptimizeIVs"), 1) // Perform optimization of induction variables @@ -509,7 +524,8 @@ CONFIG_INTEGER(JitDoValueNumber, W("JitDoValueNumber"), 1) // Perform value numb CONFIG_METHODSET(JitOptRepeat, W("JitOptRepeat")) // Runs optimizer multiple times on the method CONFIG_INTEGER(JitOptRepeatCount, W("JitOptRepeatCount"), 2) // Number of times to repeat opts when repeating CONFIG_INTEGER(JitDoIfConversion, W("JitDoIfConversion"), 1) // Perform If conversion -#endif // defined(OPT_CONFIG) + +#endif // defined(OPT_CONFIG) // Max # of MapSelect's considered for a particular top-level invocation. CONFIG_INTEGER(JitVNMapSelBudget, W("JitVNMapSelBudget"), DEFAULT_MAP_SELECT_BUDGET) diff --git a/src/coreclr/jit/optcse.cpp b/src/coreclr/jit/optcse.cpp index cd554f02e5637..b38049c04dddd 100644 --- a/src/coreclr/jit/optcse.cpp +++ b/src/coreclr/jit/optcse.cpp @@ -2190,6 +2190,13 @@ void CSE_HeuristicRandom::ConsiderCandidates() JITDUMPEXEC(m_pCompiler->gtDispTree(candidate.Expr())); JITDUMP("\n"); +#ifdef DEBUG + if (m_pCompiler->optConfigDisableCSE2()) + { + continue; + } +#endif + if (dsc->defExcSetPromise == ValueNumStore::NoVN) { JITDUMP("Abandoned " FMT_CSE " because we had defs with different Exc sets\n", candidate.CseIndex()); @@ -5407,7 +5414,7 @@ bool Compiler::optConfigDisableCSE2() { if (verbose) { - printf(" Disabled by jitNoCSE2 > totalCSEcount\n"); + printf(" Disabled by jitNoCSE2 %d > totalCSEcount %d\n", jitNoCSE2, totalCSEcount); } return true; } diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index a90d5301bccc3..0b9ae08445a1a 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -5187,6 +5187,21 @@ void Compiler::optHoistCandidate(GenTree* tree, return; } +#if defined(DEBUG) + + // Punt if we've reached the hoisting limit. + int limit = JitConfig.JitHoistLimit(); + unsigned current = m_totalHoistedExpressions; // this doesn't include the current candidate yet + + if ((limit >= 0) && (current >= static_cast(limit))) + { + JITDUMP(" ... not hoisting in " FMT_LP ", hoist count %u >= JitHoistLimit %u\n", loop->GetIndex(), current, + static_cast(limit)); + return; + } + +#endif // defined(DEBUG) + // Expression can be hoisted optPerformHoistExpr(tree, treeBb, loop);