diff options
author | Artem Dergachev <artem.dergachev@gmail.com> | 2019-04-30 03:01:02 +0000 |
---|---|---|
committer | Artem Dergachev <artem.dergachev@gmail.com> | 2019-04-30 03:01:02 +0000 |
commit | c208eda5d902a10fcbc85024a06a60f72fbed767 (patch) | |
tree | b07ebad2889f75d147d3c47c6b888e71e61a8023 /include | |
parent | 4ecb1e1c614b63724545e32904ca321e148e629c (diff) |
[analyzer] Treat functions without run-time branches as "small".
Currently we always inline functions that have no branches, i.e. have exactly
three CFG blocks: ENTRY, some code, EXIT. This makes sense because when there
are no branches, it means that there's no exponential complexity introduced
by inlining such function. Such functions also don't trigger various fundamental
problems with our inlining mechanism, such as the problem of inlined
defensive checks.
Sometimes the CFG may contain more blocks, but in practice it still has
linear structure because all directions (except, at most, one) of all branches
turned out to be unreachable. When this happens, still treat the function
as "small". This is useful, in particular, for dealing with C++17 if constexpr.
Differential Revision: https://reviews.llvm.org/D61051
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@359531 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r-- | include/clang/Analysis/CFG.h | 6 | ||||
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h | 19 |
2 files changed, 25 insertions, 0 deletions
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index dc83a99e66..5722cbee86 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -1172,6 +1172,12 @@ public: /// implementation needs such an interface. unsigned size() const { return NumBlockIDs; } + /// Returns true if the CFG has no branches. Usually it boils down to the CFG + /// having exactly three blocks (entry, the actual code, exit), but sometimes + /// more blocks appear due to having control flow that can be fully + /// resolved in compile time. + bool isLinear() const; + //===--------------------------------------------------------------------===// // CFG Debugging: Pretty-Printing and Visualization. //===--------------------------------------------------------------------===// diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 185774b586..f0b01f182b 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -718,6 +718,25 @@ private: AnalyzerOptions &Opts, const EvalCallOptions &CallOpts); + /// See if the given AnalysisDeclContext is built for a function that we + /// should always inline simply because it's small enough. + /// Apart from "small" functions, we also have "large" functions + /// (cf. isLarge()), some of which are huge (cf. isHuge()), and we classify + /// the remaining functions as "medium". + bool isSmall(AnalysisDeclContext *ADC) const; + + /// See if the given AnalysisDeclContext is built for a function that we + /// should inline carefully because it looks pretty large. + bool isLarge(AnalysisDeclContext *ADC) const; + + /// See if the given AnalysisDeclContext is built for a function that we + /// should never inline because it's legit gigantic. + bool isHuge(AnalysisDeclContext *ADC) const; + + /// See if the given AnalysisDeclContext is built for a function that we + /// should inline, just by looking at the declaration of the function. + bool mayInlineDecl(AnalysisDeclContext *ADC) const; + /// Checks our policies and decides weither the given call should be inlined. bool shouldInlineCall(const CallEvent &Call, const Decl *D, const ExplodedNode *Pred, |