Skip to content

Commit 11e03b3

Browse files
committed
C++: Fix primitive_basic_block_member join order
This predicate looked like a join of two already-computed predicates, but it was a bit more complicated because the `*` operator expands into two cases: the reflexive case and the transitive case. The join order for the transitive case placed the `PrimitiveBasicBlock` charpred call _after_ the `member_step+` call, which means that all the tuples of `member_step+` passed through the pipeline. This commit changes the implementation by fully writing out the expansion of `*` into two cases, where the base case is manually specialised to make sure the join orderer doesn't get tempted into reusing the same strategy for both cases. This speeds up the predicate from 2m38s to 1s on a snapshot of our own C/C++ code.
1 parent 2658520 commit 11e03b3

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

cpp/ql/src/semmle/code/cpp/controlflow/internal/PrimitiveBasicBlocks.qll

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,14 @@ private cached module Cached {
6666
/** Holds if `node` is the `pos`th control-flow node in primitive basic block `bb`. */
6767
cached
6868
predicate primitive_basic_block_member(Node node, PrimitiveBasicBlock bb, int pos) {
69-
pos = getMemberIndex(node) and
70-
member_step*(bb, node)
69+
primitive_basic_block_entry_node(bb) and
70+
(
71+
pos = 0 and
72+
node = bb
73+
or
74+
pos = getMemberIndex(node) and
75+
member_step+(bb, node)
76+
)
7177
}
7278

7379
/** Gets the number of control-flow nodes in the primitive basic block `bb`. */

0 commit comments

Comments
 (0)