Skip to content

Conversation

@indietyp
Copy link
Member

@indietyp indietyp commented Dec 7, 2025

🌟 What is the purpose of this PR?

Add a generic dataflow analysis framework to MIR with a liveness analysis implementation

🔍 What does this change?

  • Introduces a new dataflow analysis framework in mir/src/pass/analysis/dataflow/
  • Implements a lattice-based approach with support for both forward and backward analyses
  • Adds a liveness analysis implementation as the first client of the framework
  • Refactors the Pass trait into separate TransformPass and AnalysisPass traits
  • Adds new_filled method to MixedBitSet to support creating filled bitsets
  • Adds SwitchIntValue enum to represent switch terminator branch values
  • Enables the iter_intersperse feature for formatting output

Pre-Merge Checklist 🚀

🚢 Has this modified a publishable library?

This PR:

  • does not modify any publishable blocks or libraries, or modifications do not need publishing

📜 Does this require a change to the docs?

The changes in this PR:

  • are internal and do not require a docs change

🕸️ Does this require a change to the Turbo Graph?

The changes in this PR:

  • do not affect the execution graph

🛡 What tests cover this?

  • Added comprehensive test suite for the liveness analysis
  • Added algebraic law verification tests for lattice implementations

@vercel vercel bot temporarily deployed to Preview – petrinaut December 7, 2025 21:08 Inactive
@github-actions github-actions bot added area/libs Relates to first-party libraries/crates/packages (area) type/eng > backend Owned by the @backend team area/tests New or updated tests labels Dec 7, 2025
Copy link
Member Author

indietyp commented Dec 7, 2025

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@vercel vercel bot temporarily deployed to Preview – petrinaut December 7, 2025 21:11 Inactive
@codecov
Copy link

codecov bot commented Dec 7, 2025

Codecov Report

❌ Patch coverage is 79.09270% with 212 lines in your changes missing coverage. Please review.
✅ Project coverage is 58.17%. Comparing base (aa64e0a) to head (e0837a2).

Files with missing lines Patch % Lines
...hashql/mir/src/pass/analysis/dataflow/framework.rs 44.85% 176 Missing and 1 partial ⚠️
...hql/mir/src/pass/analysis/dataflow/lattice/laws.rs 90.37% 25 Missing and 1 partial ⚠️
libs/@local/hashql/core/src/id/bit_vec/mod.rs 0.00% 5 Missing ⚠️
...hql/mir/src/pass/analysis/dataflow/liveness/mod.rs 94.59% 1 Missing and 1 partial ⚠️
libs/@local/hashql/mir/src/pass/mod.rs 0.00% 2 Missing ⚠️
Additional details and impacted files
@@                                         Coverage Diff                                         @@
##           bm/be-209-hashql-implement-dataflow-tracking-between-statements    #8168      +/-   ##
===================================================================================================
+ Coverage                                                            57.98%   58.17%   +0.19%     
===================================================================================================
  Files                                                                 1169     1175       +6     
  Lines                                                               109681   110687    +1006     
  Branches                                                              4985     4994       +9     
===================================================================================================
+ Hits                                                                 63603    64397     +794     
- Misses                                                               45329    45538     +209     
- Partials                                                               749      752       +3     
Flag Coverage Δ
rust.hashql-compiletest 49.36% <ø> (ø)
rust.hashql-mir 83.93% <79.48%> (-0.85%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@vercel vercel bot temporarily deployed to Preview – petrinaut December 7, 2025 21:17 Inactive
@vercel vercel bot temporarily deployed to Preview – petrinaut December 8, 2025 07:52 Inactive
@graphite-app graphite-app bot requested review from a team December 8, 2025 08:08
@vercel vercel bot temporarily deployed to Preview – petrinaut December 8, 2025 08:26 Inactive
@vercel vercel bot temporarily deployed to Preview – petrinaut December 8, 2025 08:32 Inactive
@github-actions
Copy link
Contributor

github-actions bot commented Dec 8, 2025

Benchmark results

@rust/hash-graph-benches – Integrations

policy_resolution_large

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2002 $$28.1 \mathrm{ms} \pm 264 \mathrm{μs}\left({\color{gray}-0.782 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$3.25 \mathrm{ms} \pm 13.5 \mathrm{μs}\left({\color{gray}0.759 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 1001 $$12.9 \mathrm{ms} \pm 105 \mathrm{μs}\left({\color{gray}0.161 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 3314 $$42.5 \mathrm{ms} \pm 273 \mathrm{μs}\left({\color{gray}0.771 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$14.0 \mathrm{ms} \pm 65.3 \mathrm{μs}\left({\color{gray}-0.619 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 1526 $$24.3 \mathrm{ms} \pm 169 \mathrm{μs}\left({\color{gray}-0.134 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 2078 $$27.5 \mathrm{ms} \pm 173 \mathrm{μs}\left({\color{lightgreen}-39.151 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.65 \mathrm{ms} \pm 22.6 \mathrm{μs}\left({\color{lightgreen}-82.244 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 1033 $$14.2 \mathrm{ms} \pm 95.9 \mathrm{μs}\left({\color{lightgreen}-51.845 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_medium

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 102 $$3.67 \mathrm{ms} \pm 16.2 \mathrm{μs}\left({\color{gray}-1.414 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.82 \mathrm{ms} \pm 13.1 \mathrm{μs}\left({\color{gray}-0.217 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 51 $$3.21 \mathrm{ms} \pm 14.8 \mathrm{μs}\left({\color{gray}-0.655 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 269 $$5.08 \mathrm{ms} \pm 24.5 \mathrm{μs}\left({\color{gray}-1.586 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$3.40 \mathrm{ms} \pm 18.0 \mathrm{μs}\left({\color{gray}-0.957 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 107 $$3.96 \mathrm{ms} \pm 19.1 \mathrm{μs}\left({\color{gray}-1.406 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 133 $$4.38 \mathrm{ms} \pm 21.2 \mathrm{μs}\left({\color{gray}-0.066 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.29 \mathrm{ms} \pm 12.4 \mathrm{μs}\left({\color{gray}-0.422 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 63 $$3.98 \mathrm{ms} \pm 27.6 \mathrm{μs}\left({\color{gray}0.233 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_none

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2 $$2.50 \mathrm{ms} \pm 12.6 \mathrm{μs}\left({\color{red}7.09 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.48 \mathrm{ms} \pm 10.2 \mathrm{μs}\left({\color{red}7.06 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 1 $$2.55 \mathrm{ms} \pm 10.6 \mathrm{μs}\left({\color{red}7.12 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 8 $$2.77 \mathrm{ms} \pm 18.4 \mathrm{μs}\left({\color{gray}4.61 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$2.62 \mathrm{ms} \pm 10.5 \mathrm{μs}\left({\color{gray}4.71 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 3 $$2.81 \mathrm{ms} \pm 11.5 \mathrm{μs}\left({\color{gray}3.32 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_small

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 52 $$2.92 \mathrm{ms} \pm 12.1 \mathrm{μs}\left({\color{red}6.43 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.57 \mathrm{ms} \pm 10.2 \mathrm{μs}\left({\color{red}6.87 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 25 $$2.76 \mathrm{ms} \pm 9.20 \mathrm{μs}\left({\color{red}7.85 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 94 $$3.24 \mathrm{ms} \pm 15.8 \mathrm{μs}\left({\color{red}5.99 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$2.81 \mathrm{ms} \pm 10.3 \mathrm{μs}\left({\color{red}6.99 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 26 $$3.05 \mathrm{ms} \pm 14.0 \mathrm{μs}\left({\color{red}7.12 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 66 $$3.27 \mathrm{ms} \pm 16.0 \mathrm{μs}\left({\color{red}8.87 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$2.79 \mathrm{ms} \pm 11.4 \mathrm{μs}\left({\color{red}6.17 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 29 $$3.05 \mathrm{ms} \pm 15.4 \mathrm{μs}\left({\color{red}7.11 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_complete

Function Value Mean Flame graphs
entity_by_id;one_depth 1 entities $$38.2 \mathrm{ms} \pm 156 \mathrm{μs}\left({\color{gray}-0.776 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 10 entities $$85.8 \mathrm{ms} \pm 533 \mathrm{μs}\left({\color{gray}1.41 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 25 entities $$42.7 \mathrm{ms} \pm 191 \mathrm{μs}\left({\color{gray}1.72 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 5 entities $$45.9 \mathrm{ms} \pm 256 \mathrm{μs}\left({\color{gray}2.72 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 50 entities $$53.0 \mathrm{ms} \pm 279 \mathrm{μs}\left({\color{gray}1.28 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 1 entities $$40.6 \mathrm{ms} \pm 169 \mathrm{μs}\left({\color{gray}2.32 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 10 entities $$498 \mathrm{ms} \pm 1.06 \mathrm{ms}\left({\color{gray}-0.265 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 25 entities $$99.1 \mathrm{ms} \pm 393 \mathrm{μs}\left({\color{gray}-0.313 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 5 entities $$83.1 \mathrm{ms} \pm 346 \mathrm{μs}\left({\color{gray}0.624 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 50 entities $$291 \mathrm{ms} \pm 577 \mathrm{μs}\left({\color{lightgreen}-8.114 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 1 entities $$14.8 \mathrm{ms} \pm 78.0 \mathrm{μs}\left({\color{gray}1.50 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 10 entities $$15.4 \mathrm{ms} \pm 75.5 \mathrm{μs}\left({\color{gray}2.95 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 25 entities $$15.6 \mathrm{ms} \pm 88.8 \mathrm{μs}\left({\color{gray}3.60 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 5 entities $$14.9 \mathrm{ms} \pm 55.2 \mathrm{μs}\left({\color{gray}0.828 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 50 entities $$18.5 \mathrm{ms} \pm 104 \mathrm{μs}\left({\color{gray}0.959 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_linkless

Function Value Mean Flame graphs
entity_by_id 1 entities $$14.7 \mathrm{ms} \pm 72.7 \mathrm{μs}\left({\color{gray}3.27 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10 entities $$14.7 \mathrm{ms} \pm 91.8 \mathrm{μs}\left({\color{gray}-0.591 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 100 entities $$15.1 \mathrm{ms} \pm 86.5 \mathrm{μs}\left({\color{gray}3.40 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 1000 entities $$15.5 \mathrm{ms} \pm 69.8 \mathrm{μs}\left({\color{gray}1.42 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10000 entities $$22.4 \mathrm{ms} \pm 148 \mathrm{μs}\left({\color{gray}1.11 \mathrm{\%}}\right) $$ Flame Graph

representative_read_entity

Function Value Mean Flame graphs
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/block/v/1 $$29.4 \mathrm{ms} \pm 313 \mathrm{μs}\left({\color{gray}2.90 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/book/v/1 $$30.6 \mathrm{ms} \pm 299 \mathrm{μs}\left({\color{gray}2.94 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/building/v/1 $$29.7 \mathrm{ms} \pm 322 \mathrm{μs}\left({\color{gray}-0.252 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/organization/v/1 $$30.6 \mathrm{ms} \pm 279 \mathrm{μs}\left({\color{gray}0.650 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/page/v/2 $$28.7 \mathrm{ms} \pm 247 \mathrm{μs}\left({\color{gray}-4.788 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/person/v/1 $$31.2 \mathrm{ms} \pm 340 \mathrm{μs}\left({\color{gray}1.62 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/playlist/v/1 $$30.2 \mathrm{ms} \pm 274 \mathrm{μs}\left({\color{gray}-1.967 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/song/v/1 $$29.3 \mathrm{ms} \pm 273 \mathrm{μs}\left({\color{gray}-1.819 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/uk-address/v/1 $$30.4 \mathrm{ms} \pm 309 \mathrm{μs}\left({\color{gray}1.59 \mathrm{\%}}\right) $$ Flame Graph

representative_read_entity_type

Function Value Mean Flame graphs
get_entity_type_by_id Account ID: bf5a9ef5-dc3b-43cf-a291-6210c0321eba $$8.89 \mathrm{ms} \pm 39.5 \mathrm{μs}\left({\color{gray}0.565 \mathrm{\%}}\right) $$ Flame Graph

representative_read_multiple_entities

Function Value Mean Flame graphs
entity_by_property traversal_paths=0 0 $$56.4 \mathrm{ms} \pm 318 \mathrm{μs}\left({\color{gray}-1.555 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$110 \mathrm{ms} \pm 407 \mathrm{μs}\left({\color{gray}1.31 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$62.3 \mathrm{ms} \pm 313 \mathrm{μs}\left({\color{gray}-1.003 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$70.8 \mathrm{ms} \pm 358 \mathrm{μs}\left({\color{gray}-1.498 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$80.0 \mathrm{ms} \pm 313 \mathrm{μs}\left({\color{gray}-0.085 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$86.9 \mathrm{ms} \pm 348 \mathrm{μs}\left({\color{gray}0.392 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=0 0 $$52.6 \mathrm{ms} \pm 275 \mathrm{μs}\left({\color{gray}1.13 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$81.4 \mathrm{ms} \pm 392 \mathrm{μs}\left({\color{gray}0.459 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$59.0 \mathrm{ms} \pm 350 \mathrm{μs}\left({\color{gray}0.463 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$67.8 \mathrm{ms} \pm 284 \mathrm{μs}\left({\color{gray}0.652 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$69.8 \mathrm{ms} \pm 375 \mathrm{μs}\left({\color{gray}0.631 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$70.5 \mathrm{ms} \pm 458 \mathrm{μs}\left({\color{gray}0.498 \mathrm{\%}}\right) $$

scenarios

Function Value Mean Flame graphs
full_test query-limited $$140 \mathrm{ms} \pm 628 \mathrm{μs}\left({\color{red}8.65 \mathrm{\%}}\right) $$ Flame Graph
full_test query-unlimited $$136 \mathrm{ms} \pm 549 \mathrm{μs}\left({\color{red}6.55 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-limited $$41.7 \mathrm{ms} \pm 189 \mathrm{μs}\left({\color{lightgreen}-59.227 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-unlimited $$580 \mathrm{ms} \pm 1.00 \mathrm{ms}\left({\color{lightgreen}-8.405 \mathrm{\%}}\right) $$ Flame Graph

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/libs Relates to first-party libraries/crates/packages (area) area/tests New or updated tests type/eng > backend Owned by the @backend team

Development

Successfully merging this pull request may close these issues.

2 participants