From: Giuseppe Ottaviano Date: Tue, 8 Sep 2015 19:20:36 +0000 (-0700) Subject: Implement assume() X-Git-Tag: deprecate-dynamic-initializer~434 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=b6a637141cf0d28ccdda5a9eccbe57ba5f367c67;p=folly.git Implement assume() Summary: In some cases hinting the compiler about conditions that are guaranteed to be true can help it generate better code. For instance, remove unnecessary bound checks. Clang has `__builtin_assume` and on GCC we can simulate it with `__builtin_unreachable`, so better just abstract both into a function. Reviewed By: @philippv Differential Revision: D2419937 --- diff --git a/folly/Assume.h b/folly/Assume.h new file mode 100644 index 00000000..1da9bb0d --- /dev/null +++ b/folly/Assume.h @@ -0,0 +1,49 @@ +/* + * Copyright 2015 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOLLY_BASE_ASSUME_H_ +#define FOLLY_BASE_ASSUME_H_ + +#include +#include + +namespace folly { + +/** + * Inform the compiler that the argument can be assumed true. It is + * undefined behavior if the argument is not actually true, so use + * with care. + * + * Implemented as a function instead of a macro because + * __builtin_assume does not evaluate its argument at runtime, so it + * cannot be used with expressions that have side-effects. + */ + +FOLLY_ALWAYS_INLINE void assume(bool cond) { +#ifndef NDEBUG + DCHECK(cond); +#elif defined(__clang__) // Must go first because Clang also defines __GNUC__. + __builtin_assume(cond); +#elif defined(__GNUC__) + if (!cond) { __builtin_unreachable(); } +#else + // Do nothing. +#endif +} + +} // namespace folly + +#endif diff --git a/folly/Makefile.am b/folly/Makefile.am index b7f69dc6..49c22ef6 100644 --- a/folly/Makefile.am +++ b/folly/Makefile.am @@ -21,6 +21,7 @@ nobase_follyinclude_HEADERS = \ ApplyTuple.h \ Arena.h \ Arena-inl.h \ + Assume.h \ AtomicBitSet.h \ AtomicHashArray.h \ AtomicHashArray-inl.h \ diff --git a/folly/Portability.h b/folly/Portability.h index 77baf95a..b990b302 100644 --- a/folly/Portability.h +++ b/folly/Portability.h @@ -116,7 +116,7 @@ #elif defined(__clang__) || defined(__GNUC__) # define FOLLY_ALWAYS_INLINE inline __attribute__((__always_inline__)) #else -# define FOLLY_ALWAYS_INLINE +# define FOLLY_ALWAYS_INLINE inline #endif // detection for 64 bit