Skip to content

Commit 0628625

Browse files
authored
Merge pull request github#2835 from MathiasVP/value-number-perf
C++: Value number performance fix
2 parents 8cda847 + 49d2f5a commit 0628625

File tree

3 files changed

+135
-99
lines changed

3 files changed

+135
-99
lines changed

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

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,18 @@ newtype TValueNumber =
1919
fieldAddressValueNumber(_, irFunc, field, objectAddress)
2020
} or
2121
TBinaryValueNumber(
22-
IRFunction irFunc, Opcode opcode, IRType type, TValueNumber leftOperand,
23-
TValueNumber rightOperand
22+
IRFunction irFunc, Opcode opcode, TValueNumber leftOperand, TValueNumber rightOperand
2423
) {
25-
binaryValueNumber(_, irFunc, opcode, type, leftOperand, rightOperand)
24+
binaryValueNumber(_, irFunc, opcode, leftOperand, rightOperand)
2625
} or
2726
TPointerArithmeticValueNumber(
28-
IRFunction irFunc, Opcode opcode, IRType type, int elementSize, TValueNumber leftOperand,
27+
IRFunction irFunc, Opcode opcode, int elementSize, TValueNumber leftOperand,
2928
TValueNumber rightOperand
3029
) {
31-
pointerArithmeticValueNumber(_, irFunc, opcode, type, elementSize, leftOperand, rightOperand)
30+
pointerArithmeticValueNumber(_, irFunc, opcode, elementSize, leftOperand, rightOperand)
3231
} or
33-
TUnaryValueNumber(IRFunction irFunc, Opcode opcode, IRType type, TValueNumber operand) {
34-
unaryValueNumber(_, irFunc, opcode, type, operand)
32+
TUnaryValueNumber(IRFunction irFunc, Opcode opcode, TValueNumber operand) {
33+
unaryValueNumber(_, irFunc, opcode, operand)
3534
} or
3635
TInheritanceConversionValueNumber(
3736
IRFunction irFunc, Opcode opcode, Class baseClass, Class derivedClass, TValueNumber operand
@@ -99,14 +98,28 @@ private predicate numberableInstruction(Instruction instr) {
9998
instr instanceof LoadTotalOverlapInstruction
10099
}
101100

101+
private predicate filteredNumberableInstruction(Instruction instr) {
102+
// count rather than strictcount to handle missing AST elements
103+
// separate instanceof and inline casts to avoid failed casts with a count of 0
104+
instr instanceof VariableAddressInstruction and
105+
count(instr.(VariableAddressInstruction).getIRVariable().getAST()) != 1
106+
or
107+
instr instanceof ConstantInstruction and
108+
count(instr.getResultIRType()) != 1
109+
or
110+
instr instanceof FieldAddressInstruction and
111+
count(instr.(FieldAddressInstruction).getField()) != 1
112+
}
113+
102114
private predicate variableAddressValueNumber(
103115
VariableAddressInstruction instr, IRFunction irFunc, Language::AST ast
104116
) {
105117
instr.getEnclosingIRFunction() = irFunc and
106118
// The underlying AST element is used as value-numbering key instead of the
107119
// `IRVariable` to work around a problem where a variable or expression with
108120
// multiple types gives rise to multiple `IRVariable`s.
109-
instr.getIRVariable().getAST() = ast
121+
instr.getIRVariable().getAST() = ast and
122+
strictcount(instr.getIRVariable().getAST()) = 1
110123
}
111124

112125
private predicate initializeParameterValueNumber(
@@ -123,10 +136,11 @@ private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRF
123136
instr.getEnclosingIRFunction() = irFunc
124137
}
125138

126-
private predicate constantValueNumber(
139+
predicate constantValueNumber(
127140
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
128141
) {
129142
instr.getEnclosingIRFunction() = irFunc and
143+
strictcount(instr.getResultIRType()) = 1 and
130144
instr.getResultIRType() = type and
131145
instr.getValue() = value
132146
}
@@ -145,42 +159,40 @@ private predicate fieldAddressValueNumber(
145159
) {
146160
instr.getEnclosingIRFunction() = irFunc and
147161
instr.getField() = field and
162+
strictcount(instr.getField()) = 1 and
148163
tvalueNumber(instr.getObjectAddress()) = objectAddress
149164
}
150165

151166
private predicate binaryValueNumber(
152-
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, IRType type, TValueNumber leftOperand,
167+
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber leftOperand,
153168
TValueNumber rightOperand
154169
) {
155170
instr.getEnclosingIRFunction() = irFunc and
156171
not instr instanceof PointerArithmeticInstruction and
157172
instr.getOpcode() = opcode and
158-
instr.getResultIRType() = type and
159173
tvalueNumber(instr.getLeft()) = leftOperand and
160174
tvalueNumber(instr.getRight()) = rightOperand
161175
}
162176

163177
private predicate pointerArithmeticValueNumber(
164-
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, IRType type,
165-
int elementSize, TValueNumber leftOperand, TValueNumber rightOperand
178+
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize,
179+
TValueNumber leftOperand, TValueNumber rightOperand
166180
) {
167181
instr.getEnclosingIRFunction() = irFunc and
168182
instr.getOpcode() = opcode and
169-
instr.getResultIRType() = type and
170183
instr.getElementSize() = elementSize and
171184
tvalueNumber(instr.getLeft()) = leftOperand and
172185
tvalueNumber(instr.getRight()) = rightOperand
173186
}
174187

175188
private predicate unaryValueNumber(
176-
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, IRType type, TValueNumber operand
189+
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber operand
177190
) {
178191
instr.getEnclosingIRFunction() = irFunc and
179192
not instr instanceof InheritanceConversionInstruction and
180193
not instr instanceof CopyInstruction and
181194
not instr instanceof FieldAddressInstruction and
182195
instr.getOpcode() = opcode and
183-
instr.getResultIRType() = type and
184196
tvalueNumber(instr.getUnary()) = operand
185197
}
186198

@@ -200,9 +212,9 @@ private predicate loadTotalOverlapValueNumber(
200212
TValueNumber operand
201213
) {
202214
instr.getEnclosingIRFunction() = irFunc and
203-
instr.getResultIRType() = type and
204215
tvalueNumber(instr.getAnOperand().(MemoryOperand).getAnyDef()) = memOperand and
205-
tvalueNumberOfOperand(instr.getAnOperand().(AddressOperand)) = operand
216+
tvalueNumberOfOperand(instr.getAnOperand().(AddressOperand)) = operand and
217+
instr.getResultIRType() = type
206218
}
207219

208220
/**
@@ -212,7 +224,11 @@ private predicate loadTotalOverlapValueNumber(
212224
private predicate uniqueValueNumber(Instruction instr, IRFunction irFunc) {
213225
instr.getEnclosingIRFunction() = irFunc and
214226
not instr.getResultIRType() instanceof IRVoidType and
215-
not numberableInstruction(instr)
227+
(
228+
not numberableInstruction(instr)
229+
or
230+
filteredNumberableInstruction(instr)
231+
)
216232
}
217233

218234
/**
@@ -255,7 +271,7 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
255271
initializeThisValueNumber(instr, irFunc) and
256272
result = TInitializeThisValueNumber(irFunc)
257273
or
258-
exists(IRType type, string value |
274+
exists(string value, IRType type |
259275
constantValueNumber(instr, irFunc, type, value) and
260276
result = TConstantValueNumber(irFunc, type, value)
261277
)
@@ -270,14 +286,14 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
270286
result = TFieldAddressValueNumber(irFunc, field, objectAddress)
271287
)
272288
or
273-
exists(Opcode opcode, IRType type, TValueNumber leftOperand, TValueNumber rightOperand |
274-
binaryValueNumber(instr, irFunc, opcode, type, leftOperand, rightOperand) and
275-
result = TBinaryValueNumber(irFunc, opcode, type, leftOperand, rightOperand)
289+
exists(Opcode opcode, TValueNumber leftOperand, TValueNumber rightOperand |
290+
binaryValueNumber(instr, irFunc, opcode, leftOperand, rightOperand) and
291+
result = TBinaryValueNumber(irFunc, opcode, leftOperand, rightOperand)
276292
)
277293
or
278-
exists(Opcode opcode, IRType type, TValueNumber operand |
279-
unaryValueNumber(instr, irFunc, opcode, type, operand) and
280-
result = TUnaryValueNumber(irFunc, opcode, type, operand)
294+
exists(Opcode opcode, TValueNumber operand |
295+
unaryValueNumber(instr, irFunc, opcode, operand) and
296+
result = TUnaryValueNumber(irFunc, opcode, operand)
281297
)
282298
or
283299
exists(
@@ -287,14 +303,10 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
287303
result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand)
288304
)
289305
or
290-
exists(
291-
Opcode opcode, IRType type, int elementSize, TValueNumber leftOperand,
292-
TValueNumber rightOperand
293-
|
294-
pointerArithmeticValueNumber(instr, irFunc, opcode, type, elementSize, leftOperand,
295-
rightOperand) and
306+
exists(Opcode opcode, int elementSize, TValueNumber leftOperand, TValueNumber rightOperand |
307+
pointerArithmeticValueNumber(instr, irFunc, opcode, elementSize, leftOperand, rightOperand) and
296308
result =
297-
TPointerArithmeticValueNumber(irFunc, opcode, type, elementSize, leftOperand, rightOperand)
309+
TPointerArithmeticValueNumber(irFunc, opcode, elementSize, leftOperand, rightOperand)
298310
)
299311
or
300312
exists(IRType type, TValueNumber memOperand, TValueNumber operand |

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

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,18 @@ newtype TValueNumber =
1919
fieldAddressValueNumber(_, irFunc, field, objectAddress)
2020
} or
2121
TBinaryValueNumber(
22-
IRFunction irFunc, Opcode opcode, IRType type, TValueNumber leftOperand,
23-
TValueNumber rightOperand
22+
IRFunction irFunc, Opcode opcode, TValueNumber leftOperand, TValueNumber rightOperand
2423
) {
25-
binaryValueNumber(_, irFunc, opcode, type, leftOperand, rightOperand)
24+
binaryValueNumber(_, irFunc, opcode, leftOperand, rightOperand)
2625
} or
2726
TPointerArithmeticValueNumber(
28-
IRFunction irFunc, Opcode opcode, IRType type, int elementSize, TValueNumber leftOperand,
27+
IRFunction irFunc, Opcode opcode, int elementSize, TValueNumber leftOperand,
2928
TValueNumber rightOperand
3029
) {
31-
pointerArithmeticValueNumber(_, irFunc, opcode, type, elementSize, leftOperand, rightOperand)
30+
pointerArithmeticValueNumber(_, irFunc, opcode, elementSize, leftOperand, rightOperand)
3231
} or
33-
TUnaryValueNumber(IRFunction irFunc, Opcode opcode, IRType type, TValueNumber operand) {
34-
unaryValueNumber(_, irFunc, opcode, type, operand)
32+
TUnaryValueNumber(IRFunction irFunc, Opcode opcode, TValueNumber operand) {
33+
unaryValueNumber(_, irFunc, opcode, operand)
3534
} or
3635
TInheritanceConversionValueNumber(
3736
IRFunction irFunc, Opcode opcode, Class baseClass, Class derivedClass, TValueNumber operand
@@ -99,14 +98,28 @@ private predicate numberableInstruction(Instruction instr) {
9998
instr instanceof LoadTotalOverlapInstruction
10099
}
101100

101+
private predicate filteredNumberableInstruction(Instruction instr) {
102+
// count rather than strictcount to handle missing AST elements
103+
// separate instanceof and inline casts to avoid failed casts with a count of 0
104+
instr instanceof VariableAddressInstruction and
105+
count(instr.(VariableAddressInstruction).getIRVariable().getAST()) != 1
106+
or
107+
instr instanceof ConstantInstruction and
108+
count(instr.getResultIRType()) != 1
109+
or
110+
instr instanceof FieldAddressInstruction and
111+
count(instr.(FieldAddressInstruction).getField()) != 1
112+
}
113+
102114
private predicate variableAddressValueNumber(
103115
VariableAddressInstruction instr, IRFunction irFunc, Language::AST ast
104116
) {
105117
instr.getEnclosingIRFunction() = irFunc and
106118
// The underlying AST element is used as value-numbering key instead of the
107119
// `IRVariable` to work around a problem where a variable or expression with
108120
// multiple types gives rise to multiple `IRVariable`s.
109-
instr.getIRVariable().getAST() = ast
121+
instr.getIRVariable().getAST() = ast and
122+
strictcount(instr.getIRVariable().getAST()) = 1
110123
}
111124

112125
private predicate initializeParameterValueNumber(
@@ -123,10 +136,11 @@ private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRF
123136
instr.getEnclosingIRFunction() = irFunc
124137
}
125138

126-
private predicate constantValueNumber(
139+
predicate constantValueNumber(
127140
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
128141
) {
129142
instr.getEnclosingIRFunction() = irFunc and
143+
strictcount(instr.getResultIRType()) = 1 and
130144
instr.getResultIRType() = type and
131145
instr.getValue() = value
132146
}
@@ -145,42 +159,40 @@ private predicate fieldAddressValueNumber(
145159
) {
146160
instr.getEnclosingIRFunction() = irFunc and
147161
instr.getField() = field and
162+
strictcount(instr.getField()) = 1 and
148163
tvalueNumber(instr.getObjectAddress()) = objectAddress
149164
}
150165

151166
private predicate binaryValueNumber(
152-
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, IRType type, TValueNumber leftOperand,
167+
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber leftOperand,
153168
TValueNumber rightOperand
154169
) {
155170
instr.getEnclosingIRFunction() = irFunc and
156171
not instr instanceof PointerArithmeticInstruction and
157172
instr.getOpcode() = opcode and
158-
instr.getResultIRType() = type and
159173
tvalueNumber(instr.getLeft()) = leftOperand and
160174
tvalueNumber(instr.getRight()) = rightOperand
161175
}
162176

163177
private predicate pointerArithmeticValueNumber(
164-
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, IRType type,
165-
int elementSize, TValueNumber leftOperand, TValueNumber rightOperand
178+
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize,
179+
TValueNumber leftOperand, TValueNumber rightOperand
166180
) {
167181
instr.getEnclosingIRFunction() = irFunc and
168182
instr.getOpcode() = opcode and
169-
instr.getResultIRType() = type and
170183
instr.getElementSize() = elementSize and
171184
tvalueNumber(instr.getLeft()) = leftOperand and
172185
tvalueNumber(instr.getRight()) = rightOperand
173186
}
174187

175188
private predicate unaryValueNumber(
176-
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, IRType type, TValueNumber operand
189+
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber operand
177190
) {
178191
instr.getEnclosingIRFunction() = irFunc and
179192
not instr instanceof InheritanceConversionInstruction and
180193
not instr instanceof CopyInstruction and
181194
not instr instanceof FieldAddressInstruction and
182195
instr.getOpcode() = opcode and
183-
instr.getResultIRType() = type and
184196
tvalueNumber(instr.getUnary()) = operand
185197
}
186198

@@ -200,9 +212,9 @@ private predicate loadTotalOverlapValueNumber(
200212
TValueNumber operand
201213
) {
202214
instr.getEnclosingIRFunction() = irFunc and
203-
instr.getResultIRType() = type and
204215
tvalueNumber(instr.getAnOperand().(MemoryOperand).getAnyDef()) = memOperand and
205-
tvalueNumberOfOperand(instr.getAnOperand().(AddressOperand)) = operand
216+
tvalueNumberOfOperand(instr.getAnOperand().(AddressOperand)) = operand and
217+
instr.getResultIRType() = type
206218
}
207219

208220
/**
@@ -212,7 +224,11 @@ private predicate loadTotalOverlapValueNumber(
212224
private predicate uniqueValueNumber(Instruction instr, IRFunction irFunc) {
213225
instr.getEnclosingIRFunction() = irFunc and
214226
not instr.getResultIRType() instanceof IRVoidType and
215-
not numberableInstruction(instr)
227+
(
228+
not numberableInstruction(instr)
229+
or
230+
filteredNumberableInstruction(instr)
231+
)
216232
}
217233

218234
/**
@@ -255,7 +271,7 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
255271
initializeThisValueNumber(instr, irFunc) and
256272
result = TInitializeThisValueNumber(irFunc)
257273
or
258-
exists(IRType type, string value |
274+
exists(string value, IRType type |
259275
constantValueNumber(instr, irFunc, type, value) and
260276
result = TConstantValueNumber(irFunc, type, value)
261277
)
@@ -270,14 +286,14 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
270286
result = TFieldAddressValueNumber(irFunc, field, objectAddress)
271287
)
272288
or
273-
exists(Opcode opcode, IRType type, TValueNumber leftOperand, TValueNumber rightOperand |
274-
binaryValueNumber(instr, irFunc, opcode, type, leftOperand, rightOperand) and
275-
result = TBinaryValueNumber(irFunc, opcode, type, leftOperand, rightOperand)
289+
exists(Opcode opcode, TValueNumber leftOperand, TValueNumber rightOperand |
290+
binaryValueNumber(instr, irFunc, opcode, leftOperand, rightOperand) and
291+
result = TBinaryValueNumber(irFunc, opcode, leftOperand, rightOperand)
276292
)
277293
or
278-
exists(Opcode opcode, IRType type, TValueNumber operand |
279-
unaryValueNumber(instr, irFunc, opcode, type, operand) and
280-
result = TUnaryValueNumber(irFunc, opcode, type, operand)
294+
exists(Opcode opcode, TValueNumber operand |
295+
unaryValueNumber(instr, irFunc, opcode, operand) and
296+
result = TUnaryValueNumber(irFunc, opcode, operand)
281297
)
282298
or
283299
exists(
@@ -287,14 +303,10 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
287303
result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand)
288304
)
289305
or
290-
exists(
291-
Opcode opcode, IRType type, int elementSize, TValueNumber leftOperand,
292-
TValueNumber rightOperand
293-
|
294-
pointerArithmeticValueNumber(instr, irFunc, opcode, type, elementSize, leftOperand,
295-
rightOperand) and
306+
exists(Opcode opcode, int elementSize, TValueNumber leftOperand, TValueNumber rightOperand |
307+
pointerArithmeticValueNumber(instr, irFunc, opcode, elementSize, leftOperand, rightOperand) and
296308
result =
297-
TPointerArithmeticValueNumber(irFunc, opcode, type, elementSize, leftOperand, rightOperand)
309+
TPointerArithmeticValueNumber(irFunc, opcode, elementSize, leftOperand, rightOperand)
298310
)
299311
or
300312
exists(IRType type, TValueNumber memOperand, TValueNumber operand |

0 commit comments

Comments
 (0)