|
30 | 30 | namespace arrow { |
31 | 31 | namespace internal { |
32 | 32 |
|
33 | | -// static inline bool check_add_int32_int32(int32_t a, int32_t b, int32_t* ret) |
34 | | - |
35 | 33 | // Define functions AddWithOverflow, SubtractWithOverflow, MultiplyWithOverflow |
36 | 34 | // with the signature `bool(T u, T v, T* out)` where T is an integer type. |
37 | 35 | // On overflow, these functions return true. Otherwise, false is returned |
@@ -63,46 +61,69 @@ using transformed_int_t = |
63 | 61 | template <typename Int> |
64 | 62 | using upscaled_int32_t = transformed_int_t<Int, int32_t, uint32_t>; |
65 | 63 |
|
66 | | -// TODO use builtins on clang/gcc |
| 64 | +// Use GCC/CLang builtins for checked arithmetic, promising better performance |
| 65 | +// than SafeInt's hand-written implementations. |
| 66 | +#if defined __has_builtin |
| 67 | +# if __has_builtin(__builtin_object_size) |
| 68 | +# define USE_CHECKED_ARITHMETIC_BUILTINS 1 |
| 69 | +# else |
| 70 | +# define USE_CHECKED_ARITHMETIC_BUILTINS 0 |
| 71 | +# endif |
| 72 | +#endif |
67 | 73 |
|
68 | 74 | template <typename Int> |
69 | 75 | [[nodiscard]] bool AddWithOverflowGeneric(Int u, Int v, Int* out) { |
| 76 | +#if USE_CHECKED_ARITHMETIC_BUILTINS |
| 77 | + return __builtin_add_overflow(u, v, out); |
| 78 | +#else |
70 | 79 | if constexpr (sizeof(Int) < 4) { |
71 | 80 | auto r = |
72 | | - static_cast<upscaled_int32_t<Int>>(u) + static_cast<upscaled_int32_t<Int>>(v); |
| 81 | + static_cast<upscaled_int32_t<Int> >(u) + static_cast<upscaled_int32_t<Int> >(v); |
73 | 82 | *out = static_cast<Int>(r); |
74 | 83 | return r != *out; |
75 | 84 | } else { |
76 | 85 | return SafeIntAddWithOverflow(u, v, out); |
77 | 86 | } |
| 87 | +#endif |
78 | 88 | } |
79 | 89 |
|
80 | 90 | template <typename Int> |
81 | 91 | [[nodiscard]] bool SubtractWithOverflowGeneric(Int u, Int v, Int* out) { |
| 92 | +#if USE_CHECKED_ARITHMETIC_BUILTINS |
| 93 | + return __builtin_sub_overflow(u, v, out); |
| 94 | +#else |
82 | 95 | if constexpr (sizeof(Int) < 4) { |
83 | 96 | auto r = |
84 | | - static_cast<upscaled_int32_t<Int>>(u) - static_cast<upscaled_int32_t<Int>>(v); |
| 97 | + static_cast<upscaled_int32_t<Int> >(u) - static_cast<upscaled_int32_t<Int> >(v); |
85 | 98 | *out = static_cast<Int>(r); |
86 | 99 | return r != *out; |
87 | 100 | } else { |
88 | 101 | return SafeIntSubtractWithOverflow(u, v, out); |
89 | 102 | } |
| 103 | +#endif |
90 | 104 | } |
91 | 105 |
|
92 | 106 | template <typename Int> |
93 | 107 | [[nodiscard]] bool MultiplyWithOverflowGeneric(Int u, Int v, Int* out) { |
| 108 | +#if USE_CHECKED_ARITHMETIC_BUILTINS |
| 109 | + return __builtin_mul_overflow(u, v, out); |
| 110 | +#else |
94 | 111 | if constexpr (sizeof(Int) < 4) { |
95 | 112 | auto r = |
96 | | - static_cast<upscaled_int32_t<Int>>(u) * static_cast<upscaled_int32_t<Int>>(v); |
| 113 | + static_cast<upscaled_int32_t<Int> >(u) * static_cast<upscaled_int32_t<Int> >(v); |
97 | 114 | *out = static_cast<Int>(r); |
98 | 115 | return r != *out; |
99 | 116 | } else { |
100 | 117 | return SafeIntMultiplyWithOverflow(u, v, out); |
101 | 118 | } |
| 119 | +#endif |
102 | 120 | } |
103 | 121 |
|
104 | 122 | template <typename Int> |
105 | 123 | [[nodiscard]] bool DivideWithOverflowGeneric(Int u, Int v, Int* out) { |
| 124 | + if (v == 0) { |
| 125 | + return true; |
| 126 | + } |
106 | 127 | if constexpr (sizeof(Int) < 4) { |
107 | 128 | using UpscaledInt = upscaled_int32_t<Int>; |
108 | 129 | UpscaledInt r; |
|
0 commit comments