Skip to content

Commit d686347

Browse files
committed
C++: Optimize EnumSwitch.getAMissingCase
The `cpp/missing-case-in-switch` performed badly on some snapshots, to the extent where it was as slow as the most expensive IR stages (example: ChakraCore). This commit makes it faster, removing a `pragma[noopt]` along the way. The intermediate tuple counts on a customer codebase drop from 84M to 3M, while the content hash of `getAMissingCase` is the same. Before: (124s) Tuple counts for Stmt::EnumSwitch::getAMissingCase#ff#antijoin_rhs: 20867789 ~0% {3} r1 = JOIN Stmt::SwitchStmt::getASwitchCase_dispred#ff AS L WITH Stmt::EnumSwitch::getAMissingCase#ff#shared AS R ON FIRST 1 OUTPUT L.<1>, R.<0>, R.<1> 20122830 ~0% {3} r2 = JOIN r1 WITH Stmt::SwitchCase::getExpr_dispred#ff AS R ON FIRST 1 OUTPUT R.<1>, r1.<1>, r1.<2> 20122830 ~0% {3} r3 = JOIN r2 WITH Expr::Expr::getValue_dispred#ff AS R ON FIRST 1 OUTPUT r2.<2>, r2.<1>, R.<1> 83961918 ~0% {4} r4 = JOIN r3 WITH Enum::EnumConstant::getInitializer_dispred#ff AS R ON FIRST 1 OUTPUT R.<1>, r3.<1>, r3.<0>, r3.<2> 83961918 ~0% {4} r5 = JOIN r4 WITH initialisers AS R ON FIRST 1 OUTPUT R.<2>, r4.<3>, r4.<1>, r4.<2> 234348 ~185% {2} r6 = JOIN r5 WITH Expr::Expr::getValue_dispred#ff AS R ON FIRST 2 OUTPUT r5.<2>, r5.<3> return r6 ... (124s) Tuple counts for Stmt::EnumSwitch::getAMissingCase#ff: 663127 ~4% {2} r1 = Stmt::EnumSwitch::getAMissingCase#ff#shared AS L AND NOT Stmt::EnumSwitch::getAMissingCase#ff#antijoin_rhs AS R(L.<0>, L.<1>) return r1 (124s) Registering Stmt::EnumSwitch::getAMissingCase#ff + [] with content 2060ff326cvhihcsvoph6k9divuv4 (124s) >>> Wrote relation Stmt::EnumSwitch::getAMissingCase#ff with 663127 rows and 2 columns. After: (5s) Tuple counts for Stmt::EnumSwitch::getAMissingCase_dispred#ff#antijoin_rhs: 746029 ~0% {2} r1 = JOIN Stmt::EnumSwitch::getAMissingCase_dispred#ff#shared AS L WITH Enum::Enum::getAnEnumConstant_dispred#ff AS R ON FIRST 1 OUTPUT R.<1>, L.<1> 3116197 ~2% {3} r2 = JOIN r1 WITH Enum::EnumConstant::getInitializer_dispred#ff AS R ON FIRST 1 OUTPUT R.<1>, r1.<1>, r1.<0> 3116197 ~0% {3} r3 = JOIN r2 WITH initialisers AS R ON FIRST 1 OUTPUT R.<2>, r2.<1>, r2.<2> 3116197 ~311% {3} r4 = JOIN r3 WITH Expr::Expr::getValue_dispred#ff AS R ON FIRST 1 OUTPUT r3.<1>, R.<1>, r3.<2> 234348 ~185% {2} r5 = JOIN r4 WITH Stmt::EnumSwitch::matchesValue#ff AS R ON FIRST 2 OUTPUT r4.<0>, r4.<2> return r5 (5s) Registering Stmt::EnumSwitch::getAMissingCase_dispred#ff#antijoin_rhs + [] with content 173483d71508vl534mvlr1g0ehi12 (5s) >>> Wrote relation Stmt::EnumSwitch::getAMissingCase_dispred#ff#antijoin_rhs with 82902 rows and 2 columns. (5s) Starting to evaluate predicate Stmt::EnumSwitch::getAMissingCase_dispred#ff/2@ae4c0b (5s) Tuple counts for Stmt::EnumSwitch::getAMissingCase_dispred#ff: 746029 ~2% {2} r1 = JOIN Stmt::EnumSwitch::getAMissingCase_dispred#ff#shared AS L WITH Enum::Enum::getAnEnumConstant_dispred#ff AS R ON FIRST 1 OUTPUT L.<1>, R.<1> 663127 ~4% {2} r2 = r1 AND NOT Stmt::EnumSwitch::getAMissingCase_dispred#ff#antijoin_rhs AS R(r1.<0>, r1.<1>) return r2 (5s) Registering Stmt::EnumSwitch::getAMissingCase_dispred#ff + [] with content 2060ff326cvhihcsvoph6k9divuv4 (5s) >>> Wrote relation Stmt::EnumSwitch::getAMissingCase_dispred#ff with 663127 rows and 2 columns.
1 parent bd94e80 commit d686347

File tree

1 file changed

+5
-19
lines changed
  • cpp/ql/src/semmle/code/cpp/stmts

1 file changed

+5
-19
lines changed

cpp/ql/src/semmle/code/cpp/stmts/Stmt.qll

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,30 +1604,16 @@ class EnumSwitch extends SwitchStmt {
16041604
* ```
16051605
* there are results `GREEN` and `BLUE`.
16061606
*/
1607-
pragma[noopt]
16081607
EnumConstant getAMissingCase() {
16091608
exists(Enum et |
1610-
exists(Expr e, Type t |
1611-
e = this.getExpr() and
1612-
this instanceof EnumSwitch and
1613-
t = e.getType() and
1614-
et = t.getUnderlyingType()
1615-
) and
1609+
et = this.getExpr().getUnderlyingType() and
16161610
result = et.getAnEnumConstant() and
1617-
not exists(string value |
1618-
exists(SwitchCase sc, Expr e |
1619-
sc = this.getASwitchCase() and
1620-
e = sc.getExpr() and
1621-
value = e.getValue()
1622-
) and
1623-
exists(Initializer init, Expr e |
1624-
init = result.getInitializer() and
1625-
e = init.getExpr() and
1626-
e.getValue() = value
1627-
)
1628-
)
1611+
not this.matchesValue(result.getInitializer().getExpr().getValue())
16291612
)
16301613
}
1614+
1615+
pragma[noinline]
1616+
private predicate matchesValue(string value) { value = this.getASwitchCase().getExpr().getValue() }
16311617
}
16321618

16331619
/**

0 commit comments

Comments
 (0)