[SQL] Context-sensitive conditionals optimization#6335
Conversation
mythical-fred
left a comment
There was a problem hiding this comment.
Review
The optimization is well-targeted. The ContainsIf short-circuit avoids paying analysis cost on if-free expressions, and the EquivalenceContext-based comparison correctly handles alpha-renaming (testAliasedVariable proves it). The ResolveReferences.preorder(DBSPLetExpression) fix -- initializer in outer scope, body in inner scope -- is the right semantics that was missing, and dropping the let declaration's postorder cleanup into the inlined preorder is the right shape. Three IR-level unit tests cover the basic substitution, the equivalent-comparison case, and the alpha-renaming negative case.
Coverage gaps worth filling before merge
-
No SQL-level regression test. The PR description shows the
timestamp_trunc_weekcodegen win beautifully, but there is noRegression3Testscase that compiles that SQL and pins the post-optimization shape. The IR-level unit tests are good but a SQL fixture is what catches future regressions in optimizer ordering -- e.g. the newCircuitRewriter(new SimplifyConditionals(...), false)placement beforeSimplifyinCircuitOptimizer.createOptimizer, or interactions with the joins/limiters that run after it. Per the workspace rule on behavior changes without tests, this would normally block; soft-blocking here because the IR tests do exist and the description shows the wins, but please add at least one SQL-level fixture before merge. -
No nullable-bool negative test. The optimization explicitly excludes nullable booleans (
!expression.getType().mayBeNullincheckIfConstant). That is the right conservative choice today, but there should be a unit test that proves it: feedif (a: bool?) { a }and assert the innerais not rewritten. Otherwise a future relaxation has no canary.
Inline notes
9 comments below covering: complexity bound, Scopes.clone() aliasing contract, enforce(subst != null) missing diagnostic, missing @Override, temp-file accumulation in QATests, and a coverage note on the MultiCrateTests.qaTests removal.
The big-picture design -- flow-sensitive dataflow over the IR using SymbolicInterpreter + EquivalenceContext for alpha-renamed equality -- is the right shape. Once the SQL-level test and the nullable-bool negative test land, this is good to go from my side.
mythical-fred
left a comment
There was a problem hiding this comment.
Re-APPROVE on 7796aa1. Two of my prior nits cleanly addressed: @Override added to postorder(DBSPIsNullExpression), and the Scopes.clone() lastClone/version memoization removed — eliminates the implicit aliasing contract and matches the explicit-copy semantics callers expect. The other three threads (constant-prop excludes nullable booleans; complexity bound on linear scan; enforce message in DBSPVariablePath) are non-blocking and can land as follow-ups. The replaceConnectors/deleteOnExit and MultiCrateTests doc nits also still apply but aren't blockers.
|
|
||
| /** Simplifies expressions based on their context within a conditional; | ||
| * if (a) { ... a ... } simplifies the second occurrence of 'a' to 'true'. */ | ||
| public class SimplifyConditionals implements IRTransform { |
There was a problem hiding this comment.
You'd think calcite would have this optimization pass already
There was a problem hiding this comment.
These are expressions that are synthesized by our compiler, usually from inlining functions.
There was a problem hiding this comment.
This happens when we fuse multiple consecutive operators; this is something Calcite cannot do in general, it's set of operators is too weak to represent all we need.
| .appendSupplier(expression::toString) | ||
| .append(" = ") | ||
| .append(value); | ||
| Utilities.putNew(this.constants, expression, value); |
There was a problem hiding this comment.
you need an Utilities method to put something in a Map?
There was a problem hiding this comment.
putNew checks that the value doesn't exist already
|
good, I will let you rest a bit and send you more of these. |
Signed-off-by: Mihai Budiu <mbudiu@feldera.com>
|
I will merge this after the current release is finished, to minimize possible disruptions. We have enough changes for now. |
mythical-fred
left a comment
There was a problem hiding this comment.
Squash-rebase of previously approved work onto main — no new substantive changes. Still LGTM.
Fixes #5507
This implements a flow-sensitive dataflow analysis which tracks expressions that are constant within a conditional. For example, given:
if x { ... x ... } else { ... x ... }in thethenpart of theifxcan be substituted withtrue, and in theelsepart it can be substituted withfalse.Checklist
Code generated before:
Code generated after: