[SPARK-57217][SQL] Skip dead null assignments in If codegen when branch values are non-nullable#56278
[SPARK-57217][SQL] Skip dead null assignments in If codegen when branch values are non-nullable#56278LuciferYang wants to merge 2 commits into
Conversation
…ch values are non-nullable If.doGenCode emitted ev.isNull = branchEval.isNull; for each branch after declaring boolean ev.isNull = false;. For a non-nullable branch that assignment is a dead ev.isNull = false;, so drop it. When the whole If is non-nullable, also drop the boolean ev.isNull declaration and return isNull = FalseLiteral, letting parent operators skip null checks on the result. Refactored via small Block values (isNullDecl/setTrueIsNull/setFalseIsNull, EmptyBlock when not needed). Follows the non-nullable-children dead-branch pattern and the standard non-nullable codegen contract; shrinks the generated method (and, for non-nullable If, the downstream null checks). Adds checkEvaluation cases with nullable BoundReference branches to cover the both-children-nullable codegen template. Part of SPARK-56908.
dongjoon-hyun
left a comment
There was a problem hiding this comment.
+1, LGTM. Thank you, @LuciferYang .
|
Flagging against the scope guidance added to the umbrella SPARK-56908. This is a source-only dead-branch elimination: Janino constant-folds Before merging, please confirm this removes more than source text (a |
|
Close this PR after checking against the preceding criteria. |
What changes were proposed in this pull request?
If.doGenCodealways emitted, for each branch, anev.isNull = branchEval.isNull;assignment after theboolean ev.isNull = false;declaration. For a non-nullable branch that assignment isev.isNull = false;, which is dead (ev.isNullis already initialized tofalse). This drops that assignment for a non-nullable branch. When the wholeIfis non-nullable (both branches non-nullable), it also drops theboolean ev.isNull = false;declaration and returnsisNull = FalseLiteral, which lets parent operators skip null checks on the result.The body is refactored into small
Blockvalues (isNullDecl/setTrueIsNull/setFalseIsNull,EmptyBlockwhen not needed). This follows the SPARK-56908 non-nullable-children dead-branch pattern and the standard non-nullable codegen contract (isNull = FalseLiteral).Why are the changes needed?
It removes dead assignments (and, for a non-nullable
If, theev.isNullvariable itself), shrinking the generated method. BecauseIfis ubiquitous and often nested, theisNull = FalseLiteralpropagation additionally lets parent operators drop null checks on a non-nullableIfresult. This helps with the JVM 64KB method / constant-pool limits, Janino compile time, and JIT work. Part of SPARK-56908.Does this PR introduce any user-facing change?
No.
If.nullable,dataType, andevalare unchanged, so results and output-schema nullability are identical; only the generated Java is smaller.How was this patch tested?
Existing
ConditionalExpressionSuite"if" / "case when" (the latter delegates single-branch codegen toIf) and the SPARK-49396 nullability test, plus addedcheckEvaluationcases with nullableBoundReferencebranches that exercise the both-children-nullable codegen template (the existing non-null-literal cases now take the dead-branch-skipping paths instead).checkEvaluationruns the interpreted and codegen paths; behavior is unchanged.Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus 4.8)