Skip to content

Commit 0aad85c

Browse files
yoffCopilot
andcommitted
Python: use the shared SSA facade in the ESSA adapter
The adapter already instantiates Impl::MakeSsa<SsaInput>, so consume its cached public API for ordinary reads and phi inputs. Synthetic normal-exit uses cannot be represented as SsaInput::Expr, so retain a narrow cached raw projection filtered to normal exits. Adjacency likewise remains a cached adapter boundary because MakeSsa does not expose it. This avoids adding broad cache policy to shared SSA. Exact #156 to #158 DCA #39117 completed 48/48 with exact outputs, -0.748% aggregate query time, -0.541% median, and -3.29% DIL. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: f3f2a493-1e3f-402e-b70d-4b558ac6bf29
1 parent f49429a commit 0aad85c

1 file changed

Lines changed: 25 additions & 9 deletions

File tree

  • python/ql/lib/semmle/python/dataflow/new/internal

‎python/ql/lib/semmle/python/dataflow/new/internal/SsaImpl.qll‎

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -334,13 +334,13 @@ private module SsaInput implements Impl::SsaInputSig {
334334

335335
module Ssa = Impl::MakeSsa<SsaInput>;
336336

337-
final class Definition = Impl::Definition;
337+
final class Definition = Ssa::SsaDefinition;
338338

339-
final class WriteDefinition = Impl::WriteDefinition;
339+
final class WriteDefinition = Ssa::SsaWriteDefinition;
340340

341-
final class UncertainWriteDefinition = Impl::UncertainWriteDefinition;
341+
final class UncertainWriteDefinition = Ssa::SsaUncertainWrite;
342342

343-
final class PhiNode = Impl::PhiNode;
343+
final class PhiNode = Ssa::SsaPhiDefinition;
344344

345345
// ===========================================================================
346346
// ESSA-shaped adapter layer
@@ -523,7 +523,7 @@ class PhiFunction extends PhiNode {
523523
* the phi from one of its predecessor blocks). Mirrors legacy
524524
* ESSA's `PhiFunction.getAnInput()`.
525525
*/
526-
Ssa::SsaDefinition getAnInput() { Impl::phiHasInputFromBlock(this, result, _) }
526+
Ssa::SsaDefinition getAnInput() { result = this.(Ssa::SsaPhiDefinition).getAnInput() }
527527
}
528528

529529
/** An ESSA definition (legacy-shaped). */
@@ -537,6 +537,19 @@ class EssaVariable extends Ssa::SsaDefinition {
537537
/** Gets the underlying SSA definition (legacy name). */
538538
Ssa::SsaDefinition getDefinition() { result = this }
539539

540+
/**
541+
* Gets a synthetic normal-exit use of this definition. These uses have no
542+
* `SsaInput::Expr`, so they cannot be exposed by `SsaDefinition.getARead()`.
543+
*/
544+
cached
545+
private Cfg::ControlFlowNode getASyntheticExitUse() {
546+
exists(CfgImpl::BasicBlock bb, int i |
547+
Impl::ssaDefReachesRead(this.getSourceVariable(), this, bb, i) and
548+
bb.getNode(i) = result and
549+
result.isNormalExit()
550+
)
551+
}
552+
540553
/**
541554
* Gets a CFG node where this definition is used. Includes regular
542555
* `Name` reads as well as the synthetic scope-exit "use" registered
@@ -545,10 +558,9 @@ class EssaVariable extends Ssa::SsaDefinition {
545558
* from `SsaSourceVariable`.
546559
*/
547560
Cfg::ControlFlowNode getAUse() {
548-
exists(CfgImpl::BasicBlock bb, int i |
549-
Impl::ssaDefReachesRead(this.getSourceVariable(), this, bb, i) and
550-
bb.getNode(i) = result
551-
)
561+
result.getNode() = this.(Ssa::SsaDefinition).getARead().asExpr()
562+
or
563+
result = this.getASyntheticExitUse()
552564
}
553565

554566
/** Gets the (textual) name of the underlying variable. */
@@ -563,8 +575,10 @@ class EssaVariable extends Ssa::SsaDefinition {
563575
* library. Provides the same interface as legacy
564576
* `semmle.python.essa.SsaCompute::AdjacentUses`.
565577
*/
578+
cached
566579
module AdjacentUses {
567580
/** Holds if `nodeFrom` and `nodeTo` are adjacent uses of the same SSA variable. */
581+
cached
568582
predicate adjacentUseUse(Cfg::NameNode nodeFrom, Cfg::NameNode nodeTo) {
569583
exists(CfgImpl::BasicBlock bb1, int i1, CfgImpl::BasicBlock bb2, int i2 |
570584
Impl::adjacentUseUse(bb1, i1, bb2, i2, _, _) and
@@ -574,6 +588,7 @@ module AdjacentUses {
574588
}
575589

576590
/** Holds if `use` is a first use of definition `def`. */
591+
cached
577592
predicate firstUse(Ssa::SsaDefinition def, Cfg::NameNode use) {
578593
exists(CfgImpl::BasicBlock bb, int i |
579594
Impl::firstUse(def, bb, i, _) and
@@ -585,6 +600,7 @@ module AdjacentUses {
585600
* Holds if `use` is any reachable use of definition `def`. Combines
586601
* `firstUse` with transitive use-use adjacency.
587602
*/
603+
cached
588604
predicate useOfDef(Ssa::SsaDefinition def, Cfg::NameNode use) {
589605
firstUse(def, use)
590606
or

0 commit comments

Comments
 (0)