Skip to content

Commit 4997aa7

Browse files
authored
Merge pull request #2772 from MathiasVP/more-gvn-loads
C++: Better value numbering support for loading fields in IR
2 parents 2e883ab + aaa6233 commit 4997aa7

File tree

10 files changed

+517
-27
lines changed

10 files changed

+517
-27
lines changed

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ newtype TValueNumber =
5252
) {
5353
inheritanceConversionValueNumber(_, irFunc, opcode, baseClass, derivedClass, operand)
5454
} or
55+
TLoadTotalOverlapValueNumber(
56+
IRFunction irFunc, IRType type, ValueNumber memOperand, ValueNumber operand
57+
) {
58+
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
59+
} or
5560
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
5661

5762
/**
@@ -101,12 +106,18 @@ class ValueNumber extends TValueNumber {
101106
* The use of `p.x` on line 3 is linked to the definition of `p` on line 1 as well, but is not
102107
* congruent to that definition because `p.x` accesses only a subset of the memory defined by `p`.
103108
*/
104-
private class CongruentCopyInstruction extends CopyInstruction {
109+
class CongruentCopyInstruction extends CopyInstruction {
105110
CongruentCopyInstruction() {
106111
this.getSourceValueOperand().getDefinitionOverlap() instanceof MustExactlyOverlap
107112
}
108113
}
109114

115+
class LoadTotalOverlapInstruction extends LoadInstruction {
116+
LoadTotalOverlapInstruction() {
117+
this.getSourceValueOperand().getDefinitionOverlap() instanceof MustTotallyOverlap
118+
}
119+
}
120+
110121
/**
111122
* Holds if this library knows how to assign a value number to the specified instruction, other than
112123
* a `unique` value number that is never shared by multiple instructions.
@@ -131,6 +142,8 @@ private predicate numberableInstruction(Instruction instr) {
131142
instr instanceof PointerArithmeticInstruction
132143
or
133144
instr instanceof CongruentCopyInstruction
145+
or
146+
instr instanceof LoadTotalOverlapInstruction
134147
}
135148

136149
private predicate variableAddressValueNumber(
@@ -205,6 +218,7 @@ private predicate unaryValueNumber(
205218
instr.getEnclosingIRFunction() = irFunc and
206219
not instr instanceof InheritanceConversionInstruction and
207220
not instr instanceof CopyInstruction and
221+
not instr instanceof FieldAddressInstruction and
208222
instr.getOpcode() = opcode and
209223
instr.getResultIRType() = type and
210224
valueNumber(instr.getUnary()) = operand
@@ -221,6 +235,16 @@ private predicate inheritanceConversionValueNumber(
221235
valueNumber(instr.getUnary()) = operand
222236
}
223237

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+
224248
/**
225249
* Holds if `instr` should be assigned a unique value number because this library does not know how
226250
* to determine if two instances of that instruction are equivalent.
@@ -313,6 +337,11 @@ private ValueNumber nonUniqueValueNumber(Instruction instr) {
313337
TPointerArithmeticValueNumber(irFunc, opcode, type, elementSize, leftOperand, rightOperand)
314338
)
315339
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
316345
// The value number of a copy is just the value number of its source value.
317346
result = valueNumber(instr.(CongruentCopyInstruction).getSourceValue())
318347
)

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ newtype TValueNumber =
5252
) {
5353
inheritanceConversionValueNumber(_, irFunc, opcode, baseClass, derivedClass, operand)
5454
} or
55+
TLoadTotalOverlapValueNumber(
56+
IRFunction irFunc, IRType type, ValueNumber memOperand, ValueNumber operand
57+
) {
58+
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
59+
} or
5560
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
5661

5762
/**
@@ -101,12 +106,18 @@ class ValueNumber extends TValueNumber {
101106
* The use of `p.x` on line 3 is linked to the definition of `p` on line 1 as well, but is not
102107
* congruent to that definition because `p.x` accesses only a subset of the memory defined by `p`.
103108
*/
104-
private class CongruentCopyInstruction extends CopyInstruction {
109+
class CongruentCopyInstruction extends CopyInstruction {
105110
CongruentCopyInstruction() {
106111
this.getSourceValueOperand().getDefinitionOverlap() instanceof MustExactlyOverlap
107112
}
108113
}
109114

115+
class LoadTotalOverlapInstruction extends LoadInstruction {
116+
LoadTotalOverlapInstruction() {
117+
this.getSourceValueOperand().getDefinitionOverlap() instanceof MustTotallyOverlap
118+
}
119+
}
120+
110121
/**
111122
* Holds if this library knows how to assign a value number to the specified instruction, other than
112123
* a `unique` value number that is never shared by multiple instructions.
@@ -131,6 +142,8 @@ private predicate numberableInstruction(Instruction instr) {
131142
instr instanceof PointerArithmeticInstruction
132143
or
133144
instr instanceof CongruentCopyInstruction
145+
or
146+
instr instanceof LoadTotalOverlapInstruction
134147
}
135148

136149
private predicate variableAddressValueNumber(
@@ -205,6 +218,7 @@ private predicate unaryValueNumber(
205218
instr.getEnclosingIRFunction() = irFunc and
206219
not instr instanceof InheritanceConversionInstruction and
207220
not instr instanceof CopyInstruction and
221+
not instr instanceof FieldAddressInstruction and
208222
instr.getOpcode() = opcode and
209223
instr.getResultIRType() = type and
210224
valueNumber(instr.getUnary()) = operand
@@ -221,6 +235,16 @@ private predicate inheritanceConversionValueNumber(
221235
valueNumber(instr.getUnary()) = operand
222236
}
223237

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+
224248
/**
225249
* Holds if `instr` should be assigned a unique value number because this library does not know how
226250
* to determine if two instances of that instruction are equivalent.
@@ -313,6 +337,11 @@ private ValueNumber nonUniqueValueNumber(Instruction instr) {
313337
TPointerArithmeticValueNumber(irFunc, opcode, type, elementSize, leftOperand, rightOperand)
314338
)
315339
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
316345
// The value number of a copy is just the value number of its source value.
317346
result = valueNumber(instr.(CongruentCopyInstruction).getSourceValue())
318347
)

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ newtype TValueNumber =
5252
) {
5353
inheritanceConversionValueNumber(_, irFunc, opcode, baseClass, derivedClass, operand)
5454
} or
55+
TLoadTotalOverlapValueNumber(
56+
IRFunction irFunc, IRType type, ValueNumber memOperand, ValueNumber operand
57+
) {
58+
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
59+
} or
5560
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
5661

5762
/**
@@ -101,12 +106,18 @@ class ValueNumber extends TValueNumber {
101106
* The use of `p.x` on line 3 is linked to the definition of `p` on line 1 as well, but is not
102107
* congruent to that definition because `p.x` accesses only a subset of the memory defined by `p`.
103108
*/
104-
private class CongruentCopyInstruction extends CopyInstruction {
109+
class CongruentCopyInstruction extends CopyInstruction {
105110
CongruentCopyInstruction() {
106111
this.getSourceValueOperand().getDefinitionOverlap() instanceof MustExactlyOverlap
107112
}
108113
}
109114

115+
class LoadTotalOverlapInstruction extends LoadInstruction {
116+
LoadTotalOverlapInstruction() {
117+
this.getSourceValueOperand().getDefinitionOverlap() instanceof MustTotallyOverlap
118+
}
119+
}
120+
110121
/**
111122
* Holds if this library knows how to assign a value number to the specified instruction, other than
112123
* a `unique` value number that is never shared by multiple instructions.
@@ -131,6 +142,8 @@ private predicate numberableInstruction(Instruction instr) {
131142
instr instanceof PointerArithmeticInstruction
132143
or
133144
instr instanceof CongruentCopyInstruction
145+
or
146+
instr instanceof LoadTotalOverlapInstruction
134147
}
135148

136149
private predicate variableAddressValueNumber(
@@ -205,6 +218,7 @@ private predicate unaryValueNumber(
205218
instr.getEnclosingIRFunction() = irFunc and
206219
not instr instanceof InheritanceConversionInstruction and
207220
not instr instanceof CopyInstruction and
221+
not instr instanceof FieldAddressInstruction and
208222
instr.getOpcode() = opcode and
209223
instr.getResultIRType() = type and
210224
valueNumber(instr.getUnary()) = operand
@@ -221,6 +235,16 @@ private predicate inheritanceConversionValueNumber(
221235
valueNumber(instr.getUnary()) = operand
222236
}
223237

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+
224248
/**
225249
* Holds if `instr` should be assigned a unique value number because this library does not know how
226250
* to determine if two instances of that instruction are equivalent.
@@ -313,6 +337,11 @@ private ValueNumber nonUniqueValueNumber(Instruction instr) {
313337
TPointerArithmeticValueNumber(irFunc, opcode, type, elementSize, leftOperand, rightOperand)
314338
)
315339
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
316345
// The value number of a copy is just the value number of its source value.
317346
result = valueNumber(instr.(CongruentCopyInstruction).getSourceValue())
318347
)

cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/GlobalValueNumbering.expected

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,11 @@
3030
| test.cpp:105:11:105:12 | (Base *)... | 105:c11-c12 106:c14-c35 107:c11-c12 |
3131
| test.cpp:105:11:105:12 | pd | 105:c11-c12 106:c33-c34 |
3232
| test.cpp:105:15:105:15 | b | 105:c15-c15 107:c15-c15 109:c10-c10 |
33+
| test.cpp:125:11:125:12 | pa | 125:c11-c12 126:c11-c12 128:c3-c4 129:c11-c12 |
34+
| test.cpp:125:15:125:15 | x | 125:c15-c15 126:c15-c15 128:c7-c7 |
35+
| test.cpp:136:11:136:18 | global_a | 136:c11-c18 137:c11-c18 139:c3-c10 |
36+
| test.cpp:136:21:136:21 | x | 136:c21-c21 137:c21-c21 139:c13-c13 |
37+
| test.cpp:144:11:144:12 | pa | 144:c11-c12 145:c11-c12 147:c3-c4 149:c11-c12 |
38+
| test.cpp:145:15:145:15 | y | 145:c15-c15 147:c7-c7 |
39+
| test.cpp:153:11:153:18 | global_a | 153:c11-c18 154:c11-c18 156:c3-c10 |
40+
| test.cpp:153:21:153:21 | x | 153:c21-c21 154:c21-c21 |

0 commit comments

Comments
 (0)