Skip to content

Conversation

aschackmull
Copy link
Contributor

QA for 2.23.1 highlighted performance regressions in two repos for Java NullMaybe.ql. The underlying reason was that the control-flow reachability calculated too many splits with irrelevant values that couldn't determine any relevant branches.

This PR restricts the tracked values to those that may affect a relevant branch and at the same time improves precision by including the branch-related value-split in the universal quantification (the forall). We prioritise tracked values such that singletons take priority over any other value as that's maximally precise, for non-singletons we discard those values that cannot determine a particular branch.

@Copilot Copilot AI review requested due to automatic review settings September 25, 2025 12:45
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR addresses performance regressions in Java NullMaybe.ql by optimizing control-flow reachability calculations. The changes restrict tracked values to only those that may affect relevant branches while improving precision through singleton value prioritization.

  • Restricts tracked values to those that can determine relevant branches
  • Prioritizes singleton values for maximum precision
  • Modifies the universal quantification to include branch-related value-splits

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
Guards.qll Adds isSingleton() predicate to check if a value represents a precise singleton
ControlFlow.qll Major refactoring to optimize value tracking by filtering irrelevant values and prioritizing singletons

@aschackmull aschackmull force-pushed the controlflowreach/perf2 branch from 603ccd1 to ab77d0f Compare September 25, 2025 13:02
@aschackmull aschackmull force-pushed the controlflowreach/perf2 branch from ab77d0f to 109b6a1 Compare September 25, 2025 13:03
@aschackmull
Copy link
Contributor Author

Dca looks good. A few additional FPs are removed and performance improves.

@aschackmull aschackmull added the no-change-note-required This PR does not need a change note label Sep 26, 2025
Copy link
Contributor

@hvitved hvitved left a comment

Choose a reason for hiding this comment

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

Very nice! Only some trivial coments.

def.getDefinition() = e and
exprHasValue(e, gv) and
not exists(GuardValue gv0 | exprHasValue(e, gv0) and smaller(gv0, gv))
(exists(GuardValue gv0 | exprHasValue(e, gv0) and gv0.isSingleton()) implies gv.isSingleton())
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: I would prefer

any(GuardValue gv0 | exprHasValue(e, gv0)).isSingleton() implies gv.isSingleton()

ssaControlsBranchEdge(t, bb1, bb2, gv) and
not exists(GuardValue gv0 | ssaControlsBranchEdge(t, bb1, bb2, gv0) and smaller(gv0, gv)) and
(
exists(GuardValue gv0 | ssaControlsBranchEdge(t, bb1, bb2, gv0) and gv0.isSingleton())
Copy link
Contributor

Choose a reason for hiding this comment

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

Again, I think any(GuardValue gv0 | ssaControlsBranchEdge(t, bb1, bb2, gv0)).isSingleton() is a bit nicer.

SourceVariable src, BasicBlock bb1, BasicBlock bb2, SourceVariable var, SsaDefinition t,
GuardValueOrAny val
SourceVariable src, BasicBlock bb1, BasicBlock bb2, SourceVariable var, GuardValue condgv,
SsaDefinition t, GuardValueOption val
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the QL doc ought to mention condgv.

private predicate stepSsaValuePhi(
SourceVariable src, BasicBlock bb1, BasicBlock bb2, SourceVariable var, SsaDefinition t1,
SsaDefinition t2, GuardValueOrAny val
SourceVariable src, BasicBlock bb1, BasicBlock bb2, SourceVariable var, GuardValue condgv,
Copy link
Contributor

Choose a reason for hiding this comment

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

QL doc for condgv.

private predicate stepSsaValueNoRedef(
SourceVariable src, BasicBlock bb1, BasicBlock bb2, SourceVariable var, SsaDefinition t,
GuardValue val
SourceVariable src, BasicBlock bb1, BasicBlock bb2, SourceVariable var, GuardValue condgv,
Copy link
Contributor

Choose a reason for hiding this comment

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

Same.

private predicate sourceReachesBlockWithTrackedVar(
SsaDefinition srcDef, BasicBlock srcBb, SsaDefinition def, BasicBlock bb, FinallyStack fs,
SsaDefOption tracked, GuardValueExt val, SourceVariable var
SsaDefOption tracked, GuardValueOption val, SourceVariable var, GuardValue condgv
Copy link
Contributor

Choose a reason for hiding this comment

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

same

@aschackmull
Copy link
Contributor Author

Very nice! Only some trivial coments.

All fixed!

@aschackmull aschackmull merged commit f4388c8 into github:main Sep 26, 2025
36 checks passed
@aschackmull aschackmull deleted the controlflowreach/perf2 branch September 26, 2025 12:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
no-change-note-required This PR does not need a change note
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants