101e04c3fSmrg/*
201e04c3fSmrg * Copyright © 2018 Advanced Micro Devices, Inc.
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2101e04c3fSmrg * IN THE SOFTWARE.
2201e04c3fSmrg */
2301e04c3fSmrg
2401e04c3fSmrg/* Imported from:
2501e04c3fSmrg *   https://raw.githubusercontent.com/ridiculousfish/libdivide/master/divide_by_constants_codegen_reference.c
2601e04c3fSmrg * Paper:
2701e04c3fSmrg *   http://ridiculousfish.com/files/faster_unsigned_division_by_constants.pdf
2801e04c3fSmrg *
2901e04c3fSmrg * The author, ridiculous_fish, wrote:
3001e04c3fSmrg *
3101e04c3fSmrg *  ''Reference implementations of computing and using the "magic number"
3201e04c3fSmrg *    approach to dividing by constants, including codegen instructions.
3301e04c3fSmrg *    The unsigned division incorporates the "round down" optimization per
3401e04c3fSmrg *    ridiculous_fish.
3501e04c3fSmrg *
3601e04c3fSmrg *    This is free and unencumbered software. Any copyright is dedicated
3701e04c3fSmrg *    to the Public Domain.''
3801e04c3fSmrg */
3901e04c3fSmrg
4001e04c3fSmrg#include "fast_idiv_by_const.h"
4101e04c3fSmrg#include "u_math.h"
427ec681f3Smrg#include "util/macros.h"
4301e04c3fSmrg#include <limits.h>
4401e04c3fSmrg#include <assert.h>
4501e04c3fSmrg
4601e04c3fSmrgstruct util_fast_udiv_info
4701e04c3fSmrgutil_compute_fast_udiv_info(uint64_t D, unsigned num_bits, unsigned UINT_BITS)
4801e04c3fSmrg{
4901e04c3fSmrg   /* The numerator must fit in a uint64_t */
5001e04c3fSmrg   assert(num_bits > 0 && num_bits <= UINT_BITS);
5101e04c3fSmrg   assert(D != 0);
5201e04c3fSmrg
5301e04c3fSmrg   /* The eventual result */
5401e04c3fSmrg   struct util_fast_udiv_info result;
5501e04c3fSmrg
5601e04c3fSmrg   if (util_is_power_of_two_or_zero64(D)) {
5701e04c3fSmrg      unsigned div_shift = util_logbase2_64(D);
5801e04c3fSmrg
5901e04c3fSmrg      if (div_shift) {
6001e04c3fSmrg         /* Dividing by a power of two. */
6101e04c3fSmrg         result.multiplier = 1ull << (UINT_BITS - div_shift);
6201e04c3fSmrg         result.pre_shift = 0;
6301e04c3fSmrg         result.post_shift = 0;
6401e04c3fSmrg         result.increment = 0;
6501e04c3fSmrg         return result;
6601e04c3fSmrg      } else {
6701e04c3fSmrg         /* Dividing by 1. */
6801e04c3fSmrg         /* Assuming: floor((num + 1) * (2^32 - 1) / 2^32) = num */
697ec681f3Smrg         result.multiplier = u_uintN_max(UINT_BITS);
7001e04c3fSmrg         result.pre_shift = 0;
7101e04c3fSmrg         result.post_shift = 0;
7201e04c3fSmrg         result.increment = 1;
7301e04c3fSmrg         return result;
7401e04c3fSmrg      }
7501e04c3fSmrg   }
7601e04c3fSmrg
7701e04c3fSmrg   /* The extra shift implicit in the difference between UINT_BITS and num_bits
7801e04c3fSmrg    */
7901e04c3fSmrg   const unsigned extra_shift = UINT_BITS - num_bits;
8001e04c3fSmrg
8101e04c3fSmrg   /* The initial power of 2 is one less than the first one that can possibly
8201e04c3fSmrg    * work.
8301e04c3fSmrg    */
8401e04c3fSmrg   const uint64_t initial_power_of_2 = (uint64_t)1 << (UINT_BITS-1);
8501e04c3fSmrg
8601e04c3fSmrg   /* The remainder and quotient of our power of 2 divided by d */
8701e04c3fSmrg   uint64_t quotient = initial_power_of_2 / D;
8801e04c3fSmrg   uint64_t remainder = initial_power_of_2 % D;
8901e04c3fSmrg
9001e04c3fSmrg   /* ceil(log_2 D) */
9101e04c3fSmrg   unsigned ceil_log_2_D;
9201e04c3fSmrg
9301e04c3fSmrg   /* The magic info for the variant "round down" algorithm */
9401e04c3fSmrg   uint64_t down_multiplier = 0;
9501e04c3fSmrg   unsigned down_exponent = 0;
9601e04c3fSmrg   int has_magic_down = 0;
9701e04c3fSmrg
9801e04c3fSmrg   /* Compute ceil(log_2 D) */
9901e04c3fSmrg   ceil_log_2_D = 0;
10001e04c3fSmrg   uint64_t tmp;
10101e04c3fSmrg   for (tmp = D; tmp > 0; tmp >>= 1)
10201e04c3fSmrg      ceil_log_2_D += 1;
10301e04c3fSmrg
10401e04c3fSmrg
10501e04c3fSmrg   /* Begin a loop that increments the exponent, until we find a power of 2
10601e04c3fSmrg    * that works.
10701e04c3fSmrg    */
10801e04c3fSmrg   unsigned exponent;
10901e04c3fSmrg   for (exponent = 0; ; exponent++) {
11001e04c3fSmrg      /* Quotient and remainder is from previous exponent; compute it for this
11101e04c3fSmrg       * exponent.
11201e04c3fSmrg       */
11301e04c3fSmrg      if (remainder >= D - remainder) {
11401e04c3fSmrg         /* Doubling remainder will wrap around D */
11501e04c3fSmrg         quotient = quotient * 2 + 1;
11601e04c3fSmrg         remainder = remainder * 2 - D;
11701e04c3fSmrg      } else {
11801e04c3fSmrg         /* Remainder will not wrap */
11901e04c3fSmrg         quotient = quotient * 2;
12001e04c3fSmrg         remainder = remainder * 2;
12101e04c3fSmrg      }
12201e04c3fSmrg
12301e04c3fSmrg      /* We're done if this exponent works for the round_up algorithm.
12401e04c3fSmrg       * Note that exponent may be larger than the maximum shift supported,
12501e04c3fSmrg       * so the check for >= ceil_log_2_D is critical.
12601e04c3fSmrg       */
12701e04c3fSmrg      if ((exponent + extra_shift >= ceil_log_2_D) ||
12801e04c3fSmrg          (D - remainder) <= ((uint64_t)1 << (exponent + extra_shift)))
12901e04c3fSmrg         break;
13001e04c3fSmrg
13101e04c3fSmrg      /* Set magic_down if we have not set it yet and this exponent works for
13201e04c3fSmrg       * the round_down algorithm
13301e04c3fSmrg       */
13401e04c3fSmrg      if (!has_magic_down &&
13501e04c3fSmrg          remainder <= ((uint64_t)1 << (exponent + extra_shift))) {
13601e04c3fSmrg         has_magic_down = 1;
13701e04c3fSmrg         down_multiplier = quotient;
13801e04c3fSmrg         down_exponent = exponent;
13901e04c3fSmrg      }
14001e04c3fSmrg   }
14101e04c3fSmrg
14201e04c3fSmrg   if (exponent < ceil_log_2_D) {
14301e04c3fSmrg      /* magic_up is efficient */
14401e04c3fSmrg      result.multiplier = quotient + 1;
14501e04c3fSmrg      result.pre_shift = 0;
14601e04c3fSmrg      result.post_shift = exponent;
14701e04c3fSmrg      result.increment = 0;
14801e04c3fSmrg   } else if (D & 1) {
14901e04c3fSmrg      /* Odd divisor, so use magic_down, which must have been set */
15001e04c3fSmrg      assert(has_magic_down);
15101e04c3fSmrg      result.multiplier = down_multiplier;
15201e04c3fSmrg      result.pre_shift = 0;
15301e04c3fSmrg      result.post_shift = down_exponent;
15401e04c3fSmrg      result.increment = 1;
15501e04c3fSmrg   } else {
15601e04c3fSmrg      /* Even divisor, so use a prefix-shifted dividend */
15701e04c3fSmrg      unsigned pre_shift = 0;
15801e04c3fSmrg      uint64_t shifted_D = D;
15901e04c3fSmrg      while ((shifted_D & 1) == 0) {
16001e04c3fSmrg         shifted_D >>= 1;
16101e04c3fSmrg         pre_shift += 1;
16201e04c3fSmrg      }
16301e04c3fSmrg      result = util_compute_fast_udiv_info(shifted_D, num_bits - pre_shift,
16401e04c3fSmrg                                           UINT_BITS);
16501e04c3fSmrg      /* expect no increment or pre_shift in this path */
16601e04c3fSmrg      assert(result.increment == 0 && result.pre_shift == 0);
16701e04c3fSmrg      result.pre_shift = pre_shift;
16801e04c3fSmrg   }
16901e04c3fSmrg   return result;
17001e04c3fSmrg}
17101e04c3fSmrg
17201e04c3fSmrgstatic inline int64_t
17301e04c3fSmrgsign_extend(int64_t x, unsigned SINT_BITS)
17401e04c3fSmrg{
1757ec681f3Smrg   return (int64_t)((uint64_t)x << (64 - SINT_BITS)) >> (64 - SINT_BITS);
17601e04c3fSmrg}
17701e04c3fSmrg
17801e04c3fSmrgstruct util_fast_sdiv_info
17901e04c3fSmrgutil_compute_fast_sdiv_info(int64_t D, unsigned SINT_BITS)
18001e04c3fSmrg{
18101e04c3fSmrg   /* D must not be zero. */
18201e04c3fSmrg   assert(D != 0);
18301e04c3fSmrg   /* The result is not correct for these divisors. */
18401e04c3fSmrg   assert(D != 1 && D != -1);
18501e04c3fSmrg
18601e04c3fSmrg   /* Our result */
18701e04c3fSmrg   struct util_fast_sdiv_info result;
18801e04c3fSmrg
18901e04c3fSmrg   /* Absolute value of D (we know D is not the most negative value since
19001e04c3fSmrg    * that's a power of 2)
19101e04c3fSmrg    */
19201e04c3fSmrg   const uint64_t abs_d = (D < 0 ? -D : D);
19301e04c3fSmrg
19401e04c3fSmrg   /* The initial power of 2 is one less than the first one that can possibly
19501e04c3fSmrg    * work */
19601e04c3fSmrg   /* "two31" in Warren */
19701e04c3fSmrg   unsigned exponent = SINT_BITS - 1;
19801e04c3fSmrg   const uint64_t initial_power_of_2 = (uint64_t)1 << exponent;
19901e04c3fSmrg
20001e04c3fSmrg   /* Compute the absolute value of our "test numerator,"
20101e04c3fSmrg    * which is the largest dividend whose remainder with d is d-1.
20201e04c3fSmrg    * This is called anc in Warren.
20301e04c3fSmrg    */
20401e04c3fSmrg   const uint64_t tmp = initial_power_of_2 + (D < 0);
20501e04c3fSmrg   const uint64_t abs_test_numer = tmp - 1 - tmp % abs_d;
20601e04c3fSmrg
20701e04c3fSmrg   /* Initialize our quotients and remainders (q1, r1, q2, r2 in Warren) */
20801e04c3fSmrg   uint64_t quotient1 = initial_power_of_2 / abs_test_numer;
20901e04c3fSmrg   uint64_t remainder1 = initial_power_of_2 % abs_test_numer;
21001e04c3fSmrg   uint64_t quotient2 = initial_power_of_2 / abs_d;
21101e04c3fSmrg   uint64_t remainder2 = initial_power_of_2 % abs_d;
21201e04c3fSmrg   uint64_t delta;
21301e04c3fSmrg
21401e04c3fSmrg   /* Begin our loop */
21501e04c3fSmrg   do {
21601e04c3fSmrg      /* Update the exponent */
21701e04c3fSmrg      exponent++;
21801e04c3fSmrg
21901e04c3fSmrg      /* Update quotient1 and remainder1 */
22001e04c3fSmrg      quotient1 *= 2;
22101e04c3fSmrg      remainder1 *= 2;
22201e04c3fSmrg      if (remainder1 >= abs_test_numer) {
22301e04c3fSmrg         quotient1 += 1;
22401e04c3fSmrg         remainder1 -= abs_test_numer;
22501e04c3fSmrg      }
22601e04c3fSmrg
22701e04c3fSmrg      /* Update quotient2 and remainder2 */
22801e04c3fSmrg      quotient2 *= 2;
22901e04c3fSmrg      remainder2 *= 2;
23001e04c3fSmrg      if (remainder2 >= abs_d) {
23101e04c3fSmrg         quotient2 += 1;
23201e04c3fSmrg         remainder2 -= abs_d;
23301e04c3fSmrg      }
23401e04c3fSmrg
23501e04c3fSmrg      /* Keep going as long as (2**exponent) / abs_d <= delta */
23601e04c3fSmrg      delta = abs_d - remainder2;
23701e04c3fSmrg   } while (quotient1 < delta || (quotient1 == delta && remainder1 == 0));
23801e04c3fSmrg
23901e04c3fSmrg   result.multiplier = sign_extend(quotient2 + 1, SINT_BITS);
24001e04c3fSmrg   if (D < 0) result.multiplier = -result.multiplier;
24101e04c3fSmrg   result.shift = exponent - SINT_BITS;
24201e04c3fSmrg   return result;
24301e04c3fSmrg}
244