Skip to content

Commit

Permalink
help compiler folding for divideFloor/moduloFloor (#4512)
Browse files Browse the repository at this point in the history
Add additional test to assist compiler folding to perform these
replacements when the divisor is a power-of-two compile-time constant:
 - divideFloor -> right-shift
 - moduloFloor -> bitwise and

---------

Co-authored-by: Anton Korobeynikov <[email protected]>
  • Loading branch information
grg and asl authored Mar 12, 2024
1 parent ba9a3e0 commit d5129a4
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 2 deletions.
1 change: 1 addition & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ cc_library(
":config_h",
"@boost//:format",
"@boost//:multiprecision",
"@com_google_absl//absl/numeric:bits",
"@com_google_googletest//:gtest",
],
)
Expand Down
1 change: 1 addition & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,4 @@ add_library(p4ctoolkit STATIC ${LIBP4CTOOLKIT_SRCS})

# Disable libcall (realloc, malloc) optimizations which may cause infinite loops.
set_target_properties(p4ctoolkit PROPERTIES COMPILE_FLAGS -fno-builtin)
target_link_libraries(p4ctoolkit absl::bits)
22 changes: 20 additions & 2 deletions lib/bitrange.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ limitations under the License.
#include <optional>
#include <utility>

#include "absl/numeric/bits.h"
#include "bitvec.h"
#include "exceptions.h"
#include "hash.h"
Expand Down Expand Up @@ -71,7 +72,16 @@ namespace Detail {
* rounds towards zero. For example, `-7 / 8 == 0`, but
* `divideFloor(-7, 8) == -1`.
*/
inline int divideFloor(int dividend, int divisor) {
constexpr inline int divideFloor(int dividend, int divisor) {
#if defined(__GNUC__) || defined(__clang__)
// Code to enable compiler folding when the divisor is a power-of-two compile-time constant
// In this case, compiler should fold to a right-shift
// FIXME: Replace absl with std after moving to C++20
unsigned u_divisor = static_cast<unsigned>(divisor);
if (__builtin_constant_p(u_divisor) && absl::has_single_bit(u_divisor))
return dividend >> (absl::bit_width(u_divisor) - 1);
#endif // defined(__GNUC__) || defined(__clang__)

const int quotient = dividend / divisor;
const int remainder = dividend % divisor;
if ((remainder != 0) && ((remainder < 0) != (divisor < 0))) return quotient - 1;
Expand Down Expand Up @@ -102,7 +112,15 @@ constexpr int modulo(int dividend, int divisor) {
* dividends than for negative dividends.
* To make this concrete, `-7 % 8 == -7`, but `moduloFloor(-7, 8) == 1`.
*/
inline int moduloFloor(const int dividend, const int divisor) {
constexpr inline int moduloFloor(const int dividend, const int divisor) {
#if defined(__GNUC__) || defined(__clang__)
// Code to enable compiler folding when the divisor is a power-of-two compile-time constant
// In this case, compiler should fold to a bitwise-and
// FIXME: Replace absl with std after moving to C++20
if (__builtin_constant_p(divisor) && absl::has_single_bit(static_cast<unsigned>(divisor)))
return dividend & (divisor - 1);
#endif // defined(__GNUC__) || defined(__clang__)

const int remainder = modulo(dividend, divisor);
if (remainder == 0 || dividend >= 0) return remainder;
return divisor - remainder;
Expand Down

0 comments on commit d5129a4

Please sign in to comment.