Skip to content

C++: Fix join in TranslatedAssertion::getVariable#21750

Merged
MathiasVP merged 1 commit intomainfrom
fix-join-in-assertions-in-ir
Apr 23, 2026
Merged

C++: Fix join in TranslatedAssertion::getVariable#21750
MathiasVP merged 1 commit intomainfrom
fix-join-in-assertions-in-ir

Conversation

@MathiasVP
Copy link
Copy Markdown
Contributor

Before (on boost):

[2026-04-23 10:13:26] Evaluated non-recursive predicate _#stmtsMerge_Element::Element.getParentScope/0#dispred#b0dbb25c_10#join_rhs_Location::Location.getSt__#shared@b90e68i7 in 161ms (size: 520213).
Evaluated relational algebra for predicate _#stmtsMerge_Element::Element.getParentScope/0#dispred#b0dbb25c_10#join_rhs_Location::Location.getSt__#shared@b90e68i7 with tuple counts:
          523974   ~3%    {2} r1 = SCAN stmts OUTPUT In.2, In.0
          523974   ~0%    {2}    | JOIN WITH `Location::Location.getStartLine/0#d54f9e6c` ON FIRST 1 OUTPUT Lhs.1, Rhs.1
           13494   ~0%    {4}    | JOIN WITH `TranslatedAssertion::hasAVariable/3#76a1d6b7#bbf_102#join_rhs` ON FIRST 1 OUTPUT Rhs.2, Lhs.0, Lhs.1, Rhs.1
        77064501   ~0%    {4}    | JOIN WITH `Element::Element.getParentScope/0#dispred#b0dbb25c_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Lhs.3
          603448   ~1%    {5}    | JOIN WITH `Variable::Variable.getLocation/0#dispred#ffcb49bd` ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Lhs.3, Lhs.0
          603448   ~0%    {5}    | JOIN WITH `Location::Location.getStartLine/0#d54f9e6c` ON FIRST 1 OUTPUT Lhs.1, Lhs.2, Lhs.3, Lhs.4, Rhs.1
                          {5}    | REWRITE WITH TEST InOut.4 < InOut.1
          520916   ~0%    {3}    | SCAN OUTPUT In.3, In.0, In.2
                          return r1

[2026-04-23 10:13:26] Evaluated non-recursive predicate _Declaration::Declaration.hasName/1#dispred#ea371278#fb__#stmtsMerge_Element::Element.getParentScope__#unique_range@b5fca76q in 26ms (size: 520213).
Evaluated relational algebra for predicate _Declaration::Declaration.hasName/1#dispred#ea371278#fb__#stmtsMerge_Element::Element.getParentScope__#unique_range@b5fca76q with tuple counts:
        520213  ~0%    {4} r1 = JOIN `_#stmtsMerge_Element::Element.getParentScope/0#dispred#b0dbb25c_10#join_rhs_Location::Location.getSt__#shared` WITH `Declaration::Declaration.hasName/1#dispred#ea371278#fb` ON FIRST 1 OUTPUT Lhs.1, Lhs.2, Rhs.1, Lhs.0
                       return r1

[2026-04-23 10:13:26] Evaluated non-recursive predicate _Declaration::Declaration.hasName/1#dispred#ea371278#fb__#stmtsMerge_Element::Element.getParentScope__#unique_term@255cb1v4 in 40ms (size: 520213).
Evaluated relational algebra for predicate _Declaration::Declaration.hasName/1#dispred#ea371278#fb__#stmtsMerge_Element::Element.getParentScope__#unique_term@255cb1v4 with tuple counts:
        520213  ~0%    {5} r1 = JOIN `_#stmtsMerge_Element::Element.getParentScope/0#dispred#b0dbb25c_10#join_rhs_Location::Location.getSt__#shared` WITH `Declaration::Declaration.hasName/1#dispred#ea371278#fb` ON FIRST 1 OUTPUT Lhs.1, Lhs.2, Rhs.1, Lhs.0, Lhs.0
                       return r1

[2026-04-23 10:13:26] Evaluated non-recursive predicate TranslatedAssertion::getVariable/2#f24612a9#bbf@207815ik in 106ms (size: 466).
Evaluated relational algebra for predicate TranslatedAssertion::getVariable/2#f24612a9#bbf@207815ik with tuple counts:
        515953   ~0%    {4} r1 = AGGREGATE `_Declaration::Declaration.hasName/1#dispred#ea371278#fb__#stmtsMerge_Element::Element.getParentScope__#unique_range`, `_Declaration::Declaration.hasName/1#dispred#ea371278#fb__#stmtsMerge_Element::Element.getParentScope__#unique_term` ON In.4 WITH UNIQUE OUTPUT In.0, In.1, In.2, Agg.0
        515953   ~0%    {4}    | SCAN OUTPUT In.3, In.0, In.1, In.2
          7063   ~4%    {4}    | JOIN WITH Variable::LocalScopeVariable#3aae4a09 ON FIRST 1 OUTPUT Lhs.2, Lhs.1, Lhs.0, Lhs.3
                    
          7063   ~5%    {5} r2 = JOIN r1 WITH `TranslatedAssertion::assertion0/3#fd23c70e` ON FIRST 2 OUTPUT Lhs.2, Lhs.0, Lhs.3, Rhs.2, _
          7063   ~0%    {5}    | REWRITE WITH Out.4 := "([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?<\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)"
           726   ~0%    {7}    | JOIN WITH PRIMITIVE regexpCapture#bbff ON Lhs.3,Lhs.4
                        {7}    | REWRITE WITH TEST InOut.2 = InOut.6
            77   ~5%    {4}    | SCAN OUTPUT In.1, _, In.0, In.5
            77   ~3%    {3}    | REWRITE WITH Tmp.1 := 1, Out.1 := (In.3 - Tmp.1) KEEPING 3
                    
          7063   ~5%    {5} r3 = JOIN r1 WITH `TranslatedAssertion::assertion0/3#fd23c70e` ON FIRST 2 OUTPUT Lhs.2, Lhs.0, Lhs.3, Rhs.2, _
          7063   ~0%    {5}    | REWRITE WITH Out.4 := "([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?>\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)"
           558   ~0%    {7}    | JOIN WITH PRIMITIVE regexpCapture#bbff ON Lhs.3,Lhs.4
                        {7}    | REWRITE WITH TEST InOut.2 = InOut.6
            40   ~0%    {4}    | SCAN OUTPUT In.1, _, In.0, In.5
            40   ~0%    {3}    | REWRITE WITH Tmp.1 := 1, Out.1 := (In.3 - Tmp.1) KEEPING 3
                    
          7063   ~5%    {5} r4 = JOIN r1 WITH `TranslatedAssertion::assertion0/3#fd23c70e` ON FIRST 2 OUTPUT Lhs.2, Lhs.0, Lhs.3, Rhs.2, _
          7063   ~0%    {5}    | REWRITE WITH Out.4 := "([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?!=\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)"
          1304   ~0%    {7}    | JOIN WITH PRIMITIVE regexpCapture#bbff ON Lhs.3,Lhs.4
                        {7}    | REWRITE WITH TEST InOut.2 = InOut.6
           156   ~8%    {4}    | SCAN OUTPUT In.1, _, In.0, In.5
           156   ~0%    {3}    | REWRITE WITH Tmp.1 := 1, Out.1 := (In.3 - Tmp.1) KEEPING 3
                    
          7063   ~5%    {5} r5 = JOIN r1 WITH `TranslatedAssertion::assertion0/3#fd23c70e` ON FIRST 2 OUTPUT Lhs.2, Lhs.0, Lhs.3, Rhs.2, _
          7063   ~0%    {5}    | REWRITE WITH Out.4 := "([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?<=\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)"
           312   ~1%    {7}    | JOIN WITH PRIMITIVE regexpCapture#bbff ON Lhs.3,Lhs.4
                        {7}    | REWRITE WITH TEST InOut.2 = InOut.6
            48   ~0%    {4}    | SCAN OUTPUT In.1, _, In.0, In.5
            48   ~0%    {3}    | REWRITE WITH Tmp.1 := 1, Out.1 := (In.3 - Tmp.1) KEEPING 3
                    
          7063   ~5%    {5} r6 = JOIN r1 WITH `TranslatedAssertion::assertion0/3#fd23c70e` ON FIRST 2 OUTPUT Lhs.2, Lhs.0, Lhs.3, Rhs.2, _
          7063   ~0%    {5}    | REWRITE WITH Out.4 := "([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?==\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)"
           442   ~0%    {7}    | JOIN WITH PRIMITIVE regexpCapture#bbff ON Lhs.3,Lhs.4
                        {7}    | REWRITE WITH TEST InOut.2 = InOut.6
            77   ~0%    {4}    | SCAN OUTPUT In.1, _, In.0, In.5
            77   ~0%    {3}    | REWRITE WITH Tmp.1 := 1, Out.1 := (In.3 - Tmp.1) KEEPING 3
                    
          7063   ~5%    {5} r7 = JOIN r1 WITH `TranslatedAssertion::assertion0/3#fd23c70e` ON FIRST 2 OUTPUT Lhs.2, Lhs.0, Lhs.3, Rhs.2, _
          7063   ~2%    {5}    | REWRITE WITH Out.4 := "([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?>=\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)"
           762   ~0%    {7}    | JOIN WITH PRIMITIVE regexpCapture#bbff ON Lhs.3,Lhs.4
                        {7}    | REWRITE WITH TEST InOut.2 = InOut.6
            68   ~0%    {4}    | SCAN OUTPUT In.1, _, In.0, In.5
            68   ~0%    {3}    | REWRITE WITH Tmp.1 := 1, Out.1 := (In.3 - Tmp.1) KEEPING 3
                    
           466   ~0%    {3} r8 = r2 UNION r3 UNION r4 UNION r5 UNION r6 UNION r7
                        return r8

[2026-04-23 10:13:26] Evaluated non-recursive predicate project#TranslatedAssertion::getVariable/2#f24612a9#bbf@0cd8edj8 in 0ms (size: 466).
Evaluated relational algebra for predicate project#TranslatedAssertion::getVariable/2#f24612a9#bbf@0cd8edj8 with tuple counts:
        466  ~1%    {2} r1 = SCAN `TranslatedAssertion::getVariable/2#f24612a9#bbf` OUTPUT In.0, In.1
        466  ~1%    {2}    | STREAM DEDUP
                    return r1

After:

[2026-04-23 12:03:17] Evaluated non-recursive predicate _#stmtsMerge_Location::Location.getStartLine/0#d54f9e6c_TranslatedAssertion::hasAVariable/3#76a1d6b7__#shared@4cb5aa3e in 66ms (size: 715).
Evaluated relational algebra for predicate _#stmtsMerge_Location::Location.getStartLine/0#d54f9e6c_TranslatedAssertion::hasAVariable/3#76a1d6b7__#shared@4cb5aa3e with tuple counts:
        523974  ~3%    {2} r1 = SCAN stmts OUTPUT In.2, In.0
        523974  ~0%    {2}    | JOIN WITH `Location::Location.getStartLine/0#d54f9e6c` ON FIRST 1 OUTPUT Lhs.1, Rhs.1
          1320  ~0%    {4}    | JOIN WITH `project#TranslatedAssertion::foo/4#c1510ca9_102#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.0, Lhs.1, Rhs.2
          8454  ~3%    {5}    | JOIN WITH `TranslatedAssertion::hasAVariable/3#76a1d6b7` ON FIRST 2 OUTPUT Lhs.3, Rhs.2, Lhs.1, Lhs.2, Lhs.0
           863  ~0%    {6}    | JOIN WITH `TranslatedAssertion::hasNameAndParentScope/3#9c2e3c4b` ON FIRST 2 OUTPUT Rhs.2, Lhs.2, Lhs.3, Lhs.4, Lhs.0, Lhs.1
           863  ~0%    {7}    | JOIN WITH `Variable::Variable.getLocation/0#dispred#ffcb49bd` ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Lhs.3, Lhs.4, Lhs.5, Lhs.0
           863  ~2%    {7}    | JOIN WITH `Location::Location.getStartLine/0#d54f9e6c` ON FIRST 1 OUTPUT Lhs.1, Lhs.2, Lhs.3, Lhs.4, Lhs.5, Lhs.6, Rhs.1
           715  ~2%    {7}    | REWRITE WITH TEST InOut.6 < InOut.1
                       return r1

[2026-04-23 12:03:17] Evaluated non-recursive predicate __#stmtsMerge_Location::Location.getStartLine/0#d54f9e6c_TranslatedAssertion::hasAVariable/3#76a1d6b__#unique_range@03333d50 in 0ms (size: 715).
Evaluated relational algebra for predicate __#stmtsMerge_Location::Location.getStartLine/0#d54f9e6c_TranslatedAssertion::hasAVariable/3#76a1d6b__#unique_range@03333d50 with tuple counts:
        715  ~0%    {5} r1 = SCAN `_#stmtsMerge_Location::Location.getStartLine/0#d54f9e6c_TranslatedAssertion::hasAVariable/3#76a1d6b7__#shared` OUTPUT In.0, In.2, In.3, In.5, In.4
                    return r1

[2026-04-23 12:03:17] Evaluated non-recursive predicate __#stmtsMerge_Location::Location.getStartLine/0#d54f9e6c_TranslatedAssertion::hasAVariable/3#76a1d6b__#unique_term@2cb192ht in 0ms (size: 715).
Evaluated relational algebra for predicate __#stmtsMerge_Location::Location.getStartLine/0#d54f9e6c_TranslatedAssertion::hasAVariable/3#76a1d6b__#unique_term@2cb192ht with tuple counts:
        715  ~0%    {6} r1 = SCAN `_#stmtsMerge_Location::Location.getStartLine/0#d54f9e6c_TranslatedAssertion::hasAVariable/3#76a1d6b7__#shared` OUTPUT In.0, In.2, In.3, In.5, In.4, In.5
                    return r1

[2026-04-23 12:03:17] Evaluated non-recursive predicate TranslatedAssertion::foo/4#c1510ca9_0231#join_rhs@38b0d20b in 0ms (size: 1320).
Evaluated relational algebra for predicate TranslatedAssertion::foo/4#c1510ca9_0231#join_rhs@38b0d20b with tuple counts:
        1320  ~0%    {4} r1 = SCAN `TranslatedAssertion::foo/4#c1510ca9` OUTPUT In.0, In.2, In.3, In.1
                     return r1

[2026-04-23 12:03:17] Found predicate Variable::LocalScopeVariable#3aae4a09@f207e3e9 in the relation cache (size: 380828)
[2026-04-23 12:03:17] Evaluated non-recursive predicate TranslatedAssertion::getVariable/2#f24612a9@3cd966nd in 0ms (size: 466).
Evaluated relational algebra for predicate TranslatedAssertion::getVariable/2#f24612a9@3cd966nd with tuple counts:
        709  ~3%    {4} r1 = AGGREGATE `__#stmtsMerge_Location::Location.getStartLine/0#d54f9e6c_TranslatedAssertion::hasAVariable/3#76a1d6b__#unique_range`, `__#stmtsMerge_Location::Location.getStartLine/0#d54f9e6c_TranslatedAssertion::hasAVariable/3#76a1d6b__#unique_term` ON In.5 WITH UNIQUE OUTPUT In.0, In.1, In.2, Agg.0
        709  ~3%    {4}    | SCAN OUTPUT In.3, In.0, In.1, In.2
        466  ~0%    {4}    | JOIN WITH Variable::LocalScopeVariable#3aae4a09 ON FIRST 1 OUTPUT Lhs.2, Lhs.1, Lhs.3, Lhs.0
        466  ~0%    {3}    | JOIN WITH `TranslatedAssertion::foo/4#c1510ca9_0231#join_rhs` ON FIRST 3 OUTPUT Lhs.0, Rhs.3, Lhs.3
                    return r1

Copilot AI review requested due to automatic review settings April 23, 2026 11:14
@MathiasVP MathiasVP requested a review from a team as a code owner April 23, 2026 11:14
@github-actions github-actions Bot added the C++ label Apr 23, 2026
@MathiasVP MathiasVP changed the title C++: Fix join in getVariable C++: Fix join in TranslatedAssertion::getVariable Apr 23, 2026
@MathiasVP MathiasVP added the no-change-note-required This PR does not need a change note label Apr 23, 2026
Copy link
Copy Markdown
Contributor

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 updates the internal C++ IR assertion-variable lookup logic in TranslatedAssertion.qll to avoid an expensive join pattern in getVariable, aligning with the provided before/after relational algebra evidence (significant reduction in intermediate tuple counts and runtime).

Changes:

  • Introduces pragma[nomagic] helper predicates (hasAssertionOperand/4, hasNameAndParentScope/3, hasParentScope/2) to restructure the getVariable/2 computation.
  • Refactors getVariable/2 to use the new helpers and a unique(Variable v, Element parentScope | ...) form intended to improve join behavior.
Show a summary per file
File Description
cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedAssertion.qll Refactors getVariable by adding helper predicates and nomagic pragmas to change join structure and improve evaluation performance.

Copilot's findings

  • Files reviewed: 1/1 changed files
  • Comments generated: 0

Copy link
Copy Markdown
Contributor

@jketema jketema left a comment

Choose a reason for hiding this comment

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

Happy with this if DCA is happy.

@MathiasVP
Copy link
Copy Markdown
Contributor Author

DCA was uneventful

@MathiasVP MathiasVP merged commit 82c99a5 into main Apr 23, 2026
22 of 23 checks passed
@MathiasVP MathiasVP deleted the fix-join-in-assertions-in-ir branch April 23, 2026 16:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C++ 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.

3 participants