Skip to content

Preserve integer identity for Boolean arithmetic slots - #9946

Merged
richlander merged 4 commits into
mainfrom
feature/9371-unrenderable-splits-2
Oct 12, 2026
Merged

richlander merged 4 commits into
mainfrom
feature/9371-unrenderable-splits-2

Conversation

@richlander

@richlander richlander commented Oct 11, 2026 •

Copy link
Copy Markdown
Owner

dotnet-inspect builds robust, capable .NET inspection features that provide foundational capabilities or compelling experiences and are conventionally sound, delightfully new or unique, or both.

Summary

  • Preserve exact System.Int32 identity for complete slot webs produced by Boolean/int arithmetic before Boolean operands are normalized to condition ? 1 : 0.
  • Require Boolean folding to account for every store and load that may share the Boolean-compatible I4 storage family, while continuing to ignore proven unrelated reference and non-I4 reuse of the same numeric slot.
  • Retire four non-reference UnrenderableStoreType split webs without adding broad residual testimony or enum inference.
  • Deliberately leave TypeRef.FunctionPointerParameterText split because its Boolean branch encodes ArgumentRefKind and requires separate enum-specific proof.

Part of #9371.

Design basis

Normative owner: docs/design/value-typed-emission.md#bounded-i4-slot-identity-preservation.

ArithmeticBoolOperandPass owns integer identity only for complete slot webs whose stores and loads stay inside its exact Boolean/System.Int32 arithmetic domain. BooleanFoldingPass owns Boolean materialization only when omitted uses cannot belong to the same I4 storage family. Arbitrary Boolean producers, non-Int32 arithmetic, enum identity, mixed scopes, and non-arithmetic observers remain outside these rules.

Demo

Roslyn 5.0.0's
ForEachLoopOperation.get_ChildOperationsCount computes a count from two
Boolean comparisons, stores it, and later adds it to two more counts.

The checksum-matched PDB/SourceLink oracle is:

=>
    (LoopControlVariable is null ? 0 : 1) +
    (Collection is null ? 0 : 1) +
    NextVariables.Length +
    (Body is null ? 0 : 1);

Source:
https://raw.githubusercontent.com/dotnet/roslyn/6c4a46a31302167b425d5e0a31ea83c9a9aa1d09/src/Compilers/Core/Portable/Generated/Operations.Generated.cs

Exact base d93cb58f8 split the same stack slot into an integer producer and an
unassigned Boolean consumer, then narrowed the multi-term count back to
zero-or-one:

bool S_256_1;

int S_256 = (LoopControlVariable is not null ? 1 : 0)
    + (Collection is not null ? 1 : 0);
ImmutableArray<IOperation> V_0 = NextVariables;
return (S_256_1 ? 1 : 0) + V_0.Length
    + (base.Body is not null ? 1 : 0);

Exact reviewed head a48017a48 preserves the slot's integer identity and
reuses the actual count directly:

int S_256 = (LoopControlVariable is not null ? 1 : 0)
    + (Collection is not null ? 1 : 0);
ImmutableArray<IOperation> V_0 = NextVariables;
return S_256 + V_0.Length
    + (base.Body is not null ? 1 : 0);

Evidence

  • Current-head dotnet build dotnet-inspect.slnx -c Release: succeeded with 0 warnings and 0 errors.
  • Current-head focused synthetic and same-number reuse gates: 11/11 passed,
    including unrelated Int64 same-number reuse.
  • Current-head pinned Roslyn product witnesses: 2/2 passed.
  • Fixed 14-assembly, 89,065-method census against exact latest base d93cb58f8:
    • residual-bound webs: 61 -> 57;
    • residual-bound locals: 104 -> 96;
    • affected methods: 35 -> 31;
    • split webs: 30 -> 26;
    • UnrenderableStoreType: 5 webs / 10 locals -> 1 web / 2 locals;
    • nested residual webs and late-decidable webs remain zero;
    • the same four visible pass bugs remain.
  • Product output now preserves integer counts in ForEachLoopOperation.get_ChildOperationsCount and ForToLoopOperation.get_ChildOperationsCount, keeps mixed integer stores in EarlyWellKnownAttributeBinder.CanBeValidAttributeArgument, and retains the integer count in EhStructuringPass.InlineFilterLocalLoads.
  • Integrated full decompiler gate ran 9,285 tests: 9,268 passed, 10 failed, and 7 skipped. All ten failures reproduced on exact integrated base 6f846c49b, including three direct residual-census setups missing DefiniteAssignmentPass, two invalid caller-supplied corpus-sensor pipelines, and five existing fidelity/compile-back expectations.
  • npx markdownlint-cli docs/design/value-typed-emission.md and git diff --check origin/main...HEAD passed.

@richlander

Copy link
Copy Markdown
Owner Author

Round 1 is complete for PR 9946.

  • Theme: Retire residual C# printer slot splits through narrow, proof-backed typed passes.
  • Review model GPT-5.6 Sol was used for adversarial review.
  • Design basis: normative owner docs/design/value-typed-emission.md#bounded-i4-slot-identity-preservation — Boolean materialization accounts only for the Boolean-compatible I4 storage family, while known non-I4 primitive families are unrelated same-number reuse; supporting BooleanFoldingPass as the typed-pass owner, TypeFamilies as primitive-family classification, and StackSlotReuseRenderingTests as the same-number-reuse consumer gate.
  • Review feedback is: converging.
  • Round start: 2026-10-11T00:45:49Z.
  • Round end: 2026-10-11T00:53:02Z.
  • Round duration: 00:07.

Progress: 1 pushed candidate, 1 usable review, 1 accepted finding.
Reviews: 0/1 clean — GPT-5.6 Sol found one medium-confidence correctness defect.
Recommendation: continue.

Resolution: Accepted the finding. BooleanFoldingPass currently admits every TypeFamilies.IsIntegerLike load into its Boolean candidate set, including Int64, UInt64, IntPtr, and UIntPtr; a normal non-Boolean consumer of that unrelated range then vetoes the actual Boolean-I4 family. A clean exact-head probe adding unrelated Int64 same-number reuse failed as predicted: the Boolean range remained int instead of materializing as bool. Round 2 will restrict candidate loads to Boolean-compatible I4 types and retain the reproduced Int64 case as a regression gate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@richlander

Copy link
Copy Markdown
Owner Author

Round 2 candidate is published at exact head
a48017a48d7ae4e9e4ab0d15df5e20cb8103958a.

It resolves the accepted round 1 finding by limiting Boolean candidate loads
to Boolean-compatible I4 types. Known I8 and native-integer loads now remain
unrelated same-number reuse, matching the owning design. The reproduced
unrelated-Int64 case is retained as a regression gate.

Validation at this head:

  • 11/11 synthetic and same-number reuse tests passed;
  • 2/2 real Roslyn witnesses passed;
  • Release solution build passed with zero warnings and errors;
  • fixed corpus remains 57 residual webs, 96 locals, 31 methods, and 26 split
    webs, with one deliberately excluded UnrenderableStoreType enum web.

@richlander

Copy link
Copy Markdown
Owner Author

Round 2 is complete for PR 9946.

  • Theme: Retire residual C# printer slot splits through narrow, proof-backed typed passes.
  • Review model GPT-5.6 Sol was used for adversarial review.
  • Design basis: normative owner docs/design/value-typed-emission.md#bounded-i4-slot-identity-preservation — arithmetic identity is preserved only for complete Boolean/Int32 arithmetic webs within one function-body scope, while Boolean materialization accounts for every potentially related I4-family store and load; supporting ArithmeticBoolOperandPass, BooleanFoldingPass, TypeFamilies, and StackSlotReuseRenderingTests.
  • Review feedback is: clean.
  • Round start: 2026-10-11T01:10:49Z.
  • Round end: 2026-10-11T01:33:58Z.
  • Round duration: 00:23.

Progress: 2 pushed candidates, 2 usable reviews, 1 accepted finding.
Reviews: 1/1 clean — GPT-5.6 Sol returned CLEAN for exact head a48017a48d7ae4e9e4ab0d15df5e20cb8103958a.
Recommendation: merge.

Resolution: The round 1 finding is resolved. Boolean candidate-load selection now admits only Boolean or StackFamily.I4 loads, leaving known I8 and native-integer same-number ranges outside both the candidate and veto sets. The committed unrelated-Int64 regression passes. Current-head ci-required is successful, live-base conflict probing is clean against d93cb58f8b5c44ecc831158db64cee502a7e63e6, GitHub reports positive mergeability, and no review threads or external reviews are pending. Merge still requires explicit authorization for this exact head and base ref.

@richlander richlander added the review-clean PR has met the adversarial review standard per AGENTS.md. label Oct 11, 2026
@richlander
richlander merged commit 2d4a2f4 into main Oct 12, 2026
15 checks passed
@richlander
richlander deleted the feature/9371-unrenderable-splits-2 branch October 12, 2026 20:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review-clean PR has met the adversarial review standard per AGENTS.md.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant