Skip to content

Optimize FlatExpression node layout for constants, parameters, and parent links#534

Draft
Copilot wants to merge 5 commits intomasterfrom
copilot/optimize-flat-expression-representation
Draft

Optimize FlatExpression node layout for constants, parameters, and parent links#534
Copilot wants to merge 5 commits intomasterfrom
copilot/optimize-flat-expression-representation

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 22, 2026

FlatExpression needs a more direct node model to support upcoming canonicalization and chaining work: compact constant storage, explicit parameter declaration/usage identity, and reliable parent reachability from child chains. This update reshapes the flat node metadata so those semantics are encoded directly instead of inferred indirectly.

  • Constant node layout

    • Inline 32-bit constant payloads directly into constant leaf metadata.
    • Keep larger/non-inlineable values in Obj instead of routing them through ClosureConstants.
    • Preserve round-trip reconstruction for enums and primitive 32-bit payloads.
  • Parameter declaration vs usage

    • Split parameter semantics into:
      • declaration nodes: own scope/position metadata
      • usage nodes: point back to the declaration index
    • Store declaration scope in ChildIdx and declaration position in ChildCount.
    • Populate declaration metadata when lambda/block owners are created.
    • Fail fast on duplicate declarations in the same binding path.
  • Child chain parent linkage

    • Make the last node in every child chain point back to its owning node.
    • Reserve a metadata flag to distinguish “next sibling” from “parent link”.
    • Keep chaining traversal simple while enabling upward navigation.
  • Reader / builder updates

    • Update flattening to emit declaration nodes once and usage nodes on reference.
    • Update reconstruction to intern parameters by declaration index rather than prior synthetic IDs.
    • Move key node access paths to GetSurePresentRef/direct refs in hot paths.
  • Focused coverage

    • Adjust FlatExpression tests to assert:
      • no closure-constant spill for the covered constant cases
      • declaration metadata is written to lambda/block-owned parameters
      • usage nodes point to declarations
      • terminal child links point back to the parent owner

Example of the new parameter model:

var p = fe.Parameter(typeof(int), "p");   // declaration node
var assign = fe.Assign(local, p);         // creates parameter usage node(s)

var decl = fe.Nodes[p];
var usage = fe.Nodes[fe.Nodes[assign].ChildIdx];

decl.ChildIdx   // owning lambda/block index
decl.ChildCount // position in owner
usage.ChildIdx  // declaration node index

Copilot AI linked an issue Apr 22, 2026 that may be closed by this pull request
Copilot AI changed the title [WIP] Optimize FlatExpression representation Optimize FlatExpression node layout for constants, parameters, and parent links Apr 22, 2026
Copilot AI requested a review from dadhi April 22, 2026 21:13
Copy link
Copy Markdown
Owner

@dadhi dadhi left a comment

Choose a reason for hiding this comment

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

The ubuntu build is failed:
/home/runner/work/FastExpressionCompiler/FastExpressionCompiler/src/FastExpressionCompiler.LightExpression/FlatExpression.cs(1793,6): error CS0246: The type or namespace name 'DoesNotReturnAttribute' could not be found (are you missing a using directive or an assembly reference?) [/home/runner/work/FastExpressionCompiler/FastExpressionCompiler/src/FastExpressionCompiler.LightExpression/FastExpressionCompiler.LightExpression.csproj::TargetFramework=net472]

Also just to verify. We are using the same condition for FE as for SE and LE in FEC to decide what to store in ClosureConstants. We did not change that. The only change is for non closure constants that previosly can be stored inplace in Constant node for up to 8 bytes, but now - just up to 4 bytes. So bigger than 4 bytes non-closure values dtored in Obj (possibly boxed). Please check that.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 22, 2026

The ubuntu build is failed:
/home/runner/work/FastExpressionCompiler/FastExpressionCompiler/src/FastExpressionCompiler.LightExpression/FlatExpression.cs(1793,6): error CS0246: The type or namespace na...

Fixed in def9eb9. I removed the DoesNotReturn annotations so net472 can compile again, and restored the original closure-constant policy: object-like constants still go through ClosureConstants, while only non-closure values that no longer fit in 4 inline bytes stay boxed in Obj.

Copilot AI requested a review from dadhi April 22, 2026 21:39
Copy link
Copy Markdown
Owner

@dadhi dadhi left a comment

Choose a reason for hiding this comment

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

Vi errors:
Error: /home/runner/work/FastExpressionCompiler/FastExpressionCompiler/src/FastExpressionCompiler.LightExpression/FlatExpression.cs(1315,40): error CS0117: 'BitConverter' does not contain a definition for 'SingleToInt32Bits' [/home/runner/work/FastExpressionCompiler/FastExpressionCompiler/src/FastExpressionCompiler.LightExpression/FastExpressionCompiler.LightExpression.csproj::TargetFramework=net472]

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 22, 2026

Vi errors:
Error: /home/runner/work/FastExpressionCompiler/FastExpressionCompiler/src/FastExpressionCompiler.LightExpression/FlatExpression.cs(1315,40): error CS0117: 'BitConverter' does not contain a...

Fixed in 5ce2ffc. I replaced the BitConverter float bit conversions with a small explicit-layout helper so the inline float constant path stays the same but compiles on net472 too.

Copilot AI requested a review from dadhi April 22, 2026 21:46
tag = pointsToParent
? (byte)(tag | nextPointsToParentMask)
: (byte)(tag & ~nextPointsToParentMask);
_data = (_data & KeepWithoutTagAndNextMask)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Let split to 4 bytes _data and 4 bytes _nodeTypeAndKind

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 1484adf. ExprNode now uses a 4-byte _data field plus a 4-byte _nodeTypeAndKind field, while keeping the 24-byte explicit layout intact.

Copilot AI requested a review from dadhi April 22, 2026 22:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FlatExpression: optimize representation

2 participants