-
Notifications
You must be signed in to change notification settings - Fork 1.6k
reduced size of ValueFlow::Value
#6784
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f232413
057f766
4a9c54c
26a474a
22315df
2133354
1077ad2
ed47405
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,6 +33,8 @@ | |
| #include <type_traits> | ||
| #include <vector> | ||
|
|
||
| FORCE_WARNING_CLANG_PUSH("-Wpadded") | ||
|
|
||
| class Token; | ||
|
|
||
| namespace ValueFlow | ||
|
|
@@ -43,6 +45,10 @@ namespace ValueFlow | |
|
|
||
| explicit Value(long long val = 0, Bound b = Bound::Point) : | ||
| bound(b), | ||
| safe(false), | ||
| conditional(false), | ||
| macro(false), | ||
| defaultArg(false), | ||
| intvalue(val), | ||
| varvalue(val), | ||
| wideintvalue(val) | ||
|
|
@@ -262,6 +268,53 @@ namespace ValueFlow | |
| /** The value bound */ | ||
| Bound bound = Bound::Point; | ||
|
|
||
| /** value relies on safe checking */ | ||
| // cppcheck-suppress premium-misra-cpp-2023-12.2.1 | ||
| bool safe : 1; | ||
|
|
||
| /** Conditional value */ | ||
| bool conditional : 1; | ||
|
|
||
| /** Value is is from an expanded macro */ | ||
| bool macro : 1; | ||
|
|
||
| /** Is this value passed as default parameter to the function? */ | ||
| bool defaultArg : 1; | ||
|
|
||
| long long : 4; // padding | ||
|
|
||
| /** kind of moved */ | ||
| enum class MoveKind : std::uint8_t { NonMovedVariable, MovedVariable, ForwardedVariable } moveKind = MoveKind::NonMovedVariable; | ||
|
|
||
| enum class LifetimeScope : std::uint8_t { Local, Argument, SubFunction, ThisPointer, ThisValue } lifetimeScope = LifetimeScope::Local; | ||
|
|
||
| enum class LifetimeKind : std::uint8_t { | ||
| // Pointer points to a member of lifetime | ||
| Object, | ||
| // A member of object points to the lifetime | ||
| SubObject, | ||
| // Lambda has captured lifetime(similar to SubObject) | ||
| Lambda, | ||
| // Iterator points to the lifetime of a container(similar to Object) | ||
| Iterator, | ||
| // A pointer that holds the address of the lifetime | ||
| Address | ||
| } lifetimeKind = LifetimeKind::Object; | ||
|
|
||
| /** How known is this value */ | ||
| enum class ValueKind : std::uint8_t { | ||
| /** This value is possible, other unlisted values may also be possible */ | ||
| Possible, | ||
| /** Only listed values are possible */ | ||
| Known, | ||
| /** Inconclusive */ | ||
| Inconclusive, | ||
| /** Listed values are impossible */ | ||
| Impossible | ||
| } valueKind = ValueKind::Possible; | ||
|
|
||
| std::int8_t indirect{}; // TODO: can we reduce the size? | ||
|
|
||
| /** int value (or sometimes bool value?) */ | ||
| long long intvalue{}; | ||
|
|
||
|
|
@@ -279,35 +332,20 @@ namespace ValueFlow | |
|
|
||
| ErrorPath errorPath; | ||
|
|
||
| ErrorPath debugPath; | ||
| ErrorPath debugPath; // TODO: make lighter by default | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is only used when I did hack this out locally and it saves about 3% IR and several operations no longer show up at all in profiling it appears we just narrowly exceed some threshold for some compiler optimization(s) or allocation pattern.
This comment was marked as outdated.
Sorry, something went wrong. |
||
|
|
||
| /** For calculated values - varId that calculated value depends on */ | ||
| nonneg int varId{}; | ||
|
|
||
| enum class UnknownFunctionReturn : uint8_t { | ||
| enum class UnknownFunctionReturn : std::uint8_t { | ||
| no, // not unknown function return | ||
| outOfMemory, // out of memory | ||
| outOfResources, // out of resource | ||
| other // other | ||
| }; | ||
| UnknownFunctionReturn unknownFunctionReturn{UnknownFunctionReturn::no}; | ||
|
|
||
| /** value relies on safe checking */ | ||
| bool safe{}; | ||
|
|
||
| /** Conditional value */ | ||
| bool conditional{}; | ||
|
|
||
| /** Value is is from an expanded macro */ | ||
| bool macro{}; | ||
|
|
||
| /** Is this value passed as default parameter to the function? */ | ||
| bool defaultArg{}; | ||
|
|
||
| int8_t indirect{}; | ||
|
|
||
| /** kind of moved */ | ||
| enum class MoveKind : std::uint8_t { NonMovedVariable, MovedVariable, ForwardedVariable } moveKind = MoveKind::NonMovedVariable; | ||
| long long : 24; // padding | ||
|
|
||
| /** Path id */ | ||
| MathLib::bigint path{}; | ||
|
|
@@ -320,38 +358,11 @@ namespace ValueFlow | |
| // Set to where a lifetime is captured by value | ||
| const Token* capturetok{}; | ||
|
|
||
| enum class LifetimeKind : std::uint8_t { | ||
| // Pointer points to a member of lifetime | ||
| Object, | ||
| // A member of object points to the lifetime | ||
| SubObject, | ||
| // Lambda has captured lifetime(similar to SubObject) | ||
| Lambda, | ||
| // Iterator points to the lifetime of a container(similar to Object) | ||
| Iterator, | ||
| // A pointer that holds the address of the lifetime | ||
| Address | ||
| } lifetimeKind = LifetimeKind::Object; | ||
|
|
||
| enum class LifetimeScope : std::uint8_t { Local, Argument, SubFunction, ThisPointer, ThisValue } lifetimeScope = LifetimeScope::Local; | ||
|
|
||
| RET_NONNULL static const char* toString(MoveKind moveKind); | ||
| RET_NONNULL static const char* toString(LifetimeKind lifetimeKind); | ||
| RET_NONNULL static const char* toString(LifetimeScope lifetimeScope); | ||
| RET_NONNULL static const char* toString(Bound bound); | ||
|
|
||
| /** How known is this value */ | ||
| enum class ValueKind : std::uint8_t { | ||
| /** This value is possible, other unlisted values may also be possible */ | ||
| Possible, | ||
| /** Only listed values are possible */ | ||
| Known, | ||
| /** Inconclusive */ | ||
| Inconclusive, | ||
| /** Listed values are impossible */ | ||
| Impossible | ||
| } valueKind = ValueKind::Possible; | ||
|
|
||
| void setKnown() { | ||
| valueKind = ValueKind::Known; | ||
| } | ||
|
|
@@ -419,4 +430,6 @@ namespace ValueFlow | |
| }; | ||
| } | ||
|
|
||
| FORCE_WARNING_CLANG_POP | ||
|
|
||
| #endif // vfvalueH | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An old wisdom is that it is a good idea to order members by size.
See i.e.: http://katecpp.github.io/struct-members-order/
I have seen good results in a embedded project.
I guess it's pretty platform-dependent and would make no difference on some platforms.
would it be a good idea to use "pragma packed" on this struct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. I have not done much in this memory so far because there were always still bigger issues in the projects I worked on.
Given the low amount of explicit padding we have to apply (and my limited understanding of
packed) that might not be necessary. I also think that might come only into play is when you really want to optimize for cachelines (which I have no experience working with) and I assume this will always be out-of-scope for this application.