C++: Stop caching raw IR construction predicates

These predicates are only used within the new single IR stage, so there's no need to cache them beyond that. RA diffs are trivial. Where previously many of the predicate on `Instruction` were inline wrappers around cached predicates from `IRConstruction`, now the predicates from `IRConstruction` get inlined into the `Instruction` predicates, and the `Instruction` predicates get materialized. The net amount of work is the same, but now it's not getting cached unnecessarily.
This commit is contained in:
Dave Bartolomeo
2020-06-17 09:47:48 -04:00
parent 8e977dc6bf
commit e85cc0b0c6

View File

@@ -169,60 +169,51 @@ module Raw {
} }
} }
import Cached class TStageInstruction = TRawInstruction;
cached predicate hasInstruction(TRawInstruction instr) { any() }
private module Cached {
class TStageInstruction = TRawInstruction;
cached predicate hasModeledMemoryResult(Instruction instruction) { none() }
predicate hasInstruction(TRawInstruction instr) { any() }
cached predicate hasConflatedMemoryResult(Instruction instruction) {
predicate hasModeledMemoryResult(Instruction instruction) { none() }
cached
predicate hasConflatedMemoryResult(Instruction instruction) {
instruction instanceof AliasedDefinitionInstruction instruction instanceof AliasedDefinitionInstruction
or or
instruction.getOpcode() instanceof Opcode::InitializeNonLocal instruction.getOpcode() instanceof Opcode::InitializeNonLocal
} }
cached Instruction getRegisterOperandDefinition(Instruction instruction, RegisterOperandTag tag) {
Instruction getRegisterOperandDefinition(Instruction instruction, RegisterOperandTag tag) {
result = result =
getInstructionTranslatedElement(instruction) getInstructionTranslatedElement(instruction)
.getInstructionRegisterOperand(getInstructionTag(instruction), tag) .getInstructionRegisterOperand(getInstructionTag(instruction), tag)
} }
cached Instruction getMemoryOperandDefinition(
Instruction getMemoryOperandDefinition(
Instruction instruction, MemoryOperandTag tag, Overlap overlap Instruction instruction, MemoryOperandTag tag, Overlap overlap
) { ) {
none() none()
} }
/** Gets a non-phi instruction that defines an operand of `instr`. */ /** Gets a non-phi instruction that defines an operand of `instr`. */
private Instruction getNonPhiOperandDef(Instruction instr) { private Instruction getNonPhiOperandDef(Instruction instr) {
result = getRegisterOperandDefinition(instr, _) result = getRegisterOperandDefinition(instr, _)
or or
result = getMemoryOperandDefinition(instr, _, _) result = getMemoryOperandDefinition(instr, _, _)
} }
/** /**
* Gets a non-phi instruction that defines an operand of `instr` but only if * Gets a non-phi instruction that defines an operand of `instr` but only if
* both `instr` and the result have neighbor on the other side of the edge * both `instr` and the result have neighbor on the other side of the edge
* between them. This is a necessary condition for being in a cycle, and it * between them. This is a necessary condition for being in a cycle, and it
* removes about two thirds of the tuples that would otherwise be in this * removes about two thirds of the tuples that would otherwise be in this
* predicate. * predicate.
*/ */
private Instruction getNonPhiOperandDefOfIntermediate(Instruction instr) { private Instruction getNonPhiOperandDefOfIntermediate(Instruction instr) {
result = getNonPhiOperandDef(instr) and result = getNonPhiOperandDef(instr) and
exists(getNonPhiOperandDef(result)) and exists(getNonPhiOperandDef(result)) and
instr = getNonPhiOperandDef(_) instr = getNonPhiOperandDef(_)
} }
/** /**
* Holds if `instr` is part of a cycle in the operand graph that doesn't go * Holds if `instr` is part of a cycle in the operand graph that doesn't go
* through a phi instruction and therefore should be impossible. * through a phi instruction and therefore should be impossible.
* *
@@ -231,15 +222,13 @@ private module Cached {
* analyses that assume a cycle-free graph of non-phi operands. Therefore it's * analyses that assume a cycle-free graph of non-phi operands. Therefore it's
* better to remove these operands than to leave cycles in the operand graph. * better to remove these operands than to leave cycles in the operand graph.
*/ */
pragma[noopt] pragma[noopt]
cached predicate isInCycle(Instruction instr) {
predicate isInCycle(Instruction instr) {
instr instanceof Instruction and instr instanceof Instruction and
getNonPhiOperandDefOfIntermediate+(instr) = instr getNonPhiOperandDefOfIntermediate+(instr) = instr
} }
cached CppType getInstructionOperandType(Instruction instruction, TypedOperandTag tag) {
CppType getInstructionOperandType(Instruction instruction, TypedOperandTag tag) {
// For all `LoadInstruction`s, the operand type of the `LoadOperand` is the same as // For all `LoadInstruction`s, the operand type of the `LoadOperand` is the same as
// the result type of the load. // the result type of the load.
tag instanceof LoadOperandTag and tag instanceof LoadOperandTag and
@@ -249,34 +238,31 @@ private module Cached {
result = result =
getInstructionTranslatedElement(instruction) getInstructionTranslatedElement(instruction)
.getInstructionMemoryOperandType(getInstructionTag(instruction), tag) .getInstructionMemoryOperandType(getInstructionTag(instruction), tag)
} }
cached Instruction getPhiOperandDefinition(
Instruction getPhiOperandDefinition(
PhiInstruction instruction, IRBlock predecessorBlock, Overlap overlap PhiInstruction instruction, IRBlock predecessorBlock, Overlap overlap
) { ) {
none() none()
} }
cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) { none() }
Instruction getPhiInstructionBlockStart(PhiInstruction instr) { none() }
cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
result = result =
getInstructionTranslatedElement(instruction) getInstructionTranslatedElement(instruction)
.getInstructionSuccessor(getInstructionTag(instruction), kind) .getInstructionSuccessor(getInstructionTag(instruction), kind)
} }
/** /**
* Holds if the CFG edge (`sourceElement`, `sourceTag`) ---`kind`--> * Holds if the CFG edge (`sourceElement`, `sourceTag`) ---`kind`-->
* `targetInstruction` is a back edge under the condition that * `targetInstruction` is a back edge under the condition that
* `requiredAncestor` is an ancestor of `sourceElement`. * `requiredAncestor` is an ancestor of `sourceElement`.
*/ */
private predicate backEdgeCandidate( private predicate backEdgeCandidate(
TranslatedElement sourceElement, InstructionTag sourceTag, TranslatedElement requiredAncestor, TranslatedElement sourceElement, InstructionTag sourceTag, TranslatedElement requiredAncestor,
Instruction targetInstruction, EdgeKind kind Instruction targetInstruction, EdgeKind kind
) { ) {
// While loop: // While loop:
// Any edge from within the body of the loop to the condition of the loop // Any edge from within the body of the loop to the condition of the loop
// is a back edge. This includes edges from `continue` and the fall-through // is a back edge. This includes edges from `continue` and the fall-through
@@ -323,18 +309,17 @@ private module Cached {
targetInstruction = sourceElement.getInstructionSuccessor(sourceTag, kind) and targetInstruction = sourceElement.getInstructionSuccessor(sourceTag, kind) and
requiredAncestor = s.getUpdate() requiredAncestor = s.getUpdate()
) )
} }
private predicate jumpSourceHasAncestor(TranslatedElement jumpSource, TranslatedElement ancestor) { private predicate jumpSourceHasAncestor(TranslatedElement jumpSource, TranslatedElement ancestor) {
backEdgeCandidate(jumpSource, _, _, _, _) and backEdgeCandidate(jumpSource, _, _, _, _) and
ancestor = jumpSource ancestor = jumpSource
or or
// For performance, we don't want a fastTC here // For performance, we don't want a fastTC here
jumpSourceHasAncestor(jumpSource, ancestor.getAChild()) jumpSourceHasAncestor(jumpSource, ancestor.getAChild())
} }
cached Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind kind) {
Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind kind) {
exists( exists(
TranslatedElement sourceElement, InstructionTag sourceTag, TranslatedElement requiredAncestor TranslatedElement sourceElement, InstructionTag sourceTag, TranslatedElement requiredAncestor
| |
@@ -357,46 +342,40 @@ private module Cached {
instruction = s.getInstruction(tag) instruction = s.getInstruction(tag)
) )
) )
} }
/** Holds if `goto` jumps strictly forward in the program text. */ /** Holds if `goto` jumps strictly forward in the program text. */
private predicate isStrictlyForwardGoto(GotoStmt goto) { private predicate isStrictlyForwardGoto(GotoStmt goto) {
goto.getLocation().isBefore(goto.getTarget().getLocation()) goto.getLocation().isBefore(goto.getTarget().getLocation())
} }
cached Locatable getInstructionAST(TStageInstruction instr) {
Locatable getInstructionAST(TStageInstruction instr) {
result = getInstructionTranslatedElement(instr).getAST() result = getInstructionTranslatedElement(instr).getAST()
} }
cached CppType getInstructionResultType(TStageInstruction instr) {
CppType getInstructionResultType(TStageInstruction instr) {
exists(TranslatedElement element, InstructionTag tag | exists(TranslatedElement element, InstructionTag tag |
instructionOrigin(instr, element, tag) and instructionOrigin(instr, element, tag) and
element.hasInstruction(_, tag, result) element.hasInstruction(_, tag, result)
) )
} }
cached Opcode getInstructionOpcode(TStageInstruction instr) {
Opcode getInstructionOpcode(TStageInstruction instr) {
exists(TranslatedElement element, InstructionTag tag | exists(TranslatedElement element, InstructionTag tag |
instructionOrigin(instr, element, tag) and instructionOrigin(instr, element, tag) and
element.hasInstruction(result, tag, _) element.hasInstruction(result, tag, _)
) )
} }
cached IRFunctionBase getInstructionEnclosingIRFunction(TStageInstruction instr) {
IRFunctionBase getInstructionEnclosingIRFunction(TStageInstruction instr) {
result.getFunction() = getInstructionTranslatedElement(instr).getFunction() result.getFunction() = getInstructionTranslatedElement(instr).getFunction()
} }
cached Instruction getPrimaryInstructionForSideEffect(SideEffectInstruction instruction) {
Instruction getPrimaryInstructionForSideEffect(SideEffectInstruction instruction) {
exists(TranslatedElement element, InstructionTag tag | exists(TranslatedElement element, InstructionTag tag |
instructionOrigin(instruction, element, tag) and instructionOrigin(instruction, element, tag) and
result = element.getPrimaryInstructionForSideEffect(tag) result = element.getPrimaryInstructionForSideEffect(tag)
) )
}
} }
import CachedForDebugging import CachedForDebugging