From: MITSUNARI Shigeo <[email protected]>

Thanks for the review.  I chased down both concerns; neither can
happen, and here is why.  Below, `size` is the bit width of the mode
being divided, i.e. we are dividing a uint{size}_t value (size = 32
for uint32_t) by a constant d, and the helper is only reached in the
mh != 0 case of

  mh = choose_multiplier (d, size, size, &ml, &post_shift);

1) post_shift > size cannot happen, so `size - post_shift` is never
negative.  choose_multiplier initializes post_shift to
lgup = ceil_log2 (d) and only ever decreases it in its reduction
loop, and it asserts lgup <= n where the caller passes n = size
(gcc_assert in choose_multiplier).  Since d is a uint{size}_t
divisor, d < 2^size and hence lgup <= size.  Therefore
post_shift <= size always holds.

2) The magic computation cannot overflow.  choose_multiplier masks
ml to its low `size` bits, so ml < 2^size and the (size+1)-bit
multiplier satisfies 2^size + ml < 2^(size+1).  Shifting it left by
size - post_shift gives

  magic < 2^(2*size + 1 - post_shift) <= 2^(2*size)

because the helper already requires post_shift >= 1.  The helper also
requires GET_MODE_BITSIZE (wide_mode) <= HOST_BITS_PER_WIDE_INT,
i.e. 2*size <= HOST_BITS_PER_WIDE_INT, so magic always fits in an
unsigned HOST_WIDE_INT: for uint32_t, magic < 2^64.  The individual
shift counts (size and size - post_shift) are likewise below
HOST_BITS_PER_WIDE_INT, so no undefined behavior either.

So there is no latent bug, but to make this explicit v9 adds
gcc_checking_assert (post_shift <= size) together with comments
documenting both facts.

v9 also replaces the goto with

  if (quotient == NULL_RTX)
    {
      /* classic sub/shift/add sequence, reindented */
    }

as you suggested.

I agree that supporting a wider-than-word wide_mode on targets with a
suitable high-part multiply is best left to a follow-up; v9 does not
attempt it.

I will post v9 shortly.

Best regards,
MITSUNARI Shigeo

Reply via email to