Skip to content

Commit 23fbfbc

Browse files
committed
C#: Performance optimization of the GVN implementation.
1 parent 53b2eac commit 23fbfbc

File tree

1 file changed

+35
-20
lines changed

1 file changed

+35
-20
lines changed

csharp/ql/lib/semmle/code/csharp/commons/StructuralComparison.qll

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@ private class GvnKindStmt extends GvnKind, TGvnKindStmt {
2626
}
2727

2828
private class GvnKindDeclaration extends GvnKind, TGvnKindDeclaration {
29-
private GvnKindExpr kind;
29+
private int kind;
3030
private boolean isTargetThis;
3131
private Declaration d;
3232

3333
GvnKindDeclaration() { this = TGvnKindDeclaration(kind, isTargetThis, d) }
3434

35-
override string toString() { result = kind.toString() + "," + isTargetThis + "," + d.toString() }
35+
override string toString() {
36+
result = "Expr(" + kind.toString() + ")," + isTargetThis + "," + d.toString()
37+
}
3638
}
3739

3840
/** Gets the declaration referenced by the expression `e`, if any. */
@@ -89,21 +91,28 @@ private class GvnStruct extends Gvn, TGvnStruct {
8991
override string toString() { result = "(" + head.toString() + " :: " + tail.toString() + ")" }
9092
}
9193

94+
pragma[noinline]
95+
private predicate gvnKindDeclaration(
96+
ControlFlowElement cfe, int kind, boolean isTargetThis, Declaration d
97+
) {
98+
isTargetThis = isTargetThis(cfe) and
99+
d = referenceAttribute(cfe) and
100+
expressions(cfe, kind, _)
101+
}
102+
92103
/**
93104
* Gets the `GvnKind` of the element `cfe`.
94105
* In case `cfe` is a reference attribute, we encode the entire declaration and whether
95106
* the target is semantically equivalent to `this`.
96107
*/
97108
private GvnKind getGvnKind(ControlFlowElement cfe) {
98-
exists(GvnKind kind |
99-
kind = getKind(cfe) and
100-
(
101-
result = TGvnKindDeclaration(kind, isTargetThis(cfe), referenceAttribute(cfe))
102-
or
103-
not exists(referenceAttribute(cfe)) and
104-
result = kind
105-
)
109+
exists(int kind, boolean isTargetThis, Declaration d |
110+
gvnKindDeclaration(cfe, kind, isTargetThis, d) and
111+
result = TGvnKindDeclaration(kind, isTargetThis, d)
106112
)
113+
or
114+
not exists(referenceAttribute(cfe)) and
115+
result = getKind(cfe)
107116
}
108117

109118
private Gvn gvnConstructed(ControlFlowElement cfe, GvnKind kind, int index) {
@@ -156,9 +165,9 @@ private module Cached {
156165
newtype TGvnKind =
157166
TGvnKindExpr(int kind) { expressions(_, kind, _) } or
158167
TGvnKindStmt(int kind) { statements(_, kind) } or
159-
TGvnKindDeclaration(GvnKindExpr kind, boolean thisTarget, Declaration d) {
168+
TGvnKindDeclaration(int kind, boolean thisTarget, Declaration d) {
160169
exists(Expr e |
161-
d = referenceAttribute(e) and thisTarget = isTargetThis(e) and kind = getKind(e)
170+
d = referenceAttribute(e) and thisTarget = isTargetThis(e) and expressions(e, kind, _)
162171
)
163172
}
164173

@@ -218,15 +227,18 @@ abstract class StructuralComparisonConfiguration extends string {
218227
*/
219228
abstract predicate candidate(ControlFlowElement x, ControlFlowElement y);
220229

230+
pragma[inline]
231+
private predicate sameGvn(ControlFlowElement x, ControlFlowElement y) {
232+
pragma[only_bind_into](toGvn(pragma[only_bind_out](x))) =
233+
pragma[only_bind_into](toGvn(pragma[only_bind_out](y)))
234+
}
235+
221236
/**
222237
* Holds if elements `x` and `y` structurally equal. `x` and `y` must be
223238
* flagged as candidates for structural equality, that is,
224239
* `candidate(x, y)` must hold.
225240
*/
226-
predicate same(ControlFlowElement x, ControlFlowElement y) {
227-
candidate(x, y) and
228-
toGvn(x) = toGvn(y)
229-
}
241+
predicate same(ControlFlowElement x, ControlFlowElement y) { candidate(x, y) and sameGvn(x, y) }
230242
}
231243

232244
/**
@@ -272,14 +284,17 @@ module Internal {
272284
*/
273285
abstract predicate candidate(ControlFlowElement x, ControlFlowElement y);
274286

287+
pragma[inline]
288+
private predicate sameGvn(ControlFlowElement x, ControlFlowElement y) {
289+
pragma[only_bind_into](toGvn(pragma[only_bind_out](x))) =
290+
pragma[only_bind_into](toGvn(pragma[only_bind_out](y)))
291+
}
292+
275293
/**
276294
* Holds if elements `x` and `y` structurally equal. `x` and `y` must be
277295
* flagged as candidates for structural equality, that is,
278296
* `candidate(x, y)` must hold.
279297
*/
280-
predicate same(ControlFlowElement x, ControlFlowElement y) {
281-
candidate(x, y) and
282-
toGvn(x) = toGvn(y)
283-
}
298+
predicate same(ControlFlowElement x, ControlFlowElement y) { candidate(x, y) and sameGvn(x, y) }
284299
}
285300
}

0 commit comments

Comments
 (0)