-
Notifications
You must be signed in to change notification settings - Fork 27
Fix quadratic let hoisting when converting deep terms #442
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
saulshanabrook
merged 2 commits into
egraphs-good:main
from
yuvallu:fix-quadratic-let-conversion
Sep 30, 2026
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
Repository: egraphs-good/egglog-python
Length of output: 16376
🏁 Script executed:
Repository: egraphs-good/egglog-python
Length of output: 41640
🤖 get_repo_knowledge executed:
get_repo_knowledge egraphs-good/egglog-python /tmp/coderabbit-repo-knowledge/egraphs-good-egglog-python-c8ba653aLength of output: 384
🏁 Script executed:
Repository: egraphs-good/egglog-python
Length of output: 42278
Traverse
GetCostDecl.argsbefore marking arguments as hoisted.get_costcreates aGetCostDecl. During lowering,_expr_to_eggpasseslets_hoisted=Trueto its arguments. Because_exprs_multiple_parentsdoes not traverseGetCostDecl.args, shared constructor terms can bypass_transform_let. The separate let cache then has no entry, so each occurrence can be expanded inline.Add a regression case with shared constructor terms inside a cost argument.
Suggested scanner fix
🤖 Prompt for AI Agents
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yuvallu would you be able to look into this and confirm if this is in fact a regression?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@saulshanabrook Yes, it's a real regression from this PR, thanks for flagging it. It affects sharing only, not the result.
_exprs_multiple_parentsnever looked inside aGetCostDecl, which didn't matter before because each cost-lookup argument was scanned again when it was converted. Withlets_hoisted=Truepassed to those arguments, a subexpression shared inside aget_cost(...)argument of a scanned expression was written out twice instead of being let-bound. For example, inCostBox(get_cost(CostRoot(CostPair(shared, shared))))thesharedleaf gets one let on main but is inlined twice on 463f2bc.Fixed in b0fcdc0 with the suggested change. Both traversals that walk an expression's children now treat
GetCostDecllikeCallDecl: the scan, and_contains_unbound_var, which decides what may be hoisted (so an unbound variable inside a cost lookup still keeps its subexpression out of a top-level let). The scan now visits every child that is converted withlets_hoisted, and no other case of_expr_to_eggrecurses into children. The newtest_shared_subexpression_inside_cost_lookup_is_hoistedfails on 463f2bc (no let) and passes on main and with the fix.I also logged every command the whole test suite sends to egglog, with main's
egraph_state.pyand with this branch (155k commands). They are identical, except that in the new test the one let is emitted two commands earlier (before the unrelatedCostBoxdeclarations), with the same name and body. Full suite: 956 passed, ruff and mypy clean.Unrelated, noticed while writing the test:
get_cost(x) + i64(1)raisesKeyError: Ident(name='i64', module='egglog.builtins'), also on main, because the returned expression only carriesx's declarations. Happy to open a separate issue if that's useful.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure open another issue for that, thanks for finding that bug!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.