From 6ee3def942191a1d58befc28f0141a0780d9df95 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 10 Aug 2018 12:03:43 +0200 Subject: [PATCH] C++ IR: Speed up getInstructionOperand The `SSAConstruction::Cached::getInstructionOperand` predicate took 1m27s on a postgres snapshot before this change and was the slowest predicate in SSAIR. It now takes 4.5s. The slowdown was caused by its use of `getUnmodeledDefinitionInstruction`, which got inlined into a place where join orderer had little choice but to join the `MkInstruction` relation with itself, creating a large intermediate relation. I've added `pragma[noinline]` to `getUnmodeledDefinitionInstruction` and also to similar predicates that are likely to cause the same problem in the future. --- cpp/ql/src/semmle/code/cpp/ir/internal/FunctionIR.qll | 6 ++++++ .../semmle/code/cpp/ssa/internal/aliased_ssa/FunctionIR.qll | 6 ++++++ cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/FunctionIR.qll | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/FunctionIR.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/FunctionIR.qll index ba8f524f202..4568ae7ceb2 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/FunctionIR.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/FunctionIR.qll @@ -38,6 +38,7 @@ class FunctionIR extends TFunctionIR { /** * Gets the entry point for this function. */ + pragma[noinline] final EnterFunctionInstruction getEnterFunctionInstruction() { result.getFunctionIR() = this } @@ -45,10 +46,12 @@ class FunctionIR extends TFunctionIR { /** * Gets the exit point for this function. */ + pragma[noinline] final ExitFunctionInstruction getExitFunctionInstruction() { result.getFunctionIR() = this } + pragma[noinline] final UnmodeledDefinitionInstruction getUnmodeledDefinitionInstruction() { result.getFunctionIR() = this } @@ -56,6 +59,7 @@ class FunctionIR extends TFunctionIR { /** * Gets the single return instruction for this function. */ + pragma[noinline] final ReturnInstruction getReturnInstruction() { result.getFunctionIR() = this } @@ -64,6 +68,7 @@ class FunctionIR extends TFunctionIR { * Gets the variable used to hold the return value of this function. If this * function does not return a value, this predicate does not hold. */ + pragma[noinline] final IRReturnVariable getReturnVariable() { result.getFunctionIR() = this } @@ -71,6 +76,7 @@ class FunctionIR extends TFunctionIR { /** * Gets the block containing the entry point of this function. */ + pragma[noinline] final IRBlock getEntryBlock() { result.getFirstInstruction() = getEnterFunctionInstruction() } diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/FunctionIR.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/FunctionIR.qll index ba8f524f202..4568ae7ceb2 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/FunctionIR.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/FunctionIR.qll @@ -38,6 +38,7 @@ class FunctionIR extends TFunctionIR { /** * Gets the entry point for this function. */ + pragma[noinline] final EnterFunctionInstruction getEnterFunctionInstruction() { result.getFunctionIR() = this } @@ -45,10 +46,12 @@ class FunctionIR extends TFunctionIR { /** * Gets the exit point for this function. */ + pragma[noinline] final ExitFunctionInstruction getExitFunctionInstruction() { result.getFunctionIR() = this } + pragma[noinline] final UnmodeledDefinitionInstruction getUnmodeledDefinitionInstruction() { result.getFunctionIR() = this } @@ -56,6 +59,7 @@ class FunctionIR extends TFunctionIR { /** * Gets the single return instruction for this function. */ + pragma[noinline] final ReturnInstruction getReturnInstruction() { result.getFunctionIR() = this } @@ -64,6 +68,7 @@ class FunctionIR extends TFunctionIR { * Gets the variable used to hold the return value of this function. If this * function does not return a value, this predicate does not hold. */ + pragma[noinline] final IRReturnVariable getReturnVariable() { result.getFunctionIR() = this } @@ -71,6 +76,7 @@ class FunctionIR extends TFunctionIR { /** * Gets the block containing the entry point of this function. */ + pragma[noinline] final IRBlock getEntryBlock() { result.getFirstInstruction() = getEnterFunctionInstruction() } diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/FunctionIR.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/FunctionIR.qll index ba8f524f202..4568ae7ceb2 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/FunctionIR.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/FunctionIR.qll @@ -38,6 +38,7 @@ class FunctionIR extends TFunctionIR { /** * Gets the entry point for this function. */ + pragma[noinline] final EnterFunctionInstruction getEnterFunctionInstruction() { result.getFunctionIR() = this } @@ -45,10 +46,12 @@ class FunctionIR extends TFunctionIR { /** * Gets the exit point for this function. */ + pragma[noinline] final ExitFunctionInstruction getExitFunctionInstruction() { result.getFunctionIR() = this } + pragma[noinline] final UnmodeledDefinitionInstruction getUnmodeledDefinitionInstruction() { result.getFunctionIR() = this } @@ -56,6 +59,7 @@ class FunctionIR extends TFunctionIR { /** * Gets the single return instruction for this function. */ + pragma[noinline] final ReturnInstruction getReturnInstruction() { result.getFunctionIR() = this } @@ -64,6 +68,7 @@ class FunctionIR extends TFunctionIR { * Gets the variable used to hold the return value of this function. If this * function does not return a value, this predicate does not hold. */ + pragma[noinline] final IRReturnVariable getReturnVariable() { result.getFunctionIR() = this } @@ -71,6 +76,7 @@ class FunctionIR extends TFunctionIR { /** * Gets the block containing the entry point of this function. */ + pragma[noinline] final IRBlock getEntryBlock() { result.getFirstInstruction() = getEnterFunctionInstruction() }