Skip to content

Commit 97c5b8e

Browse files
authored
Merge pull request #882 from jbj/ir-ConstantAnalysis-perf
C++: Speed up IR ConstantAnalysis
2 parents 1f873d0 + cad4bac commit 97c5b8e

File tree

9 files changed

+289
-91
lines changed

9 files changed

+289
-91
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
Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,49 @@
11
private import internal.ConstantAnalysisInternal
2-
import semmle.code.cpp.ir.internal.IntegerConstant
2+
private import semmle.code.cpp.ir.internal.IntegerPartial
33
private import IR
44

55
language[monotonicAggregates]
6-
IntValue getConstantValue(Instruction instr) {
6+
int getConstantValue(Instruction instr) {
77
result = instr.(IntegerConstantInstruction).getValue().toInt() or
8-
exists(BinaryInstruction binInstr, IntValue left, IntValue right |
9-
binInstr = instr and
10-
left = getConstantValue(binInstr.getLeftOperand()) and
11-
right = getConstantValue(binInstr.getRightOperand()) and
12-
(
13-
binInstr instanceof AddInstruction and result = add(left, right) or
14-
binInstr instanceof SubInstruction and result = sub(left, right) or
15-
binInstr instanceof MulInstruction and result = mul(left, right) or
16-
binInstr instanceof DivInstruction and result = div(left, right) or
17-
binInstr instanceof CompareEQInstruction and result = compareEQ(left, right) or
18-
binInstr instanceof CompareNEInstruction and result = compareNE(left, right) or
19-
binInstr instanceof CompareLTInstruction and result = compareLT(left, right) or
20-
binInstr instanceof CompareGTInstruction and result = compareGT(left, right) or
21-
binInstr instanceof CompareLEInstruction and result = compareLE(left, right) or
22-
binInstr instanceof CompareGEInstruction and result = compareGE(left, right)
23-
)
24-
) or
25-
exists(UnaryInstruction unaryInstr, IntValue src |
26-
unaryInstr = instr and
27-
src = getConstantValue(unaryInstr.getOperand()) and
28-
(
29-
unaryInstr instanceof NegateInstruction and result = neg(src)
30-
)
31-
) or
8+
result = getBinaryInstructionValue(instr) or
9+
result = neg(getConstantValue(instr.(NegateInstruction).getOperand())) or
3210
result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or
3311
exists(PhiInstruction phi |
3412
phi = instr and
35-
result = max(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction())) and
36-
result = min(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction()))
13+
result = max(Instruction def | def = phi.getAnOperandDefinitionInstruction() | getConstantValueToPhi(def)) and
14+
result = min(Instruction def | def = phi.getAnOperandDefinitionInstruction() | getConstantValueToPhi(def))
15+
)
16+
}
17+
18+
pragma[noinline]
19+
int getConstantValueToPhi(Instruction def) {
20+
exists(PhiInstruction phi |
21+
result = getConstantValue(def) and
22+
def = phi.getAnOperandDefinitionInstruction()
23+
)
24+
}
25+
26+
pragma[noinline]
27+
private predicate binaryInstructionOperands(BinaryInstruction instr, int left, int right) {
28+
left = getConstantValue(instr.getLeftOperand()) and
29+
right = getConstantValue(instr.getRightOperand())
30+
}
31+
32+
pragma[noinline]
33+
private int getBinaryInstructionValue(BinaryInstruction instr) {
34+
exists(int left, int right |
35+
binaryInstructionOperands(instr, left, right) and
36+
(
37+
instr instanceof AddInstruction and result = add(left, right) or
38+
instr instanceof SubInstruction and result = sub(left, right) or
39+
instr instanceof MulInstruction and result = mul(left, right) or
40+
instr instanceof DivInstruction and result = div(left, right) or
41+
instr instanceof CompareEQInstruction and result = compareEQ(left, right) or
42+
instr instanceof CompareNEInstruction and result = compareNE(left, right) or
43+
instr instanceof CompareLTInstruction and result = compareLT(left, right) or
44+
instr instanceof CompareGTInstruction and result = compareGT(left, right) or
45+
instr instanceof CompareLEInstruction and result = compareLE(left, right) or
46+
instr instanceof CompareGEInstruction and result = compareGE(left, right)
47+
)
3748
)
3849
}

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
Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,49 @@
11
private import internal.ConstantAnalysisInternal
2-
import semmle.code.cpp.ir.internal.IntegerConstant
2+
private import semmle.code.cpp.ir.internal.IntegerPartial
33
private import IR
44

55
language[monotonicAggregates]
6-
IntValue getConstantValue(Instruction instr) {
6+
int getConstantValue(Instruction instr) {
77
result = instr.(IntegerConstantInstruction).getValue().toInt() or
8-
exists(BinaryInstruction binInstr, IntValue left, IntValue right |
9-
binInstr = instr and
10-
left = getConstantValue(binInstr.getLeftOperand()) and
11-
right = getConstantValue(binInstr.getRightOperand()) and
12-
(
13-
binInstr instanceof AddInstruction and result = add(left, right) or
14-
binInstr instanceof SubInstruction and result = sub(left, right) or
15-
binInstr instanceof MulInstruction and result = mul(left, right) or
16-
binInstr instanceof DivInstruction and result = div(left, right) or
17-
binInstr instanceof CompareEQInstruction and result = compareEQ(left, right) or
18-
binInstr instanceof CompareNEInstruction and result = compareNE(left, right) or
19-
binInstr instanceof CompareLTInstruction and result = compareLT(left, right) or
20-
binInstr instanceof CompareGTInstruction and result = compareGT(left, right) or
21-
binInstr instanceof CompareLEInstruction and result = compareLE(left, right) or
22-
binInstr instanceof CompareGEInstruction and result = compareGE(left, right)
23-
)
24-
) or
25-
exists(UnaryInstruction unaryInstr, IntValue src |
26-
unaryInstr = instr and
27-
src = getConstantValue(unaryInstr.getOperand()) and
28-
(
29-
unaryInstr instanceof NegateInstruction and result = neg(src)
30-
)
31-
) or
8+
result = getBinaryInstructionValue(instr) or
9+
result = neg(getConstantValue(instr.(NegateInstruction).getOperand())) or
3210
result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or
3311
exists(PhiInstruction phi |
3412
phi = instr and
35-
result = max(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction())) and
36-
result = min(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction()))
13+
result = max(Instruction def | def = phi.getAnOperandDefinitionInstruction() | getConstantValueToPhi(def)) and
14+
result = min(Instruction def | def = phi.getAnOperandDefinitionInstruction() | getConstantValueToPhi(def))
15+
)
16+
}
17+
18+
pragma[noinline]
19+
int getConstantValueToPhi(Instruction def) {
20+
exists(PhiInstruction phi |
21+
result = getConstantValue(def) and
22+
def = phi.getAnOperandDefinitionInstruction()
23+
)
24+
}
25+
26+
pragma[noinline]
27+
private predicate binaryInstructionOperands(BinaryInstruction instr, int left, int right) {
28+
left = getConstantValue(instr.getLeftOperand()) and
29+
right = getConstantValue(instr.getRightOperand())
30+
}
31+
32+
pragma[noinline]
33+
private int getBinaryInstructionValue(BinaryInstruction instr) {
34+
exists(int left, int right |
35+
binaryInstructionOperands(instr, left, right) and
36+
(
37+
instr instanceof AddInstruction and result = add(left, right) or
38+
instr instanceof SubInstruction and result = sub(left, right) or
39+
instr instanceof MulInstruction and result = mul(left, right) or
40+
instr instanceof DivInstruction and result = div(left, right) or
41+
instr instanceof CompareEQInstruction and result = compareEQ(left, right) or
42+
instr instanceof CompareNEInstruction and result = compareNE(left, right) or
43+
instr instanceof CompareLTInstruction and result = compareLT(left, right) or
44+
instr instanceof CompareGTInstruction and result = compareGT(left, right) or
45+
instr instanceof CompareLEInstruction and result = compareLE(left, right) or
46+
instr instanceof CompareGEInstruction and result = compareGE(left, right)
47+
)
3748
)
3849
}

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/ReachableBlock.qll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
private import ReachableBlockInternal
2-
private import semmle.code.cpp.ir.internal.IntegerConstant
32
private import IR
43
private import ConstantAnalysis
54

65
predicate isInfeasibleInstructionSuccessor(Instruction instr, EdgeKind kind) {
76
exists(int conditionValue |
8-
conditionValue = getValue(getConstantValue(instr.(ConditionalBranchInstruction).getCondition())) and
7+
conditionValue = getConstantValue(instr.(ConditionalBranchInstruction).getCondition()) and
98
if conditionValue = 0 then
109
kind instanceof TrueEdge
1110
else

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
Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,49 @@
11
private import internal.ConstantAnalysisInternal
2-
import semmle.code.cpp.ir.internal.IntegerConstant
2+
private import semmle.code.cpp.ir.internal.IntegerPartial
33
private import IR
44

55
language[monotonicAggregates]
6-
IntValue getConstantValue(Instruction instr) {
6+
int getConstantValue(Instruction instr) {
77
result = instr.(IntegerConstantInstruction).getValue().toInt() or
8-
exists(BinaryInstruction binInstr, IntValue left, IntValue right |
9-
binInstr = instr and
10-
left = getConstantValue(binInstr.getLeftOperand()) and
11-
right = getConstantValue(binInstr.getRightOperand()) and
12-
(
13-
binInstr instanceof AddInstruction and result = add(left, right) or
14-
binInstr instanceof SubInstruction and result = sub(left, right) or
15-
binInstr instanceof MulInstruction and result = mul(left, right) or
16-
binInstr instanceof DivInstruction and result = div(left, right) or
17-
binInstr instanceof CompareEQInstruction and result = compareEQ(left, right) or
18-
binInstr instanceof CompareNEInstruction and result = compareNE(left, right) or
19-
binInstr instanceof CompareLTInstruction and result = compareLT(left, right) or
20-
binInstr instanceof CompareGTInstruction and result = compareGT(left, right) or
21-
binInstr instanceof CompareLEInstruction and result = compareLE(left, right) or
22-
binInstr instanceof CompareGEInstruction and result = compareGE(left, right)
23-
)
24-
) or
25-
exists(UnaryInstruction unaryInstr, IntValue src |
26-
unaryInstr = instr and
27-
src = getConstantValue(unaryInstr.getOperand()) and
28-
(
29-
unaryInstr instanceof NegateInstruction and result = neg(src)
30-
)
31-
) or
8+
result = getBinaryInstructionValue(instr) or
9+
result = neg(getConstantValue(instr.(NegateInstruction).getOperand())) or
3210
result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or
3311
exists(PhiInstruction phi |
3412
phi = instr and
35-
result = max(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction())) and
36-
result = min(PhiOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDefinitionInstruction()))
13+
result = max(Instruction def | def = phi.getAnOperandDefinitionInstruction() | getConstantValueToPhi(def)) and
14+
result = min(Instruction def | def = phi.getAnOperandDefinitionInstruction() | getConstantValueToPhi(def))
15+
)
16+
}
17+
18+
pragma[noinline]
19+
int getConstantValueToPhi(Instruction def) {
20+
exists(PhiInstruction phi |
21+
result = getConstantValue(def) and
22+
def = phi.getAnOperandDefinitionInstruction()
23+
)
24+
}
25+
26+
pragma[noinline]
27+
private predicate binaryInstructionOperands(BinaryInstruction instr, int left, int right) {
28+
left = getConstantValue(instr.getLeftOperand()) and
29+
right = getConstantValue(instr.getRightOperand())
30+
}
31+
32+
pragma[noinline]
33+
private int getBinaryInstructionValue(BinaryInstruction instr) {
34+
exists(int left, int right |
35+
binaryInstructionOperands(instr, left, right) and
36+
(
37+
instr instanceof AddInstruction and result = add(left, right) or
38+
instr instanceof SubInstruction and result = sub(left, right) or
39+
instr instanceof MulInstruction and result = mul(left, right) or
40+
instr instanceof DivInstruction and result = div(left, right) or
41+
instr instanceof CompareEQInstruction and result = compareEQ(left, right) or
42+
instr instanceof CompareNEInstruction and result = compareNE(left, right) or
43+
instr instanceof CompareLTInstruction and result = compareLT(left, right) or
44+
instr instanceof CompareGTInstruction and result = compareGT(left, right) or
45+
instr instanceof CompareLEInstruction and result = compareLE(left, right) or
46+
instr instanceof CompareGEInstruction and result = compareGE(left, right)
47+
)
3748
)
3849
}

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/ReachableBlock.qll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
private import ReachableBlockInternal
2-
private import semmle.code.cpp.ir.internal.IntegerConstant
32
private import IR
43
private import ConstantAnalysis
54

65
predicate isInfeasibleInstructionSuccessor(Instruction instr, EdgeKind kind) {
76
exists(int conditionValue |
8-
conditionValue = getValue(getConstantValue(instr.(ConditionalBranchInstruction).getCondition())) and
7+
conditionValue = getConstantValue(instr.(ConditionalBranchInstruction).getCondition()) and
98
if conditionValue = 0 then
109
kind instanceof TrueEdge
1110
else

0 commit comments

Comments
 (0)