mirror of
https://github.com/github/codeql.git
synced 2026-04-29 18:55:14 +02:00
C++/C#: Use cached to ensure that IR is evaluated in a single stage
Before this change, evaluation of the IR was spread out across about 5 stages. This resulted in a lot of redundant evaluation, especially tuple numbering of large IPA types like `TInstruction`. This change makes two small changes that, when combined, ensure that the IR is evaluated all in one stage: First, we mark `TInstruction` as `cached`. This collapses all of the work to create instructions, across all three IR phases, into a single phase. Second, we make the `SSA` module in `SSAConstruction.qll` just contain aliases to `cached` predicates defined in the `Cached` module. This ensures that all of the `Operand`-related SSA computation happens in the same stage as all of the `Instruction`-related SSA computation.
This commit is contained in:
@@ -16,6 +16,31 @@ import Cached
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
cached
|
||||
predicate hasPhiInstructionCached(
|
||||
IRFunction irFunc, OldInstruction blockStartInstr, Alias::MemoryLocation defLocation
|
||||
) {
|
||||
exists(OldBlock oldBlock |
|
||||
definitionHasPhiNode(defLocation, oldBlock) and
|
||||
irFunc = oldBlock.getEnclosingIRFunction() and
|
||||
blockStartInstr = oldBlock.getFirstInstruction()
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasChiInstructionCached(IRFunctionBase irFunc, OldInstruction primaryInstruction) {
|
||||
hasChiNode(_, primaryInstruction) and
|
||||
irFunc = primaryInstruction.getEnclosingIRFunction()
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasUnreachedInstructionCached(IRFunction irFunc) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
irFunc = oldInstruction.getEnclosingIRFunction() and
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
|
||||
)
|
||||
}
|
||||
|
||||
class TStageInstruction =
|
||||
TRawInstruction or TPhiInstruction or TChiInstruction or TUnreachedInstruction;
|
||||
|
||||
@@ -876,33 +901,15 @@ module SSAConsistency {
|
||||
/**
|
||||
* Provides the portion of the parameterized IR interface that is used to construct the SSA stages
|
||||
* of the IR. The raw stage of the IR does not expose these predicates.
|
||||
* These predicates are all just aliases for predicates defined in the `Cached` module. This ensures
|
||||
* that all of SSA construction will be evaluated in the same stage.
|
||||
*/
|
||||
cached
|
||||
module SSA {
|
||||
class MemoryLocation = Alias::MemoryLocation;
|
||||
|
||||
cached
|
||||
predicate hasPhiInstruction(
|
||||
IRFunction irFunc, OldInstruction blockStartInstr, Alias::MemoryLocation defLocation
|
||||
) {
|
||||
exists(OldBlock oldBlock |
|
||||
definitionHasPhiNode(defLocation, oldBlock) and
|
||||
irFunc = oldBlock.getEnclosingIRFunction() and
|
||||
blockStartInstr = oldBlock.getFirstInstruction()
|
||||
)
|
||||
}
|
||||
predicate hasPhiInstruction = Cached::hasPhiInstructionCached/3;
|
||||
|
||||
cached
|
||||
predicate hasChiInstruction(IRFunctionBase irFunc, OldInstruction primaryInstruction) {
|
||||
hasChiNode(_, primaryInstruction) and
|
||||
irFunc = primaryInstruction.getEnclosingIRFunction()
|
||||
}
|
||||
predicate hasChiInstruction = Cached::hasChiInstructionCached/2;
|
||||
|
||||
cached
|
||||
predicate hasUnreachedInstruction(IRFunction irFunc) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
irFunc = oldInstruction.getEnclosingIRFunction() and
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
|
||||
)
|
||||
}
|
||||
predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ private import Imports::Opcode
|
||||
* all of the branches that can appear in that particular stage. The public `Instruction` class for
|
||||
* each phase extends the `TStageInstruction` type for that stage.
|
||||
*/
|
||||
newtype TInstruction =
|
||||
cached newtype TInstruction =
|
||||
TRawInstruction(
|
||||
IRFunctionBase irFunc, Opcode opcode, Language::AST ast,
|
||||
IRConstruction::Raw::InstructionTag1 tag1, IRConstruction::Raw::InstructionTag2 tag2
|
||||
|
||||
@@ -16,6 +16,31 @@ import Cached
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
cached
|
||||
predicate hasPhiInstructionCached(
|
||||
IRFunction irFunc, OldInstruction blockStartInstr, Alias::MemoryLocation defLocation
|
||||
) {
|
||||
exists(OldBlock oldBlock |
|
||||
definitionHasPhiNode(defLocation, oldBlock) and
|
||||
irFunc = oldBlock.getEnclosingIRFunction() and
|
||||
blockStartInstr = oldBlock.getFirstInstruction()
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasChiInstructionCached(IRFunctionBase irFunc, OldInstruction primaryInstruction) {
|
||||
hasChiNode(_, primaryInstruction) and
|
||||
irFunc = primaryInstruction.getEnclosingIRFunction()
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasUnreachedInstructionCached(IRFunction irFunc) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
irFunc = oldInstruction.getEnclosingIRFunction() and
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
|
||||
)
|
||||
}
|
||||
|
||||
class TStageInstruction =
|
||||
TRawInstruction or TPhiInstruction or TChiInstruction or TUnreachedInstruction;
|
||||
|
||||
@@ -876,33 +901,15 @@ module SSAConsistency {
|
||||
/**
|
||||
* Provides the portion of the parameterized IR interface that is used to construct the SSA stages
|
||||
* of the IR. The raw stage of the IR does not expose these predicates.
|
||||
* These predicates are all just aliases for predicates defined in the `Cached` module. This ensures
|
||||
* that all of SSA construction will be evaluated in the same stage.
|
||||
*/
|
||||
cached
|
||||
module SSA {
|
||||
class MemoryLocation = Alias::MemoryLocation;
|
||||
|
||||
cached
|
||||
predicate hasPhiInstruction(
|
||||
IRFunction irFunc, OldInstruction blockStartInstr, Alias::MemoryLocation defLocation
|
||||
) {
|
||||
exists(OldBlock oldBlock |
|
||||
definitionHasPhiNode(defLocation, oldBlock) and
|
||||
irFunc = oldBlock.getEnclosingIRFunction() and
|
||||
blockStartInstr = oldBlock.getFirstInstruction()
|
||||
)
|
||||
}
|
||||
predicate hasPhiInstruction = Cached::hasPhiInstructionCached/3;
|
||||
|
||||
cached
|
||||
predicate hasChiInstruction(IRFunctionBase irFunc, OldInstruction primaryInstruction) {
|
||||
hasChiNode(_, primaryInstruction) and
|
||||
irFunc = primaryInstruction.getEnclosingIRFunction()
|
||||
}
|
||||
predicate hasChiInstruction = Cached::hasChiInstructionCached/2;
|
||||
|
||||
cached
|
||||
predicate hasUnreachedInstruction(IRFunction irFunc) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
irFunc = oldInstruction.getEnclosingIRFunction() and
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
|
||||
)
|
||||
}
|
||||
predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user