int_div_impl.inc 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. //===-- int_div_impl.inc - Integer division ---------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // Helpers used by __udivsi3, __umodsi3, __udivdi3, and __umodsi3.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #define clz(a) (sizeof(a) == sizeof(unsigned long long) ? __builtin_clzll(a) : clzsi(a))
  13. // Adapted from Figure 3-40 of The PowerPC Compiler Writer's Guide
  14. static __inline fixuint_t __udivXi3(fixuint_t n, fixuint_t d) {
  15. const unsigned N = sizeof(fixuint_t) * CHAR_BIT;
  16. // d == 0 cases are unspecified.
  17. unsigned sr = (d ? clz(d) : N) - (n ? clz(n) : N);
  18. // 0 <= sr <= N - 1 or sr is very large.
  19. if (sr > N - 1) // n < d
  20. return 0;
  21. if (sr == N - 1) // d == 1
  22. return n;
  23. ++sr;
  24. // 1 <= sr <= N - 1. Shifts do not trigger UB.
  25. fixuint_t r = n >> sr;
  26. n <<= N - sr;
  27. fixuint_t carry = 0;
  28. for (; sr > 0; --sr) {
  29. r = (r << 1) | (n >> (N - 1));
  30. n = (n << 1) | carry;
  31. // Branch-less version of:
  32. // carry = 0;
  33. // if (r >= d) r -= d, carry = 1;
  34. const fixint_t s = (fixint_t)(d - r - 1) >> (N - 1);
  35. carry = s & 1;
  36. r -= d & s;
  37. }
  38. n = (n << 1) | carry;
  39. return n;
  40. }
  41. // Mostly identical to __udivXi3 but the return values are different.
  42. static __inline fixuint_t __umodXi3(fixuint_t n, fixuint_t d) {
  43. const unsigned N = sizeof(fixuint_t) * CHAR_BIT;
  44. // d == 0 cases are unspecified.
  45. unsigned sr = (d ? clz(d) : N) - (n ? clz(n) : N);
  46. // 0 <= sr <= N - 1 or sr is very large.
  47. if (sr > N - 1) // n < d
  48. return n;
  49. if (sr == N - 1) // d == 1
  50. return 0;
  51. ++sr;
  52. // 1 <= sr <= N - 1. Shifts do not trigger UB.
  53. fixuint_t r = n >> sr;
  54. n <<= N - sr;
  55. fixuint_t carry = 0;
  56. for (; sr > 0; --sr) {
  57. r = (r << 1) | (n >> (N - 1));
  58. n = (n << 1) | carry;
  59. // Branch-less version of:
  60. // carry = 0;
  61. // if (r >= d) r -= d, carry = 1;
  62. const fixint_t s = (fixint_t)(d - r - 1) >> (N - 1);
  63. carry = s & 1;
  64. r -= d & s;
  65. }
  66. return r;
  67. }
  68. #ifdef COMPUTE_UDIV
  69. static __inline fixint_t __divXi3(fixint_t a, fixint_t b) {
  70. const int N = (int)(sizeof(fixint_t) * CHAR_BIT) - 1;
  71. fixint_t s_a = a >> N; // s_a = a < 0 ? -1 : 0
  72. fixint_t s_b = b >> N; // s_b = b < 0 ? -1 : 0
  73. fixuint_t a_u = (fixuint_t)(a ^ s_a) + (-s_a); // negate if s_a == -1
  74. fixuint_t b_u = (fixuint_t)(b ^ s_b) + (-s_b); // negate if s_b == -1
  75. s_a ^= s_b; // sign of quotient
  76. return (COMPUTE_UDIV(a_u, b_u) ^ s_a) + (-s_a); // negate if s_a == -1
  77. }
  78. #endif // COMPUTE_UDIV
  79. #ifdef ASSIGN_UMOD
  80. static __inline fixint_t __modXi3(fixint_t a, fixint_t b) {
  81. const int N = (int)(sizeof(fixint_t) * CHAR_BIT) - 1;
  82. fixint_t s = b >> N; // s = b < 0 ? -1 : 0
  83. fixuint_t b_u = (fixuint_t)(b ^ s) + (-s); // negate if s == -1
  84. s = a >> N; // s = a < 0 ? -1 : 0
  85. fixuint_t a_u = (fixuint_t)(a ^ s) + (-s); // negate if s == -1
  86. fixuint_t res;
  87. ASSIGN_UMOD(res, a_u, b_u);
  88. return (res ^ s) + (-s); // negate if s == -1
  89. }
  90. #endif // ASSIGN_UMOD