Skip to content

Commit

Permalink
help compiler folding for divideFloor/moduloFloor
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
  • Loading branch information
grg committed Mar 7, 2024
1 parent da7807d commit cf13472
Showing 1 changed file with 15 additions and 0 deletions.
15 changes: 15 additions & 0 deletions lib/bitrange.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,24 @@ class JSONLoader;
namespace BitRange {

namespace Detail {
/**
* @return boolean indicating if @p value is a power of two.
*
* This function is declared constexpr to allow it to be used in tests to optimize code generation.
*/
constexpr bool isPowerOfTwo(int value) { return value && !(value & (value - 1)); }

/**
* @return the result of dividing @dividend by @divisor, rounded towards
* negative infinity. This is different than normal C++ integer division, which
* rounds towards zero. For example, `-7 / 8 == 0`, but
* `divideFloor(-7, 8) == -1`.
*/
inline int divideFloor(int dividend, int divisor) {
// 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
if (__builtin_constant_p(divisor) && isPowerOfTwo(divisor)) return dividend >> divisor;

const int quotient = dividend / divisor;
const int remainder = dividend % divisor;
if ((remainder != 0) && ((remainder < 0) != (divisor < 0))) return quotient - 1;
Expand Down Expand Up @@ -103,6 +114,10 @@ constexpr int modulo(int dividend, int divisor) {
* To make this concrete, `-7 % 8 == -7`, but `moduloFloor(-7, 8) == 1`.
*/
inline int moduloFloor(const int dividend, const int divisor) {
// 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
if (__builtin_constant_p(divisor) && isPowerOfTwo(divisor)) return dividend & divisor;

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

0 comments on commit cf13472

Please sign in to comment.