From ad3fe1dd9d62659880c7d563cde21bde7e3e2326 Mon Sep 17 00:00:00 2001 From: Phil Willoughby Date: Mon, 6 Nov 2017 09:06:27 -0800 Subject: [PATCH] Mark constructing an Unexpected as cold Summary: By marking the main constructors of `Unexpected` cold we are telling the compiler that we don't expect to execute them often. This can improve the locality and performance of the `Expected` branch, and reduce the code-size for the `Unexpected` branch. The constructors we have marked cold here are only the ones used to originate an `Unexpected`. We don't mark the copy- move- or conversion-constructors as `cold` because they will typically be used in error-handling branches and it is not correct to say that they are colder than their surroundings in that case. Note that the entire error-handling branch is likely to be deduced to be cold because we told the compiler that it is likely that hasValue() is true and hasError() is false. Because `makeUnexpected` unconditionally invokes one of these cold constructors it will inherit the property of being cold. The GCC function attribute reference, which describes what `cold` means, is here: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes Reviewed By: yfeldblum Differential Revision: D6234305 fbshipit-source-id: 6876073e92ce54936ba7152175d76be653f5f463 --- folly/CppAttributes.h | 12 ++++++++++++ folly/Expected.h | 7 +++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/folly/CppAttributes.h b/folly/CppAttributes.h index 7a13f615..466aab91 100644 --- a/folly/CppAttributes.h +++ b/folly/CppAttributes.h @@ -103,3 +103,15 @@ #define FOLLY_NULLABLE #define FOLLY_NONNULL #endif + +/** + * "Cold" indicates to the compiler that a function is only expected to be + * called from unlikely code paths. It can affect decisions made by the + * optimizer both when processing the function body and when analyzing + * call-sites. + */ +#if __GNUC__ +#define FOLLY_COLD __attribute__((__cold__)) +#else +#define FOLLY_COLD +#endif diff --git a/folly/Expected.h b/folly/Expected.h index f15010df..2705f335 100644 --- a/folly/Expected.h +++ b/folly/Expected.h @@ -31,6 +31,7 @@ #include +#include #include #include #include @@ -711,8 +712,10 @@ class Unexpected final { Unexpected(Unexpected&&) = default; Unexpected& operator=(const Unexpected&) = default; Unexpected& operator=(Unexpected&&) = default; - constexpr /* implicit */ Unexpected(const Error& err) : error_(err) {} - constexpr /* implicit */ Unexpected(Error&& err) : error_(std::move(err)) {} + FOLLY_COLD constexpr /* implicit */ Unexpected(const Error& err) + : error_(err) {} + FOLLY_COLD constexpr /* implicit */ Unexpected(Error&& err) + : error_(std::move(err)) {} template ::value)> -- 2.34.1