You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Suboptimal codegen for is pattern compared to .NET 6/7 #80052
Roslyn now introduces unnecessary temporary bool variables and extra conditional branches. The JIT is unable to untangle this pattern, resulting in larger, slower code.
It would be good to bisect and identify when this codegen changed, so we can understand if there was some reason for that change to occur, and based on that, what options we have for improving things.
Root cause: PR #65874 (Jan 2023) — "Enable switch dispatch for is-expressions" (fixes #45679). This routed or patterns through the general DAG lowering, which wraps results in a BoundSpillSequence with a bool temp. Before this, short or patterns went through the linear path and didn't have this overhead.
Both previous attempts modified the general DAG lowering to avoid the SpillSequence/result temp. That approach was fragile because the general path interacts with exception handler scopes (try/finally, await using), which led to the IL builder crash.
My approach is different: Instead of modifying the general DAG lowering, I route short or patterns (≤4 tests) to the existing, well-tested linear rewriter with swapped labels. For is '/' or '\\', the inverted linear sequence produces !(c != '/' && c != '\\') — a clean boolean expression with no SpillSequence or bool temp. Large or patterns (5+ tests) still go through the general path with switch dispatch.
This avoids the previous crashes because the linear rewriter doesn't use SpillSequence and doesn't interact with exception handler scopes.
Related issues: #59615, #55334 (same underlying problem)
Activity
stevenelliottjr commentedon Feb 17, 2026
I'd like to take this one. I'll investigate the pattern lowering regression and submit a PR.
RikkiGibson commentedon Feb 17, 2026
It would be good to bisect and identify when this codegen changed, so we can understand if there was some reason for that change to occur, and based on that, what options we have for improving things.
stevenelliottjr commentedon Feb 17, 2026
I did the bisect. Here's the full history:
Root cause: PR #65874 (Jan 2023) — "Enable switch dispatch for is-expressions" (fixes #45679). This routed
orpatterns through the general DAG lowering, which wraps results in aBoundSpillSequencewith a bool temp. Before this, shortorpatterns went through the linear path and didn't have this overhead.Previous fix attempts (both reverted):
PR Avoid creating a result temp for is-expressions #68694 (Aug 2023) — "Avoid creating a result temp for is-expressions" — Reverted in Revert "Avoid creating a result temp for is-expressions" #69582 due to test failures.
PR Avoid creating result temp for is-expressions (follow-up) #72273 (Mar 2024) — Follow-up attempt, fixing issues from Avoid creating a result temp for is-expressions #68694 — Reverted in Revert "Avoid creating result temp for is-expressions (#72273)" #72827 due to a compiler crash (
NullReferenceExceptioninILBuilder.BlockedBranchDestinationSlow) when the pattern appeared insideawait usingblocks ([dotnet-sdk-9.0.100-preview.3.24175.24] Microsoft.CSharp.Core.targets thrown errors when using "dotnet build" #72753). The crash was in exception handler scope handling.Both previous attempts modified the general DAG lowering to avoid the SpillSequence/result temp. That approach was fragile because the general path interacts with exception handler scopes (try/finally, await using), which led to the IL builder crash.
My approach is different: Instead of modifying the general DAG lowering, I route short
orpatterns (≤4 tests) to the existing, well-tested linear rewriter with swapped labels. Foris '/' or '\\', the inverted linear sequence produces!(c != '/' && c != '\\')— a clean boolean expression with no SpillSequence or bool temp. Largeorpatterns (5+ tests) still go through the general path with switch dispatch.This avoids the previous crashes because the linear rewriter doesn't use SpillSequence and doesn't interact with exception handler scopes.
Related issues: #59615, #55334 (same underlying problem)
Fix suboptimal codegen for short `or` patterns in is-expressions (dot…