From e7234f5cf3d87504c3a4d150d81da5b614e26dca Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 29 Aug 2018 15:48:09 +0200 Subject: [PATCH 1/2] C++: Split index calculation from BB membership Instead of computing these two things in one predicate, they are computed in separate predicates and then joined. This splits the predicate `primitive_basic_block_member`, which took 77s before, into predicates that together take 18s on a medium-sized db. --- .../internal/PrimitiveBasicBlocks.qll | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/internal/PrimitiveBasicBlocks.qll b/cpp/ql/src/semmle/code/cpp/controlflow/internal/PrimitiveBasicBlocks.qll index aaba64a83fa2..dd586c2a38f8 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/internal/PrimitiveBasicBlocks.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/internal/PrimitiveBasicBlocks.qll @@ -43,15 +43,31 @@ private cached module Cached { (not successors_extended(_, node) and successors_extended(node, _)) } + pragma[noinline] + private predicate member_step(Node n1, Node n2) { + successors_extended(n1, n2) and + not n2 instanceof PrimitiveBasicBlock + } + + private int getMemberIndex(Node node) { + primitive_basic_block_entry_node(node) and + result = 0 + or + exists(Node prev | + member_step(prev, node) and + result = getMemberIndex(prev) + 1 + ) + } + + private predicate isMember(Node node, PrimitiveBasicBlock bb) { + member_step*(bb, node) + } + /** Holds if `node` is the `pos`th control-flow node in primitive basic block `bb`. */ cached predicate primitive_basic_block_member(Node node, PrimitiveBasicBlock bb, int pos) { - (node = bb and pos = 0) - or - (not (node instanceof PrimitiveBasicBlock) and - exists (Node pred - | successors_extended(pred, node) - | primitive_basic_block_member(pred, bb, pos - 1))) + pos = getMemberIndex(node) and + isMember(node, bb) } /** Gets the number of control-flow nodes in the primitive basic block `bb`. */ From 98612b9f9a3db1a60e8061b9abcdb6e4d7cbcc9a Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Sat, 1 Sep 2018 07:46:00 +0200 Subject: [PATCH 2/2] C++: Tidy primitive_basic_block_member calculation This change gave a slight speed-up by eliminating an unnecessary intermediate predicate. --- .../cpp/controlflow/internal/PrimitiveBasicBlocks.qll | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/internal/PrimitiveBasicBlocks.qll b/cpp/ql/src/semmle/code/cpp/controlflow/internal/PrimitiveBasicBlocks.qll index dd586c2a38f8..babed5d10e15 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/internal/PrimitiveBasicBlocks.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/internal/PrimitiveBasicBlocks.qll @@ -43,12 +43,13 @@ private cached module Cached { (not successors_extended(_, node) and successors_extended(node, _)) } - pragma[noinline] + /** Holds if `n2` follows `n1` in a `PrimitiveBasicBlock`. */ private predicate member_step(Node n1, Node n2) { successors_extended(n1, n2) and not n2 instanceof PrimitiveBasicBlock } + /** Returns the index of `node` in its `PrimitiveBasicBlock`. */ private int getMemberIndex(Node node) { primitive_basic_block_entry_node(node) and result = 0 @@ -59,15 +60,11 @@ private cached module Cached { ) } - private predicate isMember(Node node, PrimitiveBasicBlock bb) { - member_step*(bb, node) - } - /** Holds if `node` is the `pos`th control-flow node in primitive basic block `bb`. */ cached predicate primitive_basic_block_member(Node node, PrimitiveBasicBlock bb, int pos) { pos = getMemberIndex(node) and - isMember(node, bb) + member_step*(bb, node) } /** Gets the number of control-flow nodes in the primitive basic block `bb`. */