Skip to content

Commit 19286bd

Browse files
authored
Merge pull request #2765 from MathiasVP/ir-gvn-ast-wrapper-fixup
C++: Make AST GVN a wrapper for IR-based GVN
2 parents e05dd35 + 538c2b2 commit 19286bd

File tree

20 files changed

+2349
-1800
lines changed

20 files changed

+2349
-1800
lines changed

config/identical-files.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,12 @@
222222
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll",
223223
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll"
224224
],
225-
"IR ValueNumber": [
225+
"C++ IR ValueNumberInternal": [
226+
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll",
227+
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll",
228+
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll"
229+
],
230+
"C++ IR ValueNumber": [
226231
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll",
227232
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll",
228233
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll",
Lines changed: 47 additions & 293 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
private import internal.ValueNumberingInternal
22
private import internal.ValueNumberingImports
3-
private import IR
43

54
/**
65
* Provides additional information about value numbering in IR dumps.
@@ -10,62 +9,38 @@ class ValueNumberPropertyProvider extends IRPropertyProvider {
109
exists(ValueNumber vn |
1110
vn = valueNumber(instr) and
1211
key = "valnum" and
13-
if strictcount(vn.getAnInstruction()) > 1 then result = vn.toString() else result = "unique"
12+
if strictcount(vn.getAnInstruction()) > 1
13+
then result = vn.getDebugString()
14+
else result = "unique"
1415
)
1516
}
1617
}
1718

18-
newtype TValueNumber =
19-
TVariableAddressValueNumber(IRFunction irFunc, IRVariable var) {
20-
variableAddressValueNumber(_, irFunc, var)
21-
} or
22-
TInitializeParameterValueNumber(IRFunction irFunc, IRVariable var) {
23-
initializeParameterValueNumber(_, irFunc, var)
24-
} or
25-
TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or
26-
TConstantValueNumber(IRFunction irFunc, IRType type, string value) {
27-
constantValueNumber(_, irFunc, type, value)
28-
} or
29-
TStringConstantValueNumber(IRFunction irFunc, IRType type, string value) {
30-
stringConstantValueNumber(_, irFunc, type, value)
31-
} or
32-
TFieldAddressValueNumber(IRFunction irFunc, Language::Field field, ValueNumber objectAddress) {
33-
fieldAddressValueNumber(_, irFunc, field, objectAddress)
34-
} or
35-
TBinaryValueNumber(
36-
IRFunction irFunc, Opcode opcode, IRType type, ValueNumber leftOperand, ValueNumber rightOperand
37-
) {
38-
binaryValueNumber(_, irFunc, opcode, type, leftOperand, rightOperand)
39-
} or
40-
TPointerArithmeticValueNumber(
41-
IRFunction irFunc, Opcode opcode, IRType type, int elementSize, ValueNumber leftOperand,
42-
ValueNumber rightOperand
43-
) {
44-
pointerArithmeticValueNumber(_, irFunc, opcode, type, elementSize, leftOperand, rightOperand)
45-
} or
46-
TUnaryValueNumber(IRFunction irFunc, Opcode opcode, IRType type, ValueNumber operand) {
47-
unaryValueNumber(_, irFunc, opcode, type, operand)
48-
} or
49-
TInheritanceConversionValueNumber(
50-
IRFunction irFunc, Opcode opcode, Language::Class baseClass, Language::Class derivedClass,
51-
ValueNumber operand
52-
) {
53-
inheritanceConversionValueNumber(_, irFunc, opcode, baseClass, derivedClass, operand)
54-
} or
55-
TLoadTotalOverlapValueNumber(
56-
IRFunction irFunc, IRType type, ValueNumber memOperand, ValueNumber operand
57-
) {
58-
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
59-
} or
60-
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
61-
6219
/**
6320
* The value number assigned to a particular set of instructions that produce equivalent results.
6421
*/
6522
class ValueNumber extends TValueNumber {
66-
final string toString() { result = getExampleInstruction().getResultId() }
23+
final string toString() { result = "GVN" }
24+
25+
final string getDebugString() { result = strictconcat(getAnInstruction().getResultId(), ", ") }
6726

68-
final Language::Location getLocation() { result = getExampleInstruction().getLocation() }
27+
final Language::Location getLocation() {
28+
if
29+
exists(Instruction i |
30+
i = getAnInstruction() and not i.getLocation() instanceof UnknownLocation
31+
)
32+
then
33+
result =
34+
min(Language::Location l |
35+
l = getAnInstruction().getLocation() and not l instanceof UnknownLocation
36+
|
37+
l
38+
order by
39+
l.getFile().getAbsolutePath(), l.getStartLine(), l.getStartColumn(), l.getEndLine(),
40+
l.getEndColumn()
41+
)
42+
else result instanceof UnknownDefaultLocation
43+
}
6944

7045
/**
7146
* Gets the instructions that have been assigned this value number. This will always produce at
@@ -90,260 +65,39 @@ class ValueNumber extends TValueNumber {
9065
* Gets an `Operand` whose definition is exact and has this value number.
9166
*/
9267
final Operand getAUse() { this = valueNumber(result.getDef()) }
93-
}
9468

95-
/**
96-
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source
97-
* operand.
98-
* For example:
99-
* ```
100-
* Point p = { 1, 2 };
101-
* Point q = p;
102-
* int a = p.x;
103-
* ```
104-
* The use of `p` on line 2 is linked to the definition of `p` on line 1, and is congruent to that
105-
* definition because it accesses the exact same memory.
106-
* The use of `p.x` on line 3 is linked to the definition of `p` on line 1 as well, but is not
107-
* congruent to that definition because `p.x` accesses only a subset of the memory defined by `p`.
108-
*/
109-
class CongruentCopyInstruction extends CopyInstruction {
110-
CongruentCopyInstruction() {
111-
this.getSourceValueOperand().getDefinitionOverlap() instanceof MustExactlyOverlap
69+
final string getKind() {
70+
this instanceof TVariableAddressValueNumber and result = "VariableAddress"
71+
or
72+
this instanceof TInitializeParameterValueNumber and result = "InitializeParameter"
73+
or
74+
this instanceof TInitializeThisValueNumber and result = "InitializeThis"
75+
or
76+
this instanceof TStringConstantValueNumber and result = "StringConstant"
77+
or
78+
this instanceof TFieldAddressValueNumber and result = "FieldAddress"
79+
or
80+
this instanceof TBinaryValueNumber and result = "Binary"
81+
or
82+
this instanceof TPointerArithmeticValueNumber and result = "PointerArithmetic"
83+
or
84+
this instanceof TUnaryValueNumber and result = "Unary"
85+
or
86+
this instanceof TInheritanceConversionValueNumber and result = "InheritanceConversion"
87+
or
88+
this instanceof TLoadTotalOverlapValueNumber and result = "LoadTotalOverlap"
89+
or
90+
this instanceof TUniqueValueNumber and result = "Unique"
11291
}
11392
}
11493

115-
class LoadTotalOverlapInstruction extends LoadInstruction {
116-
LoadTotalOverlapInstruction() {
117-
this.getSourceValueOperand().getDefinitionOverlap() instanceof MustTotallyOverlap
118-
}
119-
}
120-
121-
/**
122-
* Holds if this library knows how to assign a value number to the specified instruction, other than
123-
* a `unique` value number that is never shared by multiple instructions.
124-
*/
125-
private predicate numberableInstruction(Instruction instr) {
126-
instr instanceof VariableAddressInstruction
127-
or
128-
instr instanceof InitializeParameterInstruction
129-
or
130-
instr instanceof InitializeThisInstruction
131-
or
132-
instr instanceof ConstantInstruction
133-
or
134-
instr instanceof StringConstantInstruction
135-
or
136-
instr instanceof FieldAddressInstruction
137-
or
138-
instr instanceof BinaryInstruction
139-
or
140-
instr instanceof UnaryInstruction and not instr instanceof CopyInstruction
141-
or
142-
instr instanceof PointerArithmeticInstruction
143-
or
144-
instr instanceof CongruentCopyInstruction
145-
or
146-
instr instanceof LoadTotalOverlapInstruction
147-
}
148-
149-
private predicate variableAddressValueNumber(
150-
VariableAddressInstruction instr, IRFunction irFunc, IRVariable var
151-
) {
152-
instr.getEnclosingIRFunction() = irFunc and
153-
instr.getIRVariable() = var
154-
}
155-
156-
private predicate initializeParameterValueNumber(
157-
InitializeParameterInstruction instr, IRFunction irFunc, IRVariable var
158-
) {
159-
instr.getEnclosingIRFunction() = irFunc and
160-
instr.getIRVariable() = var
161-
}
162-
163-
private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRFunction irFunc) {
164-
instr.getEnclosingIRFunction() = irFunc
165-
}
166-
167-
private predicate constantValueNumber(
168-
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
169-
) {
170-
instr.getEnclosingIRFunction() = irFunc and
171-
instr.getResultIRType() = type and
172-
instr.getValue() = value
173-
}
174-
175-
private predicate stringConstantValueNumber(
176-
StringConstantInstruction instr, IRFunction irFunc, IRType type, string value
177-
) {
178-
instr.getEnclosingIRFunction() = irFunc and
179-
instr.getResultIRType() = type and
180-
instr.getValue().getValue() = value
181-
}
182-
183-
private predicate fieldAddressValueNumber(
184-
FieldAddressInstruction instr, IRFunction irFunc, Language::Field field, ValueNumber objectAddress
185-
) {
186-
instr.getEnclosingIRFunction() = irFunc and
187-
instr.getField() = field and
188-
valueNumber(instr.getObjectAddress()) = objectAddress
189-
}
190-
191-
private predicate binaryValueNumber(
192-
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, IRType type, ValueNumber leftOperand,
193-
ValueNumber rightOperand
194-
) {
195-
instr.getEnclosingIRFunction() = irFunc and
196-
not instr instanceof PointerArithmeticInstruction and
197-
instr.getOpcode() = opcode and
198-
instr.getResultIRType() = type and
199-
valueNumber(instr.getLeft()) = leftOperand and
200-
valueNumber(instr.getRight()) = rightOperand
201-
}
202-
203-
private predicate pointerArithmeticValueNumber(
204-
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, IRType type,
205-
int elementSize, ValueNumber leftOperand, ValueNumber rightOperand
206-
) {
207-
instr.getEnclosingIRFunction() = irFunc and
208-
instr.getOpcode() = opcode and
209-
instr.getResultIRType() = type and
210-
instr.getElementSize() = elementSize and
211-
valueNumber(instr.getLeft()) = leftOperand and
212-
valueNumber(instr.getRight()) = rightOperand
213-
}
214-
215-
private predicate unaryValueNumber(
216-
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, IRType type, ValueNumber operand
217-
) {
218-
instr.getEnclosingIRFunction() = irFunc and
219-
not instr instanceof InheritanceConversionInstruction and
220-
not instr instanceof CopyInstruction and
221-
not instr instanceof FieldAddressInstruction and
222-
instr.getOpcode() = opcode and
223-
instr.getResultIRType() = type and
224-
valueNumber(instr.getUnary()) = operand
225-
}
226-
227-
private predicate inheritanceConversionValueNumber(
228-
InheritanceConversionInstruction instr, IRFunction irFunc, Opcode opcode,
229-
Language::Class baseClass, Language::Class derivedClass, ValueNumber operand
230-
) {
231-
instr.getEnclosingIRFunction() = irFunc and
232-
instr.getOpcode() = opcode and
233-
instr.getBaseClass() = baseClass and
234-
instr.getDerivedClass() = derivedClass and
235-
valueNumber(instr.getUnary()) = operand
236-
}
237-
238-
private predicate loadTotalOverlapValueNumber(
239-
LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, ValueNumber memOperand,
240-
ValueNumber operand
241-
) {
242-
instr.getEnclosingIRFunction() = irFunc and
243-
instr.getResultIRType() = type and
244-
valueNumber(instr.getAnOperand().(MemoryOperand).getAnyDef()) = memOperand and
245-
valueNumberOfOperand(instr.getAnOperand().(AddressOperand)) = operand
246-
}
247-
248-
/**
249-
* Holds if `instr` should be assigned a unique value number because this library does not know how
250-
* to determine if two instances of that instruction are equivalent.
251-
*/
252-
private predicate uniqueValueNumber(Instruction instr, IRFunction irFunc) {
253-
instr.getEnclosingIRFunction() = irFunc and
254-
not instr.getResultIRType() instanceof IRVoidType and
255-
not numberableInstruction(instr)
256-
}
257-
25894
/**
25995
* Gets the value number assigned to `instr`, if any. Returns at most one result.
26096
*/
261-
cached
262-
ValueNumber valueNumber(Instruction instr) {
263-
result = nonUniqueValueNumber(instr)
264-
or
265-
exists(IRFunction irFunc |
266-
uniqueValueNumber(instr, irFunc) and
267-
result = TUniqueValueNumber(irFunc, instr)
268-
)
269-
}
97+
ValueNumber valueNumber(Instruction instr) { result = tvalueNumber(instr) }
27098

27199
/**
272100
* Gets the value number assigned to the exact definition of `op`, if any.
273101
* Returns at most one result.
274102
*/
275-
ValueNumber valueNumberOfOperand(Operand op) { result = valueNumber(op.getDef()) }
276-
277-
/**
278-
* Gets the value number assigned to `instr`, if any, unless that instruction is assigned a unique
279-
* value number.
280-
*/
281-
private ValueNumber nonUniqueValueNumber(Instruction instr) {
282-
exists(IRFunction irFunc |
283-
irFunc = instr.getEnclosingIRFunction() and
284-
(
285-
exists(IRVariable var |
286-
variableAddressValueNumber(instr, irFunc, var) and
287-
result = TVariableAddressValueNumber(irFunc, var)
288-
)
289-
or
290-
exists(IRVariable var |
291-
initializeParameterValueNumber(instr, irFunc, var) and
292-
result = TInitializeParameterValueNumber(irFunc, var)
293-
)
294-
or
295-
initializeThisValueNumber(instr, irFunc) and
296-
result = TInitializeThisValueNumber(irFunc)
297-
or
298-
exists(IRType type, string value |
299-
constantValueNumber(instr, irFunc, type, value) and
300-
result = TConstantValueNumber(irFunc, type, value)
301-
)
302-
or
303-
exists(IRType type, string value |
304-
stringConstantValueNumber(instr, irFunc, type, value) and
305-
result = TStringConstantValueNumber(irFunc, type, value)
306-
)
307-
or
308-
exists(Language::Field field, ValueNumber objectAddress |
309-
fieldAddressValueNumber(instr, irFunc, field, objectAddress) and
310-
result = TFieldAddressValueNumber(irFunc, field, objectAddress)
311-
)
312-
or
313-
exists(Opcode opcode, IRType type, ValueNumber leftOperand, ValueNumber rightOperand |
314-
binaryValueNumber(instr, irFunc, opcode, type, leftOperand, rightOperand) and
315-
result = TBinaryValueNumber(irFunc, opcode, type, leftOperand, rightOperand)
316-
)
317-
or
318-
exists(Opcode opcode, IRType type, ValueNumber operand |
319-
unaryValueNumber(instr, irFunc, opcode, type, operand) and
320-
result = TUnaryValueNumber(irFunc, opcode, type, operand)
321-
)
322-
or
323-
exists(
324-
Opcode opcode, Language::Class baseClass, Language::Class derivedClass, ValueNumber operand
325-
|
326-
inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and
327-
result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand)
328-
)
329-
or
330-
exists(
331-
Opcode opcode, IRType type, int elementSize, ValueNumber leftOperand,
332-
ValueNumber rightOperand
333-
|
334-
pointerArithmeticValueNumber(instr, irFunc, opcode, type, elementSize, leftOperand,
335-
rightOperand) and
336-
result =
337-
TPointerArithmeticValueNumber(irFunc, opcode, type, elementSize, leftOperand, rightOperand)
338-
)
339-
or
340-
exists(IRType type, ValueNumber memOperand, ValueNumber operand |
341-
loadTotalOverlapValueNumber(instr, irFunc, type, memOperand, operand) and
342-
result = TLoadTotalOverlapValueNumber(irFunc, type, memOperand, operand)
343-
)
344-
or
345-
// The value number of a copy is just the value number of its source value.
346-
result = valueNumber(instr.(CongruentCopyInstruction).getSourceValue())
347-
)
348-
)
349-
}
103+
ValueNumber valueNumberOfOperand(Operand op) { result = tvalueNumberOfOperand(op) }
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
import semmle.code.cpp.ir.implementation.aliased_ssa.IR
12
import semmle.code.cpp.ir.internal.Overlap
23
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
4+
import semmle.code.cpp.Location

0 commit comments

Comments
 (0)