Skip to content

Commit f20041d

Browse files
authored
Merge pull request #1133 from hvitved/csharp/more-performance-tweaks
C#: More performance tweaks
2 parents 5a56740 + 414b724 commit f20041d

File tree

3 files changed

+62
-24
lines changed

3 files changed

+62
-24
lines changed

csharp/ql/src/semmle/code/csharp/commons/Constants.qll

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,20 @@ import csharp
44
private import semmle.code.csharp.commons.ComparisonTest
55
private import semmle.code.csharp.commons.StructuralComparison as StructuralComparison
66

7+
pragma[noinline]
8+
private predicate isConstantCondition0(ControlFlow::Node cfn, boolean b) {
9+
exists(
10+
cfn.getASuccessorByType(any(ControlFlow::SuccessorTypes::BooleanSuccessor t | t.getValue() = b))
11+
) and
12+
strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1
13+
}
14+
715
/**
816
* Holds if `e` is a condition that always evaluates to Boolean value `b`.
917
*/
1018
predicate isConstantCondition(Expr e, boolean b) {
1119
forex(ControlFlow::Node cfn | cfn = e.getAControlFlowNode() |
12-
exists(
13-
cfn
14-
.getASuccessorByType(any(ControlFlow::SuccessorTypes::BooleanSuccessor t |
15-
t.getValue() = b
16-
))
17-
) and
18-
strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1
20+
isConstantCondition0(cfn, b)
1921
)
2022
}
2123

csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowElement.qll

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,40 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
7575
getAControlFlowNode().getBasicBlock().getASuccessor+().getANode() = result.getAControlFlowNode()
7676
}
7777

78+
pragma[noinline]
79+
private predicate immediatelyControlsBlockSplit0(
80+
ConditionBlock cb, BasicBlock succ, ConditionalSuccessor s
81+
) {
82+
// Only calculate dominance by explicit recursion for split nodes;
83+
// all other nodes can use regular CFG dominance
84+
this instanceof ControlFlow::Internal::SplitControlFlowElement and
85+
cb.getLastNode() = this.getAControlFlowNode() and
86+
succ = cb.getASuccessorByType(s)
87+
}
88+
89+
pragma[noinline]
90+
private predicate immediatelyControlsBlockSplit1(
91+
ConditionBlock cb, BasicBlock succ, ConditionalSuccessor s, BasicBlock pred, SuccessorType t
92+
) {
93+
this.immediatelyControlsBlockSplit0(cb, succ, s) and
94+
pred = succ.getAPredecessorByType(t) and
95+
pred != cb
96+
}
97+
98+
pragma[noinline]
99+
private predicate immediatelyControlsBlockSplit2(
100+
ConditionBlock cb, BasicBlock succ, ConditionalSuccessor s, BasicBlock pred, SuccessorType t
101+
) {
102+
this.immediatelyControlsBlockSplit1(cb, succ, s, pred, t) and
103+
(
104+
succ.dominates(pred)
105+
or
106+
// `pred` might be another split of this element
107+
pred.getLastNode().getElement() = this and
108+
t = s
109+
)
110+
}
111+
78112
/**
79113
* Holds if basic block `succ` is immediately controlled by this control flow
80114
* element with conditional value `s`. That is, `succ` can only be reached from
@@ -96,19 +130,11 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
96130
*/
97131
pragma[nomagic]
98132
private predicate immediatelyControlsBlockSplit(BasicBlock succ, ConditionalSuccessor s) {
99-
// Only calculate dominance by explicit recursion for split nodes;
100-
// all other nodes can use regular CFG dominance
101-
this instanceof ControlFlow::Internal::SplitControlFlowElement and
102-
exists(ConditionBlock cb | cb.getLastNode() = this.getAControlFlowNode() |
103-
succ = cb.getASuccessorByType(s) and
133+
exists(ConditionBlock cb | this.immediatelyControlsBlockSplit0(cb, succ, s) |
104134
forall(BasicBlock pred, SuccessorType t |
105-
pred = succ.getAPredecessorByType(t) and pred != cb
135+
this.immediatelyControlsBlockSplit1(cb, succ, s, pred, t)
106136
|
107-
succ.dominates(pred)
108-
or
109-
// `pred` might be another split of this element
110-
pred.getLastNode().getElement() = this and
111-
t = s
137+
this.immediatelyControlsBlockSplit2(cb, succ, s, pred, t)
112138
)
113139
)
114140
}

csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,21 @@ private predicate defMaybeNull(Ssa::Definition def, string msg, Element reason)
198198
)
199199
}
200200

201+
pragma[noinline]
202+
private predicate sourceVariableMaybeNull(Ssa::SourceVariable v) {
203+
defMaybeNull(v.getAnSsaDefinition(), _, _)
204+
}
205+
206+
pragma[noinline]
207+
private predicate defNullImpliesStep0(
208+
Ssa::SourceVariable v, Ssa::Definition def1, BasicBlock bb1, BasicBlock bb2
209+
) {
210+
sourceVariableMaybeNull(v) and
211+
def1.getSourceVariable() = v and
212+
def1.isLiveAtEndOfBlock(bb1) and
213+
bb2 = bb1.getASuccessor()
214+
}
215+
201216
/**
202217
* Holds if `def1` being `null` in basic block `bb1` implies that `def2` might
203218
* be `null` in basic block `bb2`. The SSA definitions share the same source
@@ -206,10 +221,7 @@ private predicate defMaybeNull(Ssa::Definition def, string msg, Element reason)
206221
private predicate defNullImpliesStep(
207222
Ssa::Definition def1, BasicBlock bb1, Ssa::Definition def2, BasicBlock bb2
208223
) {
209-
exists(Ssa::SourceVariable v |
210-
defMaybeNull(v.getAnSsaDefinition(), _, _) and
211-
def1.getSourceVariable() = v
212-
|
224+
exists(Ssa::SourceVariable v | defNullImpliesStep0(v, def1, bb1, bb2) |
213225
def2.(Ssa::PseudoDefinition).getAnInput() = def1 and
214226
bb2 = def2.getBasicBlock()
215227
or
@@ -219,9 +231,7 @@ private predicate defNullImpliesStep(
219231
bb2 = def.getBasicBlock()
220232
)
221233
) and
222-
def1.isLiveAtEndOfBlock(bb1) and
223234
not ensureNotNullAt(bb1, _, def1) and
224-
bb2 = bb1.getASuccessor() and
225235
not exists(SuccessorTypes::ConditionalSuccessor s, NullValue nv |
226236
bb1.getLastNode() = getANullCheck(def1, s, nv).getAControlFlowNode()
227237
|

0 commit comments

Comments
 (0)