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

PGO: Add new tiers #70941

Merged
merged 64 commits into from
Oct 26, 2022
Merged
Show file tree
Hide file tree
Changes from 58 commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
07de069
R2R -> InstrumentedTier0 for hot R2R methods
EgorBo Jun 23, 2022
a7bbfaf
Merge branch 'main' of github.com:dotnet/runtime into tier0instrumented
EgorBo Jun 23, 2022
4b4967b
Oops, it turns out that I didn't properly patch re-used callcountingstub
EgorBo Jun 24, 2022
1392368
remove TieredPGO
EgorBo Jun 24, 2022
1a41355
fix bug in the importer
EgorBo Jun 24, 2022
4828f3e
Add ability to instrument optimized code
EgorBo Jun 24, 2022
1fa264b
fix 32bit
EgorBo Jun 24, 2022
71928f3
fix ret type
EgorBo Jun 24, 2022
127b7d8
Clean up
EgorBo Jun 24, 2022
2cee8a9
Merge branch 'main' of github.com:dotnet/runtime into tier0instrumented
EgorBo Jun 24, 2022
911af8a
Clean up
EgorBo Jun 25, 2022
0316842
test fix
EgorBo Jun 26, 2022
2022e68
test2
EgorBo Jun 26, 2022
246dd95
Merge branch 'main' of github.com:dotnet/runtime into new-tier
EgorBo Jul 14, 2022
3a718af
Address feedback
EgorBo Jul 15, 2022
41733fe
Don't re-use callcountingstubs for now
EgorBo Jul 15, 2022
21c8f6e
Clean up
EgorBo Jul 15, 2022
f37012d
Address feedback
EgorBo Jul 15, 2022
db9c71d
Address feedback
EgorBo Jul 15, 2022
59b2bc9
Add docs
EgorBo Jul 15, 2022
ca5c347
Enable other strategies
EgorBo Jul 16, 2022
a6318a0
Clean up
EgorBo Jul 16, 2022
f75e289
Fix GetInitialOptimizationTier
EgorBo Jul 16, 2022
e9e12ea
Enable optimized Instrumentations
EgorBo Jul 16, 2022
81496c4
Update diagram
EgorBo Jul 16, 2022
be329a1
Fix assert
EgorBo Jul 16, 2022
48e375e
Update
EgorBo Jul 16, 2022
1ac3e19
Add test
EgorBo Jul 16, 2022
f6b457a
Update clrconfigvalues.h
EgorBo Jul 17, 2022
7b9e5d4
Merge branch 'main' of github.com:dotnet/runtime into new-tier
EgorBo Jul 17, 2022
cbddf5b
Update clrconfigvalues.h
EgorBo Jul 17, 2022
9345815
Update clrconfigvalues.h
EgorBo Jul 17, 2022
86523e7
Merge branch 'new-tier' of github.com:EgorBo/runtime-1 into new-tier
EgorBo Aug 6, 2022
6a0c05c
Merge branch 'main' of github.com:dotnet/runtime into new-tier
EgorBo Aug 6, 2022
a073ed7
Resolve conflicts, address feedback
EgorBo Aug 6, 2022
75da822
Apply suggestions from code review
EgorBo Aug 6, 2022
e83eb68
Remove InstrumentedTiers_strat4.csproj
EgorBo Aug 6, 2022
b1f4d2e
Address feedback
EgorBo Aug 6, 2022
acdce3d
Merge branch 'new-tier' of github.com:EgorBo/runtime-1 into new-tier
EgorBo Aug 6, 2022
27f7228
update DynamicPgo-InstrumentedTiers.md
EgorBo Aug 6, 2022
2e478c0
Clean up
EgorBo Aug 6, 2022
557ec0c
Clean up
EgorBo Aug 6, 2022
48cf945
clean up
EgorBo Aug 6, 2022
ca491a0
Rename arg in AsyncPromoteToTier1
EgorBo Aug 6, 2022
25bddf0
Address feedback
EgorBo Aug 6, 2022
f777274
Address feedback
EgorBo Aug 6, 2022
13e1211
Address feedback
EgorBo Aug 7, 2022
15c0e2d
Merge branch 'main' of github.com:dotnet/runtime into new-tier
EgorBo Aug 7, 2022
3d88252
Fix issues found during testing
EgorBo Aug 7, 2022
60a77e5
Merge branch 'main' of github.com:dotnet/runtime into new-tier
EgorBo Oct 13, 2022
df19c68
Simplify PR, get rid of strategies
EgorBo Oct 14, 2022
f46679c
Enable TieredPGO_InstrumentOnlyHotCode by default
EgorBo Oct 14, 2022
4d77f85
Merge branch 'main' of github.com:dotnet/runtime into new-tier
EgorBo Oct 17, 2022
c9bd079
Fix an assert in optimized instrumented tier
EgorBo Oct 18, 2022
d3f205b
fix osr tests
EgorBo Oct 18, 2022
ef4ae58
Update docs
EgorBo Oct 18, 2022
7fd0749
Update DynamicPgo-InstrumentedTiers.md
EgorBo Oct 18, 2022
c4395f8
Address feedback
EgorBo Oct 18, 2022
7fbcf17
Merge branch 'main' of github.com:dotnet/runtime into new-tier
EgorBo Oct 22, 2022
a183996
Address Andy's feedback
EgorBo Oct 22, 2022
ff471e1
Disable edge-profiling with a comment
EgorBo Oct 22, 2022
b202b9f
fix assert
EgorBo Oct 22, 2022
64eb6df
Update docs/design/features/DynamicPgo-InstrumentedTiers.md
EgorBo Oct 24, 2022
07339dc
Fix "mb" in the doc, add one more example to the "perf impact" section
EgorBo Oct 25, 2022
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
670 changes: 670 additions & 0 deletions docs/design/features/DynamicPgo-InstrumentedTiers.md

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions docs/design/features/DynamicPgo.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,9 @@ If we confidently could identify the top N% of methods (say 5%) then one could i
R2R methods bypass Tier0 and so don't get instrumentation in the current TieredPGO prototype. We probably don't want to instrument the code in the R2R image. And many of these R2R methods are key framework methods that are important for performance. So we need to find a way to get data for these methods.

There are a few basic ideas:
* Leverage IBC. If there is IBC data in the R2R image then we can make that data available to the JIT. It may not be as relevant as in-process collected data, but it's quite likely better than synthetic data or no data.
* Sampled instrumentation for R2R methods. Produce an instrumented version and run it every so often before the method gets promoted to Tier1. This may be costly, especially if we have to use unoptimized methods for instrumentation, as we'll do quite a bit of extra jitting.
* Make R2R methods go through Tier0 on their way to Tier1. Likely introduces an unacceptable perf hit.
1) Leverage IBC. If there is IBC data in the R2R image then we can make that data available to the JIT. It may not be as relevant as in-process collected data, but it's quite likely better than synthetic data or no data.
2) Sampled instrumentation for R2R methods. Produce an instrumented version and run it every so often before the method gets promoted to Tier1. This may be costly, especially if we have to use unoptimized methods for instrumentation, as we'll do quite a bit of extra jitting.
3) Make R2R methods go through a separate instrumentation tier on their way to Tier1, see [DynamicPgo-InstrumentedTiers.md](DynamicPgo-InstrumentedTiers.md) prototype.

#### Dynamic PGO, QuickJitForLoops, OSR

Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/debug/daccess/request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1112,6 +1112,12 @@ HRESULT ClrDataAccess::GetTieredVersions(
case NativeCodeVersion::OptimizationTierOptimized:
nativeCodeAddrs[count].OptimizationTier = DacpTieredVersionData::OptimizationTier_Optimized;
break;
case NativeCodeVersion::OptimizationTierInstrumented:
nativeCodeAddrs[count].OptimizationTier = DacpTieredVersionData::OptimizationTier_InstrumentedTier;
break;
case NativeCodeVersion::OptimizationTierInstrumentedOptimized:
nativeCodeAddrs[count].OptimizationTier = DacpTieredVersionData::OptimizationTier_InstrumentedTierOptimized;
break;
}
}
else if (pMD->IsJitOptimizationDisabled())
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/inc/clrconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,12 @@ RETAIL_CONFIG_STRING_INFO(INTERNAL_PGODataPath, W("PGODataPath"), "Read/Write PG
RETAIL_CONFIG_DWORD_INFO(INTERNAL_ReadPGOData, W("ReadPGOData"), 0, "Read PGO data")
RETAIL_CONFIG_DWORD_INFO(INTERNAL_WritePGOData, W("WritePGOData"), 0, "Write PGO data")
RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TieredPGO, W("TieredPGO"), 0, "Instrument Tier0 code and make counts available to Tier1")

// TieredPGO_InstrumentOnlyHotCode values:
//
// 0) Instrument all IL-only code, R2R'd code is never instrumented
// 1) Instrument only hot IL-only and hot R2R code (use optimizations in the instrumented tier for hot R2R and no optimizations for hot IL-only)
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TieredPGO_InstrumentOnlyHotCode, W("TieredPGO_InstrumentOnlyHotCode"), 1, "Strategy for TieredPGO, see comments in clrconfigvalues.h")
#endif

///
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/inc/dacprivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,8 @@ struct MSLAYOUT DacpTieredVersionData
OptimizationTier_OptimizedTier1,
OptimizationTier_ReadyToRun,
OptimizationTier_OptimizedTier1OSR,
OptimizationTier_InstrumentedTier,
EgorBo marked this conversation as resolved.
Show resolved Hide resolved
OptimizationTier_InstrumentedTierOptimized,
};

CLRDATA_ADDRESS NativeCodeAddr;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4095,7 +4095,7 @@ const char* Compiler::compGetTieringName(bool wantShortName) const
}
else if (tier1)
{
if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_OSR))
if (opts.IsOSR())
EgorBo marked this conversation as resolved.
Show resolved Hide resolved
{
return instrumenting ? "Instrumented Tier1-OSR" : "Tier1-OSR";
}
Expand Down
10 changes: 10 additions & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -9184,6 +9184,16 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
}
#endif

bool IsInstrumented() const
{
return jitFlags->IsSet(JitFlags::JIT_FLAG_BBINSTR);
}

bool IsInstrumentedOptimized() const
{
return IsInstrumented() && jitFlags->IsSet(JitFlags::JIT_FLAG_TIER1);
}

// true if we should use the PINVOKE_{BEGIN,END} helpers instead of generating
// PInvoke transitions inline. Normally used by R2R, but also used when generating a reverse pinvoke frame, as
// the current logic for frame setup initializes and pushes
Expand Down
25 changes: 5 additions & 20 deletions src/coreclr/jit/fginline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,8 @@ class SubstitutePlaceholdersAndDevirtualizeWalker : public GenTreeVisitor<Substi
{
JITDUMP(" ... found foldable jtrue at [%06u] in " FMT_BB "\n", m_compiler->dspTreeID(tree),
block->bbNum);
noway_assert((block->bbNext->countOfInEdges() > 0) && (block->bbJumpDest->countOfInEdges() > 0));

noway_assert(!m_compiler->fgComputePredsDone);

// We have a constant operand, and should have the all clear to optimize.
// Update side effects on the tree, assert there aren't any, and bash to nop.
Expand All @@ -538,36 +539,20 @@ class SubstitutePlaceholdersAndDevirtualizeWalker : public GenTreeVisitor<Substi
tree->gtBashToNOP();
m_madeChanges = true;

BasicBlock* bNotTaken = nullptr;

if (condTree->AsIntCon()->gtIconVal != 0)
if (!condTree->IsIntegralConst(0))
{
block->bbJumpKind = BBJ_ALWAYS;
bNotTaken = block->bbNext;
}
else
{
block->bbJumpKind = BBJ_NONE;
bNotTaken = block->bbJumpDest;
}

m_compiler->fgRemoveRefPred(bNotTaken, block);

// If that was the last ref, a subsequent flow-opt pass
// will clean up the now-unreachable bNotTaken, and any
// other transitively unreachable blocks.
if (bNotTaken->bbRefs == 0)
{
JITDUMP("... it looks like " FMT_BB " is now unreachable!\n", bNotTaken->bbNum);
}
}
}
else
{
const var_types retType = tree->TypeGet();
GenTree* foldedTree = m_compiler->gtFoldExpr(tree);
*pTree = foldedTree;
m_madeChanges = true;
*pTree = m_compiler->gtFoldExpr(tree);
m_madeChanges = true;
}
}
};
Expand Down
8 changes: 4 additions & 4 deletions src/coreclr/jit/fgprofile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ void BlockCountInstrumentor::Prepare(bool preImport)
//
// If we see any, we need to adjust our instrumentation pattern.
//
if (m_comp->opts.IsOSR() && ((m_comp->optMethodFlags & OMF_HAS_TAILCALL_SUCCESSOR) != 0))
if (m_comp->opts.IsInstrumentedOptimized() && ((m_comp->optMethodFlags & OMF_HAS_TAILCALL_SUCCESSOR) != 0))
{
JITDUMP("OSR + PGO + potential tail call --- preparing to relocate block probes\n");

Expand Down Expand Up @@ -1887,8 +1887,8 @@ PhaseStatus Compiler::fgPrepareToInstrumentMethod()
(JitConfig.TC_PartialCompilation() > 0);
const bool prejit = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT);
const bool tier0WithPatchpoints = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0) && mayHavePatchpoints;
const bool osrMethod = opts.IsOSR();
const bool useEdgeProfiles = (JitConfig.JitEdgeProfiling() > 0) && !prejit && !tier0WithPatchpoints && !osrMethod;
const bool instrOpt = opts.IsInstrumentedOptimized();
const bool useEdgeProfiles = (JitConfig.JitEdgeProfiling() > 0) && !prejit && !tier0WithPatchpoints && !instrOpt;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need block profiles for full instrumented/optimized methods? Seems like edge profiles might work -- unless perhaps the think you need is the is special handling for tail calls.

if so can you add a clarifying comment here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately we still need it for now, I'll allocate some time to investigate what is needed to enable edge-profiling after this PR


if (useEdgeProfiles)
{
Expand All @@ -1899,7 +1899,7 @@ PhaseStatus Compiler::fgPrepareToInstrumentMethod()
JITDUMP("Using block profiling, because %s\n",
(JitConfig.JitEdgeProfiling() == 0)
? "edge profiles disabled"
: prejit ? "prejitting" : osrMethod ? "OSR" : "tier0 with patchpoints");
: prejit ? "prejitting" : instrOpt ? "optimized instr" : "tier0 with patchpoints");

fgCountInstrumentor = new (this, CMK_Pgo) BlockCountInstrumentor(this);
}
Expand Down
14 changes: 8 additions & 6 deletions src/coreclr/jit/importercalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1288,7 +1288,7 @@ var_types Compiler::impImportCall(OPCODE opcode,
// have to check for anything that might introduce a recursive tail call.
// * We only instrument root method blocks in OSR methods,
//
if (opts.IsOSR() && !compIsForInlining())
if ((opts.IsInstrumentedOptimized() || opts.IsOSR()) && !compIsForInlining())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As noted below, I think this is an OSR only problem.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it could be

Suggested change
if ((opts.IsInstrumentedOptimized() || opts.IsOSR()) && !compIsForInlining())
if ((opts.IsInstrumentedOptimized() && opts.IsOSR()) && !compIsForInlining())

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opts.IsInstrumentedOptimized() && opts.IsOSR() is not working, for some reason it hits an assert even in non PGO OSR mode. I should be able to revert these changes once I fix "edge profiling" for optimized code

{
// If a root method tail call candidate block is not a BBJ_RETURN, it should have a unique
// BBJ_RETURN successor. Mark that successor so we can handle it specially during profile
Expand All @@ -1310,14 +1310,16 @@ var_types Compiler::impImportCall(OPCODE opcode,
const bool mustImportEntryBlock = gtIsRecursiveCall(methHnd) || actualCall->IsInlineCandidate() ||
actualCall->IsGuardedDevirtualizationCandidate();

BasicBlock* entryBb = opts.IsOSR() ? fgEntryBB : fgFirstBB;

// Only schedule importation if we're not currently importing.
//
if (mustImportEntryBlock && (compCurBB != fgEntryBB))
if ((opts.IsInstrumentedOptimized() || opts.IsOSR()) && mustImportEntryBlock && (compCurBB != entryBb))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an OSR only issue, as full method compilation will naturally start importing with fgFirstBB.

{
JITDUMP("\nOSR: inlineable or recursive tail call [%06u] in the method, so scheduling " FMT_BB
JITDUMP("\ninlineable or recursive tail call [%06u] in the method, so scheduling " FMT_BB
" for importation\n",
dspTreeID(call), fgEntryBB->bbNum);
impImportBlockPending(fgEntryBB);
dspTreeID(call), entryBb->bbNum);
impImportBlockPending(entryBb);
}
}
}
Expand Down Expand Up @@ -6290,7 +6292,7 @@ bool Compiler::impConsiderCallProbe(GenTreeCall* call, IL_OFFSET ilOffset)
return false;
}

assert(opts.OptimizationDisabled() || opts.IsOSR());
assert(opts.OptimizationDisabled() || opts.IsInstrumentedOptimized());
assert(!compIsForInlining());

// During importation, optionally flag this block as one that
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/vm/callcounting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ bool CallCountingManager::SetCodeEntryPoint(
// For a default code version that is not tier 0, call counting will have been disabled by this time (checked
// below). Avoid the redundant and not-insignificant expense of GetOptimizationTier() on a default code version.
!activeCodeVersion.IsDefaultVersion() &&
activeCodeVersion.GetOptimizationTier() != NativeCodeVersion::OptimizationTier0
activeCodeVersion.IsFinalTier()
) ||
!g_pConfig->TieredCompilation_CallCounting())
{
Expand Down Expand Up @@ -602,7 +602,7 @@ bool CallCountingManager::SetCodeEntryPoint(
return true;
}

_ASSERTE(activeCodeVersion.GetOptimizationTier() == NativeCodeVersion::OptimizationTier0);
_ASSERTE(!activeCodeVersion.IsFinalTier());

// If the tiering delay is active, postpone further work
if (GetAppDomain()
Expand Down Expand Up @@ -649,7 +649,7 @@ bool CallCountingManager::SetCodeEntryPoint(
}
else
{
_ASSERTE(activeCodeVersion.GetOptimizationTier() == NativeCodeVersion::OptimizationTier0);
_ASSERTE(!activeCodeVersion.IsFinalTier());

// If the tiering delay is active, postpone further work
if (GetAppDomain()
Expand All @@ -659,7 +659,7 @@ bool CallCountingManager::SetCodeEntryPoint(
return true;
}

CallCount callCountThreshold = (CallCount)g_pConfig->TieredCompilation_CallCountThreshold();
CallCount callCountThreshold = g_pConfig->TieredCompilation_CallCountThreshold();
_ASSERTE(callCountThreshold != 0);

NewHolder<CallCountingInfo> callCountingInfoHolder = new CallCountingInfo(activeCodeVersion, callCountThreshold);
Expand Down Expand Up @@ -780,7 +780,7 @@ PCODE CallCountingManager::OnCallCountThresholdReached(TransitionBlock *transiti
// used going forward under appropriate locking to synchronize further with deletion.
GCX_PREEMP_THREAD_EXISTS(CURRENT_THREAD);

_ASSERTE(codeVersion.GetOptimizationTier() == NativeCodeVersion::OptimizationTier0);
_ASSERTE(!codeVersion.IsFinalTier());

codeEntryPoint = codeVersion.GetNativeCode();
do
Expand Down
19 changes: 14 additions & 5 deletions src/coreclr/vm/codeversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,11 @@ NativeCodeVersion::OptimizationTier NativeCodeVersionNode::GetOptimizationTier()
void NativeCodeVersionNode::SetOptimizationTier(NativeCodeVersion::OptimizationTier tier)
{
LIMITED_METHOD_CONTRACT;
_ASSERTE(tier >= m_optTier);

_ASSERTE(
tier == m_optTier ||
(m_optTier != NativeCodeVersion::OptimizationTier::OptimizationTier1 &&
m_optTier != NativeCodeVersion::OptimizationTier::OptimizationTierOptimized));

m_optTier = tier;
}
Expand Down Expand Up @@ -333,6 +337,13 @@ NativeCodeVersion::OptimizationTier NativeCodeVersion::GetOptimizationTier() con
}
}

bool NativeCodeVersion::IsFinalTier() const
{
LIMITED_METHOD_DAC_CONTRACT;
OptimizationTier tier = GetOptimizationTier();
return tier == OptimizationTier1 || tier == OptimizationTierOptimized;
}

#ifndef DACCESS_COMPILE
void NativeCodeVersion::SetOptimizationTier(OptimizationTier tier)
{
Expand Down Expand Up @@ -808,7 +819,7 @@ bool ILCodeVersion::HasAnyOptimizedNativeCodeVersion(NativeCodeVersion tier0Nati
_ASSERTE(!tier0NativeCodeVersion.IsNull());
_ASSERTE(tier0NativeCodeVersion.GetILCodeVersion() == *this);
_ASSERTE(tier0NativeCodeVersion.GetMethodDesc()->IsEligibleForTieredCompilation());
_ASSERTE(tier0NativeCodeVersion.GetOptimizationTier() == NativeCodeVersion::OptimizationTier0);
_ASSERTE(!tier0NativeCodeVersion.IsFinalTier());

NativeCodeVersionCollection nativeCodeVersions = GetNativeCodeVersions(tier0NativeCodeVersion.GetMethodDesc());
for (auto itEnd = nativeCodeVersions.End(), it = nativeCodeVersions.Begin(); it != itEnd; ++it)
Expand Down Expand Up @@ -1708,9 +1719,7 @@ PCODE CodeVersionManager::PublishVersionableCodeIfNecessary(
{
#ifdef FEATURE_TIERED_COMPILATION
_ASSERTE(!config->ShouldCountCalls() || pMethodDesc->IsEligibleForTieredCompilation());
_ASSERTE(
!config->ShouldCountCalls() ||
activeVersion.GetOptimizationTier() == NativeCodeVersion::OptimizationTier0);
_ASSERTE(!config->ShouldCountCalls() || !activeVersion.IsFinalTier());
if (config->ShouldCountCalls()) // the generated code was at a tier that is call-counted
{
// This is the first call to a call-counted code version of the method
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/vm/codeversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,19 @@ class NativeCodeVersion
BOOL SetNativeCodeInterlocked(PCODE pCode, PCODE pExpected = NULL);
#endif

// NOTE: Don't change existing values to avoid breaking changes in event tracing
enum OptimizationTier
{
OptimizationTier0,
OptimizationTier1,
OptimizationTier1OSR,
OptimizationTierOptimized, // may do less optimizations than tier 1
OptimizationTierInstrumented,
OptimizationTierInstrumentedOptimized,
};
#ifdef FEATURE_TIERED_COMPILATION
OptimizationTier GetOptimizationTier() const;
bool IsFinalTier() const;
#ifndef DACCESS_COMPILE
void SetOptimizationTier(OptimizationTier tier);
#endif
Expand Down
16 changes: 12 additions & 4 deletions src/coreclr/vm/eeconfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ HRESULT EEConfig::Init()

#if defined(FEATURE_PGO)
fTieredPGO = false;
tieredPGO_InstrumentOnlyHotCode = false;
#endif

#if defined(FEATURE_READYTORUN)
Expand Down Expand Up @@ -699,10 +700,6 @@ HRESULT EEConfig::sync()

dwSleepOnExit = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_SleepOnExit);

#if defined(FEATURE_PGO)
fTieredPGO = Configuration::GetKnobBooleanValue(W("System.Runtime.TieredPGO"), CLRConfig::EXTERNAL_TieredPGO);
#endif

#if defined(FEATURE_TIERED_COMPILATION)
fTieredCompilation = Configuration::GetKnobBooleanValue(W("System.Runtime.TieredCompilation"), CLRConfig::EXTERNAL_TieredCompilation);
if (fTieredCompilation)
Expand Down Expand Up @@ -784,6 +781,17 @@ HRESULT EEConfig::sync()
}
#endif

#if defined(FEATURE_PGO)
fTieredPGO = Configuration::GetKnobBooleanValue(W("System.Runtime.TieredPGO"), CLRConfig::EXTERNAL_TieredPGO);
tieredPGO_InstrumentOnlyHotCode = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TieredPGO_InstrumentOnlyHotCode) == 1;

// We need quick jit for TieredPGO
if (!fTieredCompilation_QuickJit)
{
fTieredPGO = false;
}
#endif

#if defined(FEATURE_ON_STACK_REPLACEMENT)
dwOSR_HitLimit = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_OSR_HitLimit);
dwOSR_CounterBump = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_OSR_CounterBump);
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/vm/eeconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class EEConfig

#if defined(FEATURE_PGO)
bool TieredPGO(void) const { LIMITED_METHOD_CONTRACT; return fTieredPGO; }
bool TieredPGO_InstrumentOnlyHotCode(void) const { LIMITED_METHOD_CONTRACT; return tieredPGO_InstrumentOnlyHotCode; }
#endif

#if defined(FEATURE_READYTORUN)
Expand Down Expand Up @@ -658,6 +659,7 @@ class EEConfig

#if defined(FEATURE_PGO)
bool fTieredPGO;
bool tieredPGO_InstrumentOnlyHotCode;
#endif

#if defined(FEATURE_READYTORUN)
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1802,7 +1802,7 @@ void Interpreter::JitMethodIfAppropriate(InterpreterMethodInfo* interpMethInfo,
CodeVersionManager::LockHolder _lockHolder;
NativeCodeVersion activeCodeVersion = md->GetCodeVersionManager()->GetActiveILCodeVersion(md).GetActiveNativeCodeVersion(md);
ILCodeVersion ilCodeVersion = activeCodeVersion.GetILCodeVersion();
if (activeCodeVersion.GetOptimizationTier() == NativeCodeVersion::OptimizationTier0 &&
if (!activeCodeVersion.IsFinalTier() &&
!ilCodeVersion.HasAnyOptimizedNativeCodeVersion(activeCodeVersion))
{
tieredCompilationManager->AsyncPromoteToTier1(activeCodeVersion, &scheduleTieringBackgroundWork);
Expand Down
17 changes: 0 additions & 17 deletions src/coreclr/vm/jitinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12823,23 +12823,6 @@ CORJIT_FLAGS GetCompileFlags(MethodDesc * ftn, CORJIT_FLAGS flags, CORINFO_METHO

#ifdef FEATURE_PGO

// Instrument, if
//
// * We're writing pgo data and we're jitting at Tier0.
// * Tiered PGO is enabled and we're jitting at Tier0.
// * Tiered PGO is enabled and we are jitting an OSR method.
//
if ((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_WritePGOData) > 0)
&& flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_TIER0))
{
flags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR);
}
else if ((g_pConfig->TieredPGO())
&& (flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_TIER0) || flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_OSR)))
{
flags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR);
}

if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ReadPGOData) > 0)
{
flags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBOPT);
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/vm/method.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1993,6 +1993,8 @@ class PrepareCodeConfig
QuickJitted,
OptimizedTier1,
OptimizedTier1OSR,
InstrumentedTier,
InstrumentedTierOptimized,

Count
};
Expand Down
Loading