Skip to content

Commit 2361476

Browse files
committed
C#: Improve join-order in SplitImpl::hasSuccessor
Joining on `succ` first gets rid of bad join-orders like ``` Tuple counts for Splitting::SplitImpl::hasSuccessor_dispred#ffff/4@i4#f49ebw: 59306 ~2% {3} r1 = JOIN Splitting::SplitImpl::appliesTo#ff#prev_delta WITH Splitting::Cached::TAssertionSplit#ffff_30#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.0 'this', Lhs.1 'pred' 454395 ~0% {3} r2 = JOIN r1 WITH Splitting::AssertionSplitting::getAnAssertionDescendant#ff ON FIRST 1 OUTPUT Lhs.2 'pred', Rhs.1 'succ', Lhs.1 'this' 12157 ~0% {4} r3 = JOIN r2 WITH ControlFlowGraphImpl::succ#fff ON FIRST 2 OUTPUT Lhs.2 'this', Lhs.0 'pred', Lhs.1 'succ', Rhs.2 'c' 0 ~0% {4} r4 = JOIN Splitting::LoopSplitting::LoopUnrollingSplitImpl::appliesToPredecessor_dispred#fff#prev_delta WITH Splitting::Cached::TLoopSplit#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.1 'pred', Lhs.2 'c', Rhs.1, Rhs.0 0 ~0% {5} r5 = JOIN r4 WITH ControlFlowGraphImpl::succ#fff_021#join_rhs ON FIRST 2 OUTPUT Lhs.2, Lhs.3 'this', Lhs.0 'pred', Lhs.1 'c', Rhs.2 'succ' 0 ~0% {5} r6 = r5 AND NOT Splitting::SplitImpl::hasSuccessor_dispred#ffff#antijoin_rhs#2(Lhs.2 'pred', Lhs.4 'succ', Lhs.3 'c', Lhs.0) 0 ~0% {4} r7 = SCAN r6 OUTPUT In.1 'this', In.2 'pred', In.4 'succ', In.3 'c' 12157 ~0% {4} r8 = r3 UNION r7 0 ~0% {3} r9 = SCAN Splitting::BooleanSplitting::BooleanSplitImpl::appliesToBlock_dispred#fff#prev_delta OUTPUT In.1, In.0 'this', In.2 0 ~0% {4} r10 = JOIN r9 WITH project#PreBasicBlocks::PreBasicBlock::getElement_dispred#fff ON FIRST 1 OUTPUT Rhs.1 'pred', Lhs.1 'this', Lhs.0, Lhs.2 0 ~0% {6} r11 = JOIN r10 WITH ControlFlowGraphImpl::succ#fff ON FIRST 1 OUTPUT Lhs.1 'this', Lhs.2, Lhs.3, Lhs.0 'pred', Rhs.1, Rhs.2 'c' 0 ~0% {6} r12 = r11 AND NOT PreBasicBlocks::PreBasicBlock::getLastElement_dispred#ff(Lhs.1, Lhs.3 'pred') 0 ~0% {4} r13 = SCAN r12 OUTPUT In.0 'this', In.3 'pred', In.4 'succ', In.5 'c' 35244 ~1% {3} r14 = JOIN Splitting::SplitImpl::appliesTo#ff#prev_delta WITH Splitting::Cached::TInitializerSplit#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.0 'this', Lhs.1 'pred' 24640675 ~6% {3} r15 = JOIN r14 WITH Splitting::InitializerSplitting::constructorInitializes#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'this', Lhs.2 'pred' 24640675 ~21147% {3} r16 = JOIN r15 WITH Splitting::InitializerSplitting::InitializedInstanceMember::getInitializer_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'this', Lhs.2 'pred' 470227342920 ~481608% {3} r17 = JOIN r16 WITH Splitting::InitializerSplitting::InitializedInstanceMember::getAnInitializerDescendant#ff ON FIRST 1 OUTPUT Lhs.2 'pred', Rhs.1 'succ', Lhs.1 'this' 24560447 ~66468% {4} r18 = JOIN r17 WITH ControlFlowGraphImpl::succ#fff ON FIRST 2 OUTPUT Lhs.2 'this', Lhs.0 'pred', Lhs.1 'succ', Rhs.2 'c' 24560447 ~66468% {4} r19 = r13 UNION r18 24572604 ~48162% {4} r20 = r8 UNION r19 0 ~0% {3} r21 = JOIN r9 WITH project#PreBasicBlocks::PreBasicBlock::getElement_dispred#fff ON FIRST 1 OUTPUT Rhs.1 'pred', Lhs.2, Lhs.1 'this' 0 ~0% {4} r22 = JOIN r21 WITH ControlFlowGraphImpl::succ#fff_021#join_rhs ON FIRST 2 OUTPUT Lhs.2 'this', Lhs.0 'pred', Rhs.2 'succ', Rhs.1 0 ~0% {5} r23 = JOIN r22 WITH Splitting::Cached::TBooleanSplit#fff_20#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.2 'succ', Lhs.0 'this', Lhs.1 'pred', Lhs.3 'c' 0 ~0% {4} r24 = JOIN r23 WITH Splitting::BooleanSplitting::SsaBooleanSplitSubKind::canReachCorrelatedCondition#ff ON FIRST 2 OUTPUT Lhs.2 'this', Lhs.3 'pred', Lhs.1 'succ', Lhs.4 'c' 0 ~0% {2} r25 = SCAN Splitting::FinallySplitting::FinallySplitImpl::appliesToPredecessor_dispred#ff#prev_delta OUTPUT In.1 'pred', In.0 'this' 0 ~0% {4} r26 = JOIN r25 WITH ControlFlowGraphImpl::succ#fff ON FIRST 1 OUTPUT Lhs.1 'this', Lhs.0 'pred', Rhs.1, Rhs.2 'c' 0 ~0% {4} r27 = r26 AND NOT Splitting::FinallySplitting::FinallyControlFlowElement::isEntryNode_dispred#f(Lhs.2 'succ') 0 ~0% {5} r28 = JOIN r27 WITH Splitting::Cached::TFinallySplit#fff_21#join_rhs ON FIRST 1 OUTPUT Lhs.2 'succ', Lhs.0 'this', Lhs.1 'pred', Lhs.3 'c', Rhs.1 0 ~0% {6} r29 = JOIN r28 WITH ControlFlowGraphImpl::Statements::TryStmtTree::getAFinallyDescendant#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'this', Lhs.2 'pred', Lhs.0 'succ', Lhs.3 'c', Lhs.4 0 ~0% {7} r30 = JOIN r29 WITH ControlFlowGraphImpl::Statements::TryStmtTree::nestLevel_dispred#ff ON FIRST 1 OUTPUT Lhs.1 'this', Lhs.2 'pred', Lhs.3 'succ', Lhs.4 'c', Lhs.5, Lhs.0, Rhs.1 0 ~0% {7} r31 = SELECT r30 ON In.6 >= In.4 0 ~0% {4} r32 = SCAN r31 OUTPUT In.0 'this', In.1 'pred', In.2 'succ', In.3 'c' 0 ~0% {4} r33 = r24 UNION r32 0 ~0% {4} r34 = JOIN r25 WITH ControlFlowGraphImpl::succ#fff ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'this', Lhs.0 'pred', Rhs.2 'c' 0 ~0% {4} r35 = JOIN r34 WITH Splitting::FinallySplitting::FinallyControlFlowElement::isEntryNode_dispred#f ON FIRST 1 OUTPUT Lhs.1 'this', Lhs.2 'pred', Lhs.0 'succ', Lhs.3 'c' 0 ~0% {5} r36 = JOIN r35 WITH Splitting::Cached::TFinallySplit#fff_21#join_rhs ON FIRST 1 OUTPUT Lhs.2 'succ', Lhs.0 'this', Lhs.1 'pred', Lhs.3 'c', Rhs.1 0 ~0% {6} r37 = JOIN r36 WITH ControlFlowGraphImpl::Statements::TryStmtTree::getAFinallyDescendant#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'this', Lhs.2 'pred', Lhs.0 'succ', Lhs.3 'c', Lhs.4 0 ~0% {7} r38 = JOIN r37 WITH ControlFlowGraphImpl::Statements::TryStmtTree::nestLevel_dispred#ff ON FIRST 1 OUTPUT Lhs.1 'this', Lhs.2 'pred', Lhs.3 'succ', Lhs.4 'c', Lhs.5, Lhs.0, Rhs.1 0 ~0% {7} r39 = SELECT r38 ON In.6 > In.4 0 ~0% {4} r40 = SCAN r39 OUTPUT In.0 'this', In.1 'pred', In.2 'succ', In.3 'c' 0 ~0% {3} r41 = SCAN Splitting::ExceptionHandlerSplitting::ExceptionHandlerSplitImpl::appliesToPredecessor_dispred#fff#prev_delta OUTPUT In.1 'pred', In.2 'c', In.0 'this' 0 ~0% {4} r42 = JOIN r41 WITH ControlFlowGraphImpl::last#fff_120#join_rhs ON FIRST 2 OUTPUT Rhs.2, Lhs.2 'this', Lhs.0 'pred', Lhs.1 'c' 0 ~0% {5} r43 = JOIN r42 WITH Stmt::TryStmt::getCatchClause_dispred#fff_201#join_rhs ON FIRST 1 OUTPUT Rhs.1, Rhs.2, Lhs.1 'this', Lhs.2 'pred', Lhs.3 'c' 0 ~0% {4} r44 = JOIN r43 WITH Stmt::TryStmt::getCatchClause_dispred#fff ON FIRST 2 OUTPUT Rhs.2, Lhs.2 'this', Lhs.3 'pred', Lhs.4 'c' 0 ~0% {5} r45 = JOIN r44 WITH Stmt::CatchClause::isLast_dispred#f ON FIRST 1 OUTPUT Lhs.0, 1, Lhs.1 'this', Lhs.2 'pred', Lhs.3 'c' 0 ~0% {3} r46 = JOIN r45 WITH catch_type_02#join_rhs ON FIRST 2 OUTPUT Lhs.2 'this', Lhs.3 'pred', Lhs.4 'c' 0 {3} r47 = MATERIALIZE r46 AS unknown 0 ~0% {3} r48 = Splitting::ExceptionHandlerSplitting::ExceptionHandlerSplitImpl::appliesToPredecessor_dispred#fff#prev_delta AND NOT r47(Lhs.0 'this', Lhs.1 'pred', Lhs.2 'c') 0 ~0% {3} r49 = SCAN r48 OUTPUT In.1 'pred', In.2 'c', In.0 'this' 0 ~0% {4} r50 = JOIN r49 WITH ControlFlowGraphImpl::succ#fff_021#join_rhs ON FIRST 2 OUTPUT Lhs.2 'this', Lhs.0 'pred', Lhs.1 'c', Rhs.2 'succ' 0 ~0% {4} r51 = JOIN r49 WITH ControlFlowGraphImpl::succ#fff_021#join_rhs ON FIRST 2 OUTPUT Rhs.2 'succ', Lhs.2 'this', Lhs.0 'pred', Lhs.1 'c' 0 ~0% {5} r52 = JOIN r51 WITH ControlFlowGraphImpl::ControlFlowTree::first_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'this', Lhs.2 'pred', Lhs.3 'c', Lhs.0 'succ' 0 ~0% {6} r53 = JOIN r52 WITH Stmt::CatchClause::getBlock_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, 1, Lhs.1 'this', Lhs.2 'pred', Lhs.3 'c', Lhs.4 'succ' 0 ~0% {4} r54 = JOIN r53 WITH catch_type_02#join_rhs ON FIRST 2 OUTPUT Lhs.2 'this', Lhs.3 'pred', Lhs.4 'c', Lhs.5 'succ' 0 {4} r55 = MATERIALIZE r54 AS unknown 0 ~0% {4} r56 = r50 AND NOT r55(Lhs.0 'this', Lhs.1 'pred', Lhs.2 'c', Lhs.3 'succ') 0 ~0% {4} r57 = r56 AND NOT ControlFlowGraphImpl::Statements::StandardStmt::getChildElement0_dispred#fff#antijoin_rhs#2(Lhs.3 'succ') 0 ~0% {4} r58 = SCAN r57 OUTPUT In.0 'this', In.1 'pred', In.3 'succ', In.2 'c' 0 ~0% {4} r59 = r40 UNION r58 0 ~0% {4} r60 = r33 UNION r59 24572604 ~48162% {4} r61 = r20 UNION r60 24572604 ~48162% {4} r62 = r61 AND NOT Splitting::SplitImpl::hasSuccessor_dispred#ffff#prev(Lhs.0 'this', Lhs.1 'pred', Lhs.2 'succ', Lhs.3 'c') return r62 ```
1 parent 7ac04a8 commit 2361476

File tree

1 file changed

+13
-9
lines changed
  • csharp/ql/src/semmle/code/csharp/controlflow/internal

1 file changed

+13
-9
lines changed

csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,13 @@ abstract class SplitImpl extends Split {
209209
or
210210
exists(ControlFlowElement pred | this.appliesTo(pred) | this.hasSuccessor(pred, cfe, _))
211211
}
212+
213+
/** The `succ` relation restricted to predecessors `pred` that this split applies to. */
214+
pragma[noinline]
215+
final predicate appliesSucc(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
216+
this.appliesTo(pred) and
217+
succ(pred, succ, c)
218+
}
212219
}
213220

214221
module InitializerSplitting {
@@ -382,8 +389,7 @@ module InitializerSplitting {
382389
}
383390

384391
override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
385-
this.appliesTo(pred) and
386-
succ(pred, succ, c) and
392+
this.appliesSucc(pred, succ, c) and
387393
succ =
388394
any(InitializedInstanceMember m |
389395
constructorInitializes(this.getConstructor(), m.getInitializer())
@@ -620,8 +626,7 @@ module AssertionSplitting {
620626
}
621627

622628
override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
623-
this.appliesTo(pred) and
624-
succ(pred, succ, c) and
629+
this.appliesSucc(pred, succ, c) and
625630
succ = getAnAssertionDescendant(a)
626631
}
627632
}
@@ -858,8 +863,7 @@ module FinallySplitting {
858863
}
859864

860865
override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
861-
this.appliesToPredecessor(pred) and
862-
succ(pred, succ, c) and
866+
this.appliesSucc(pred, succ, c) and
863867
succ =
864868
any(FinallyControlFlowElement fcfe |
865869
if fcfe.isEntryNode()
@@ -1037,7 +1041,7 @@ module ExceptionHandlerSplitting {
10371041

10381042
override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
10391043
this.appliesToPredecessor(pred, c) and
1040-
succ(pred, succ, c) and
1044+
this.appliesSucc(pred, succ, c) and
10411045
not first(any(SpecificCatchClause scc).getBlock(), succ) and
10421046
not succ instanceof GeneralCatchClause and
10431047
not exists(TryStmt ts, SpecificCatchClause scc, int last |
@@ -1298,7 +1302,7 @@ module BooleanSplitting {
12981302
override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
12991303
exists(PreBasicBlock bb, Completion c0 | this.appliesToBlock(bb, c0) |
13001304
pred = bb.getAnElement() and
1301-
succ(pred, succ, c) and
1305+
this.appliesSucc(pred, succ, c) and
13021306
(
13031307
pred = bb.getLastElement()
13041308
implies
@@ -1489,7 +1493,7 @@ module LoopSplitting {
14891493

14901494
override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
14911495
this.appliesToPredecessor(pred, c) and
1492-
succ(pred, succ, c) and
1496+
this.appliesSucc(pred, succ, c) and
14931497
not loop.stop(pred, succ, c)
14941498
}
14951499
}

0 commit comments

Comments
 (0)