Skip to content

Commit 2f91778

Browse files
Robert MarshMathiasVP
authored andcommitted
C++: add IR-based wrapper for value numbering
1 parent ffaaed0 commit 2f91778

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* Provides an implementation of Global Value Numbering.
3+
* See https://en.wikipedia.org/wiki/Global_value_numbering
4+
*
5+
* The predicate `globalValueNumber` converts an expression into a `GVN`,
6+
* which is an abstract type representing the value of the expression. If
7+
* two expressions have the same `GVN` then they compute the same value.
8+
* For example:
9+
*
10+
* ```
11+
* void f(int x, int y) {
12+
* g(x+y, x+y);
13+
* }
14+
* ```
15+
*
16+
* In this example, both arguments in the call to `g` compute the same value,
17+
* so both arguments have the same `GVN`. In other words, we can find
18+
* this call with the following query:
19+
*
20+
* ```
21+
* from FunctionCall call, GVN v
22+
* where v = globalValueNumber(call.getArgument(0))
23+
* and v = globalValueNumber(call.getArgument(1))
24+
* select call
25+
* ```
26+
*
27+
* The analysis is conservative, so two expressions might have different
28+
* `GVN`s even though the actually always compute the same value. The most
29+
* common reason for this is that the analysis cannot prove that there
30+
* are no side-effects that might cause the computed value to change.
31+
*/
32+
33+
import cpp
34+
private import semmle.code.cpp.ir.implementation.aliased_ssa.gvn.internal.ValueNumberingInternal
35+
private import semmle.code.cpp.ir.IR
36+
37+
/**
38+
* A Global Value Number. A GVN is an abstract representation of the value
39+
* computed by an expression. The relationship between `Expr` and `GVN` is
40+
* many-to-one: every `Expr` has exactly one `GVN`, but multiple
41+
* expressions can have the same `GVN`. If two expressions have the same
42+
* `GVN`, it means that they compute the same value at run time. The `GVN`
43+
* is an opaque value, so you cannot deduce what the run-time value of an
44+
* expression will be from its `GVN`. The only use for the `GVN` of an
45+
* expression is to find other expressions that compute the same value.
46+
* Use the predicate `globalValueNumber` to get the `GVN` for an `Expr`.
47+
*
48+
* Note: `GVN` has `toString` and `getLocation` methods, so that it can be
49+
* displayed in a results list. These work by picking an arbitrary
50+
* expression with this `GVN` and using its `toString` and `getLocation`
51+
* methods.
52+
*/
53+
class GVN extends TValueNumber {
54+
private Instruction getAnInstruction() { this = tvalueNumber(result) }
55+
56+
final string toString() { result = "GVN" }
57+
58+
final Location getLocation() {
59+
result = rank[1](Location l |
60+
l = getAnExpr().getLocation()
61+
|
62+
l
63+
order by
64+
l.getFile().getAbsolutePath(), l.getStartLine(), l.getStartColumn(), l.getEndLine(),
65+
l.getEndColumn()
66+
)
67+
}
68+
69+
/** Gets an expression that has this GVN. */
70+
Expr getAnExpr() { result = getAnInstruction().getConvertedResultExpression() }
71+
}
72+
73+
/** Gets the global value number of expression `e`. */
74+
GVN globalValueNumber(Expr e) { e = result.getAnExpr() }

0 commit comments

Comments
 (0)