From c79ec8c37a4bc6e15ff677e0da8c07f935a7eef5 Mon Sep 17 00:00:00 2001 From: Alex Eyers-Taylor Date: Thu, 5 Oct 2023 16:32:29 +0100 Subject: [PATCH] CPP: Improve performance of IR debugging --- .../ir/implementation/aliased_ssa/IRBlock.qll | 35 +++++++++++++------ .../aliased_ssa/Instruction.qll | 16 ++++----- .../cpp/ir/implementation/raw/IRBlock.qll | 35 +++++++++++++------ .../cpp/ir/implementation/raw/Instruction.qll | 16 ++++----- .../raw/internal/IRConstruction.qll | 7 +++- .../implementation/unaliased_ssa/IRBlock.qll | 35 +++++++++++++------ .../unaliased_ssa/Instruction.qll | 16 ++++----- .../ir/implementation/raw/IRBlock.qll | 35 +++++++++++++------ .../ir/implementation/raw/Instruction.qll | 16 ++++----- .../implementation/unaliased_ssa/IRBlock.qll | 35 +++++++++++++------ .../unaliased_ssa/Instruction.qll | 16 ++++----- 11 files changed, 166 insertions(+), 96 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll index 78008a6c69b..50395db47e7 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll @@ -8,6 +8,22 @@ private import internal.IRBlockImports as Imports import Imports::EdgeKind private import Cached +/** + * Holds if `block` is a block in `func` and `sortOverride`, `sortKey1`, and `sortKey2` are the + * sort keys of the block (derived from its first instruction) + */ +pragma[nomagic] +private predicate blockSortKeys( + IRFunction func, IRBlockBase block, int sortOverride, int sortKey1, int sortKey2 +) { + block.getEnclosingIRFunction() = func and + block.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and + // Ensure that the block containing `EnterFunction` always comes first. + if block.getFirstInstruction() instanceof EnterFunctionInstruction + then sortOverride = 0 + else sortOverride = 1 +} + /** * A basic block in the IR. A basic block consists of a sequence of `Instructions` with the only * incoming edges at the beginning of the sequence and the only outgoing edges at the end of the @@ -37,17 +53,14 @@ class IRBlockBase extends TIRBlock { exists(IRConfiguration::IRConfiguration config | config.shouldEvaluateDebugStringsForFunction(this.getEnclosingFunction()) ) and - this = - rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | - funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and - funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and - // Ensure that the block containing `EnterFunction` always comes first. - if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction - then sortOverride = 0 - else sortOverride = 1 - | - funcBlock order by sortOverride, sortKey1, sortKey2 - ) + exists(IRFunction func | + this = + rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | + blockSortKeys(func, funcBlock, sortOverride, sortKey1, sortKey2) + | + funcBlock order by sortOverride, sortKey1, sortKey2 + ) + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index 2a3a6d3407a..bf07e73d5fe 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -116,14 +116,14 @@ class Instruction extends Construction::TStageInstruction { private int getLineRank() { this.shouldGenerateDumpStrings() and - this = - rank[result](Instruction instr | - instr = - getAnInstructionAtLine(this.getEnclosingIRFunction(), this.getLocation().getFile(), - this.getLocation().getStartLine()) - | - instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() - ) + exists(IRFunction enclosing, Language::File file, int line | + this = + rank[result](Instruction instr | + instr = getAnInstructionAtLine(enclosing, file, line) + | + instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() + ) + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRBlock.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRBlock.qll index 78008a6c69b..50395db47e7 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRBlock.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRBlock.qll @@ -8,6 +8,22 @@ private import internal.IRBlockImports as Imports import Imports::EdgeKind private import Cached +/** + * Holds if `block` is a block in `func` and `sortOverride`, `sortKey1`, and `sortKey2` are the + * sort keys of the block (derived from its first instruction) + */ +pragma[nomagic] +private predicate blockSortKeys( + IRFunction func, IRBlockBase block, int sortOverride, int sortKey1, int sortKey2 +) { + block.getEnclosingIRFunction() = func and + block.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and + // Ensure that the block containing `EnterFunction` always comes first. + if block.getFirstInstruction() instanceof EnterFunctionInstruction + then sortOverride = 0 + else sortOverride = 1 +} + /** * A basic block in the IR. A basic block consists of a sequence of `Instructions` with the only * incoming edges at the beginning of the sequence and the only outgoing edges at the end of the @@ -37,17 +53,14 @@ class IRBlockBase extends TIRBlock { exists(IRConfiguration::IRConfiguration config | config.shouldEvaluateDebugStringsForFunction(this.getEnclosingFunction()) ) and - this = - rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | - funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and - funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and - // Ensure that the block containing `EnterFunction` always comes first. - if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction - then sortOverride = 0 - else sortOverride = 1 - | - funcBlock order by sortOverride, sortKey1, sortKey2 - ) + exists(IRFunction func | + this = + rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | + blockSortKeys(func, funcBlock, sortOverride, sortKey1, sortKey2) + | + funcBlock order by sortOverride, sortKey1, sortKey2 + ) + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll index 2a3a6d3407a..bf07e73d5fe 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -116,14 +116,14 @@ class Instruction extends Construction::TStageInstruction { private int getLineRank() { this.shouldGenerateDumpStrings() and - this = - rank[result](Instruction instr | - instr = - getAnInstructionAtLine(this.getEnclosingIRFunction(), this.getLocation().getFile(), - this.getLocation().getStartLine()) - | - instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() - ) + exists(IRFunction enclosing, Language::File file, int line | + this = + rank[result](Instruction instr | + instr = getAnInstructionAtLine(enclosing, file, line) + | + instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() + ) + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll index ed4b39bc24b..005eaeb7d1a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll @@ -423,7 +423,12 @@ private module CachedForDebugging { cached predicate instructionHasSortKeys(Instruction instruction, int key1, int key2) { key1 = getInstructionTranslatedElement(instruction).getId() and - getInstructionTag(instruction) = + getInstructionTag(instruction) = tagByRank(key2) + } + + pragma[nomagic] + private InstructionTag tagByRank(int key2) { + result = rank[key2](InstructionTag tag, string tagId | tagId = getInstructionTagId(tag) | diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll index 78008a6c69b..50395db47e7 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll @@ -8,6 +8,22 @@ private import internal.IRBlockImports as Imports import Imports::EdgeKind private import Cached +/** + * Holds if `block` is a block in `func` and `sortOverride`, `sortKey1`, and `sortKey2` are the + * sort keys of the block (derived from its first instruction) + */ +pragma[nomagic] +private predicate blockSortKeys( + IRFunction func, IRBlockBase block, int sortOverride, int sortKey1, int sortKey2 +) { + block.getEnclosingIRFunction() = func and + block.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and + // Ensure that the block containing `EnterFunction` always comes first. + if block.getFirstInstruction() instanceof EnterFunctionInstruction + then sortOverride = 0 + else sortOverride = 1 +} + /** * A basic block in the IR. A basic block consists of a sequence of `Instructions` with the only * incoming edges at the beginning of the sequence and the only outgoing edges at the end of the @@ -37,17 +53,14 @@ class IRBlockBase extends TIRBlock { exists(IRConfiguration::IRConfiguration config | config.shouldEvaluateDebugStringsForFunction(this.getEnclosingFunction()) ) and - this = - rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | - funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and - funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and - // Ensure that the block containing `EnterFunction` always comes first. - if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction - then sortOverride = 0 - else sortOverride = 1 - | - funcBlock order by sortOverride, sortKey1, sortKey2 - ) + exists(IRFunction func | + this = + rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | + blockSortKeys(func, funcBlock, sortOverride, sortKey1, sortKey2) + | + funcBlock order by sortOverride, sortKey1, sortKey2 + ) + ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index 2a3a6d3407a..bf07e73d5fe 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -116,14 +116,14 @@ class Instruction extends Construction::TStageInstruction { private int getLineRank() { this.shouldGenerateDumpStrings() and - this = - rank[result](Instruction instr | - instr = - getAnInstructionAtLine(this.getEnclosingIRFunction(), this.getLocation().getFile(), - this.getLocation().getStartLine()) - | - instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() - ) + exists(IRFunction enclosing, Language::File file, int line | + this = + rank[result](Instruction instr | + instr = getAnInstructionAtLine(enclosing, file, line) + | + instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() + ) + ) } /** diff --git a/csharp/ql/src/experimental/ir/implementation/raw/IRBlock.qll b/csharp/ql/src/experimental/ir/implementation/raw/IRBlock.qll index 78008a6c69b..50395db47e7 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/IRBlock.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/IRBlock.qll @@ -8,6 +8,22 @@ private import internal.IRBlockImports as Imports import Imports::EdgeKind private import Cached +/** + * Holds if `block` is a block in `func` and `sortOverride`, `sortKey1`, and `sortKey2` are the + * sort keys of the block (derived from its first instruction) + */ +pragma[nomagic] +private predicate blockSortKeys( + IRFunction func, IRBlockBase block, int sortOverride, int sortKey1, int sortKey2 +) { + block.getEnclosingIRFunction() = func and + block.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and + // Ensure that the block containing `EnterFunction` always comes first. + if block.getFirstInstruction() instanceof EnterFunctionInstruction + then sortOverride = 0 + else sortOverride = 1 +} + /** * A basic block in the IR. A basic block consists of a sequence of `Instructions` with the only * incoming edges at the beginning of the sequence and the only outgoing edges at the end of the @@ -37,17 +53,14 @@ class IRBlockBase extends TIRBlock { exists(IRConfiguration::IRConfiguration config | config.shouldEvaluateDebugStringsForFunction(this.getEnclosingFunction()) ) and - this = - rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | - funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and - funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and - // Ensure that the block containing `EnterFunction` always comes first. - if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction - then sortOverride = 0 - else sortOverride = 1 - | - funcBlock order by sortOverride, sortKey1, sortKey2 - ) + exists(IRFunction func | + this = + rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | + blockSortKeys(func, funcBlock, sortOverride, sortKey1, sortKey2) + | + funcBlock order by sortOverride, sortKey1, sortKey2 + ) + ) } /** diff --git a/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll b/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll index 2a3a6d3407a..bf07e73d5fe 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll @@ -116,14 +116,14 @@ class Instruction extends Construction::TStageInstruction { private int getLineRank() { this.shouldGenerateDumpStrings() and - this = - rank[result](Instruction instr | - instr = - getAnInstructionAtLine(this.getEnclosingIRFunction(), this.getLocation().getFile(), - this.getLocation().getStartLine()) - | - instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() - ) + exists(IRFunction enclosing, Language::File file, int line | + this = + rank[result](Instruction instr | + instr = getAnInstructionAtLine(enclosing, file, line) + | + instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() + ) + ) } /** diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRBlock.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRBlock.qll index 78008a6c69b..50395db47e7 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRBlock.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRBlock.qll @@ -8,6 +8,22 @@ private import internal.IRBlockImports as Imports import Imports::EdgeKind private import Cached +/** + * Holds if `block` is a block in `func` and `sortOverride`, `sortKey1`, and `sortKey2` are the + * sort keys of the block (derived from its first instruction) + */ +pragma[nomagic] +private predicate blockSortKeys( + IRFunction func, IRBlockBase block, int sortOverride, int sortKey1, int sortKey2 +) { + block.getEnclosingIRFunction() = func and + block.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and + // Ensure that the block containing `EnterFunction` always comes first. + if block.getFirstInstruction() instanceof EnterFunctionInstruction + then sortOverride = 0 + else sortOverride = 1 +} + /** * A basic block in the IR. A basic block consists of a sequence of `Instructions` with the only * incoming edges at the beginning of the sequence and the only outgoing edges at the end of the @@ -37,17 +53,14 @@ class IRBlockBase extends TIRBlock { exists(IRConfiguration::IRConfiguration config | config.shouldEvaluateDebugStringsForFunction(this.getEnclosingFunction()) ) and - this = - rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | - funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and - funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and - // Ensure that the block containing `EnterFunction` always comes first. - if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction - then sortOverride = 0 - else sortOverride = 1 - | - funcBlock order by sortOverride, sortKey1, sortKey2 - ) + exists(IRFunction func | + this = + rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 | + blockSortKeys(func, funcBlock, sortOverride, sortKey1, sortKey2) + | + funcBlock order by sortOverride, sortKey1, sortKey2 + ) + ) } /** diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll index 2a3a6d3407a..bf07e73d5fe 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll @@ -116,14 +116,14 @@ class Instruction extends Construction::TStageInstruction { private int getLineRank() { this.shouldGenerateDumpStrings() and - this = - rank[result](Instruction instr | - instr = - getAnInstructionAtLine(this.getEnclosingIRFunction(), this.getLocation().getFile(), - this.getLocation().getStartLine()) - | - instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() - ) + exists(IRFunction enclosing, Language::File file, int line | + this = + rank[result](Instruction instr | + instr = getAnInstructionAtLine(enclosing, file, line) + | + instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() + ) + ) } /**