Skip to content

Commit be35c67

Browse files
committed
C++: Factor out getConstantValueToPhi
This speeds up `getConstantValue`, the main predicate in `ConstantAnalysis`, from 2.4s to 1.6s on comdb2.
1 parent 283bb2f commit be35c67

File tree

6 files changed

+66
-9
lines changed

6 files changed

+66
-9
lines changed

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1484,6 +1484,17 @@ class PhiInstruction extends Instruction {
14841484
override final MemoryAccessKind getResultMemoryAccess() {
14851485
result instanceof PhiMemoryAccess
14861486
}
1487+
1488+
/**
1489+
* Gets an instruction that defines the input to one of the operands of this
1490+
* instruction. It's possible for more than one operand to have the same
1491+
* defining instruction, so this predicate will have the same number of
1492+
* results as `getAnOperand()` or fewer.
1493+
*/
1494+
pragma[noinline]
1495+
final Instruction getAnOperandDefinitionInstruction() {
1496+
result = this.getAnOperand().(PhiOperand).getDefinitionInstruction()
1497+
}
14871498
}
14881499

14891500
/**
@@ -1492,7 +1503,7 @@ class PhiInstruction extends Instruction {
14921503
*
14931504
* A `ChiInstruction` is inserted immediately after an instruction that writes to memory. The
14941505
* `ChiInstruction` has two operands. The first operand, given by `getTotalOperand()`, represents
1495-
* the previous state of all of the memory that might be alised by the memory write. The second
1506+
* the previous state of all of the memory that might be aliased by the memory write. The second
14961507
* operand, given by `getPartialOperand()`, represents the memory that was actually modified by the
14971508
* memory write. The result of the `ChiInstruction` represents the same memory as
14981509
* `getTotalOperand()`, updated to include the changes due to the value that was actually stored by

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/constant/ConstantAnalysis.qll

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,16 @@ int getConstantValue(Instruction instr) {
1616
result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or
1717
exists(PhiInstruction phi |
1818
phi = instr and
19-
result = max(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction())) and
20-
result = min(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction()))
19+
result = max(Instruction def | def = phi.getAnOperandDefinitionInstruction() | getConstantValueToPhi(def)) and
20+
result = min(Instruction def | def = phi.getAnOperandDefinitionInstruction() | getConstantValueToPhi(def))
21+
)
22+
}
23+
24+
pragma[noinline]
25+
int getConstantValueToPhi(Instruction def) {
26+
exists(PhiInstruction phi |
27+
result = getConstantValue(def) and
28+
def = phi.getAnOperandDefinitionInstruction()
2129
)
2230
}
2331

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1484,6 +1484,17 @@ class PhiInstruction extends Instruction {
14841484
override final MemoryAccessKind getResultMemoryAccess() {
14851485
result instanceof PhiMemoryAccess
14861486
}
1487+
1488+
/**
1489+
* Gets an instruction that defines the input to one of the operands of this
1490+
* instruction. It's possible for more than one operand to have the same
1491+
* defining instruction, so this predicate will have the same number of
1492+
* results as `getAnOperand()` or fewer.
1493+
*/
1494+
pragma[noinline]
1495+
final Instruction getAnOperandDefinitionInstruction() {
1496+
result = this.getAnOperand().(PhiOperand).getDefinitionInstruction()
1497+
}
14871498
}
14881499

14891500
/**
@@ -1492,7 +1503,7 @@ class PhiInstruction extends Instruction {
14921503
*
14931504
* A `ChiInstruction` is inserted immediately after an instruction that writes to memory. The
14941505
* `ChiInstruction` has two operands. The first operand, given by `getTotalOperand()`, represents
1495-
* the previous state of all of the memory that might be alised by the memory write. The second
1506+
* the previous state of all of the memory that might be aliased by the memory write. The second
14961507
* operand, given by `getPartialOperand()`, represents the memory that was actually modified by the
14971508
* memory write. The result of the `ChiInstruction` represents the same memory as
14981509
* `getTotalOperand()`, updated to include the changes due to the value that was actually stored by

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/constant/ConstantAnalysis.qll

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,16 @@ int getConstantValue(Instruction instr) {
1616
result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or
1717
exists(PhiInstruction phi |
1818
phi = instr and
19-
result = max(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction())) and
20-
result = min(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction()))
19+
result = max(Instruction def | def = phi.getAnOperandDefinitionInstruction() | getConstantValueToPhi(def)) and
20+
result = min(Instruction def | def = phi.getAnOperandDefinitionInstruction() | getConstantValueToPhi(def))
21+
)
22+
}
23+
24+
pragma[noinline]
25+
int getConstantValueToPhi(Instruction def) {
26+
exists(PhiInstruction phi |
27+
result = getConstantValue(def) and
28+
def = phi.getAnOperandDefinitionInstruction()
2129
)
2230
}
2331

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1484,6 +1484,17 @@ class PhiInstruction extends Instruction {
14841484
override final MemoryAccessKind getResultMemoryAccess() {
14851485
result instanceof PhiMemoryAccess
14861486
}
1487+
1488+
/**
1489+
* Gets an instruction that defines the input to one of the operands of this
1490+
* instruction. It's possible for more than one operand to have the same
1491+
* defining instruction, so this predicate will have the same number of
1492+
* results as `getAnOperand()` or fewer.
1493+
*/
1494+
pragma[noinline]
1495+
final Instruction getAnOperandDefinitionInstruction() {
1496+
result = this.getAnOperand().(PhiOperand).getDefinitionInstruction()
1497+
}
14871498
}
14881499

14891500
/**
@@ -1492,7 +1503,7 @@ class PhiInstruction extends Instruction {
14921503
*
14931504
* A `ChiInstruction` is inserted immediately after an instruction that writes to memory. The
14941505
* `ChiInstruction` has two operands. The first operand, given by `getTotalOperand()`, represents
1495-
* the previous state of all of the memory that might be alised by the memory write. The second
1506+
* the previous state of all of the memory that might be aliased by the memory write. The second
14961507
* operand, given by `getPartialOperand()`, represents the memory that was actually modified by the
14971508
* memory write. The result of the `ChiInstruction` represents the same memory as
14981509
* `getTotalOperand()`, updated to include the changes due to the value that was actually stored by

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/constant/ConstantAnalysis.qll

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,16 @@ int getConstantValue(Instruction instr) {
1616
result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or
1717
exists(PhiInstruction phi |
1818
phi = instr and
19-
result = max(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction())) and
20-
result = min(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction()))
19+
result = max(Instruction def | def = phi.getAnOperandDefinitionInstruction() | getConstantValueToPhi(def)) and
20+
result = min(Instruction def | def = phi.getAnOperandDefinitionInstruction() | getConstantValueToPhi(def))
21+
)
22+
}
23+
24+
pragma[noinline]
25+
int getConstantValueToPhi(Instruction def) {
26+
exists(PhiInstruction phi |
27+
result = getConstantValue(def) and
28+
def = phi.getAnOperandDefinitionInstruction()
2129
)
2230
}
2331

0 commit comments

Comments
 (0)