JIT: Run liveness + DCE in tier0#124060
Conversation
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
There was a problem hiding this comment.
Pull request overview
This PR introduces an experimental optimization to run liveness analysis during tier0 compilation (when not in debug mode and not using forced MinOpts). The change is inspired by PR #123500, which showed that running full liveness for async methods in MinOpts can reduce IR generation sufficiently to offset the cost of the analysis itself.
Changes:
- Adds a new
fgTier0Liveness()function that runs liveness analysis in tier0 and immediately discards the results after use - The function performs liveness analysis temporarily, then cleans up all tracking state so the rest of the compilation pipeline is unaffected
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/coreclr/jit/liveness.cpp | Implements fgTier0Liveness() with a Tier0Liveness configuration that runs basic liveness analysis with full state cleanup afterwards |
| src/coreclr/jit/compiler.h | Declares the new fgTier0Liveness() method |
| src/coreclr/jit/compiler.cpp | Calls fgTier0Liveness() when tier0 optimizations are enabled (after optimization loop, before lowering phases) |
| } | ||
|
|
||
| //------------------------------------------------------------------------ | ||
| // fgSsaLiveness: Run SSA liveness. |
There was a problem hiding this comment.
The comment incorrectly states "Run SSA liveness" which is a copy-paste error from the fgSsaLiveness function above. This should say something like "Run tier0 liveness" or "Run liveness for tier0 optimization" to accurately describe what this function does.
| // fgSsaLiveness: Run SSA liveness. | |
| // fgTier0Liveness: Run tier0 liveness. |
| struct Tier0Liveness : public Liveness<Tier0Liveness> | ||
| { | ||
| enum | ||
| { | ||
| SsaLiveness = false, | ||
| ComputeMemoryLiveness = false, | ||
| IsLIR = false, | ||
| IsEarly = false, | ||
| }; |
There was a problem hiding this comment.
The PR title states "Run liveness + DCE in tier0", but dead code elimination (DCE) will not actually run with this configuration. DCE only runs when IsEarly=true, which causes the compiler to use the TryRemoveDeadStoreEarly path during liveness analysis. The Tier0Liveness struct sets IsEarly=false, so it will follow the standard liveness path without DCE.
At the call site, fgNodeThreading is NodeThreading::AllTrees, and with IsEarly=false, the liveness analysis follows the code path at lines 1265-1313 in liveness.cpp which does not perform dead store removal. The DCE path at lines 1314-1387 only executes when IsEarly=true.
If the intent is to run DCE in tier0, IsEarly should be set to true. If DCE is not intended, the PR title and description should be updated to remove the mention of DCE.


Just an experiment after seeing the results of #123500. Unlike for runtime async this may not prevent as much IR being generated, so probably won't see throughput wins.