Line data Source code
1 : // Copyright 2014 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/base/bits.h"
6 :
7 : #include <limits>
8 :
9 : #include "src/base/logging.h"
10 :
11 : namespace v8 {
12 : namespace base {
13 : namespace bits {
14 :
15 2948447 : uint32_t RoundUpToPowerOfTwo32(uint32_t value) {
16 : DCHECK_LE(value, uint32_t{1} << 31);
17 2948447 : if (value) --value;
18 : // Use computation based on leading zeros if we have compiler support for that.
19 : #if V8_HAS_BUILTIN_CLZ || V8_CC_MSVC
20 2948447 : return 1u << (32 - CountLeadingZeros(value));
21 : #else
22 : value |= value >> 1;
23 : value |= value >> 2;
24 : value |= value >> 4;
25 : value |= value >> 8;
26 : value |= value >> 16;
27 : return value + 1;
28 : #endif
29 : }
30 :
31 1918076 : uint64_t RoundUpToPowerOfTwo64(uint64_t value) {
32 : DCHECK_LE(value, uint64_t{1} << 63);
33 1918076 : if (value) --value;
34 : // Use computation based on leading zeros if we have compiler support for that.
35 : #if V8_HAS_BUILTIN_CLZ
36 1918076 : return uint64_t{1} << (64 - CountLeadingZeros(value));
37 : #else
38 : value |= value >> 1;
39 : value |= value >> 2;
40 : value |= value >> 4;
41 : value |= value >> 8;
42 : value |= value >> 16;
43 : value |= value >> 32;
44 : return value + 1;
45 : #endif
46 : }
47 :
48 :
49 1280 : int32_t SignedMulHigh32(int32_t lhs, int32_t rhs) {
50 2655 : int64_t const value = static_cast<int64_t>(lhs) * static_cast<int64_t>(rhs);
51 2655 : return bit_cast<int32_t, uint32_t>(bit_cast<uint64_t>(value) >> 32u);
52 : }
53 :
54 :
55 1375 : int32_t SignedMulHighAndAdd32(int32_t lhs, int32_t rhs, int32_t acc) {
56 1375 : return bit_cast<int32_t>(bit_cast<uint32_t>(acc) +
57 1375 : bit_cast<uint32_t>(SignedMulHigh32(lhs, rhs)));
58 : }
59 :
60 :
61 19838 : int32_t SignedDiv32(int32_t lhs, int32_t rhs) {
62 19838 : if (rhs == 0) return 0;
63 19787 : if (rhs == -1) return lhs == std::numeric_limits<int32_t>::min() ? lhs : -lhs;
64 19451 : return lhs / rhs;
65 : }
66 :
67 :
68 39384 : int32_t SignedMod32(int32_t lhs, int32_t rhs) {
69 39384 : if (rhs == 0 || rhs == -1) return 0;
70 39182 : return lhs % rhs;
71 : }
72 :
73 139950 : int64_t SignedSaturatedAdd64(int64_t lhs, int64_t rhs) {
74 : using limits = std::numeric_limits<int64_t>;
75 : // Underflow if {lhs + rhs < min}. In that case, return {min}.
76 139950 : if (rhs < 0 && lhs < limits::min() - rhs) return limits::min();
77 : // Overflow if {lhs + rhs > max}. In that case, return {max}.
78 139950 : if (rhs >= 0 && lhs > limits::max() - rhs) return limits::max();
79 139950 : return lhs + rhs;
80 : }
81 :
82 0 : int64_t SignedSaturatedSub64(int64_t lhs, int64_t rhs) {
83 : using limits = std::numeric_limits<int64_t>;
84 : // Underflow if {lhs - rhs < min}. In that case, return {min}.
85 0 : if (rhs > 0 && lhs < limits::min() + rhs) return limits::min();
86 : // Overflow if {lhs - rhs > max}. In that case, return {max}.
87 0 : if (rhs <= 0 && lhs > limits::max() + rhs) return limits::max();
88 0 : return lhs - rhs;
89 : }
90 :
91 97702 : bool SignedMulOverflow32(int32_t lhs, int32_t rhs, int32_t* val) {
92 : // Compute the result as {int64_t}, then check for overflow.
93 97702 : int64_t result = int64_t{lhs} * int64_t{rhs};
94 97702 : *val = static_cast<int32_t>(result);
95 : using limits = std::numeric_limits<int32_t>;
96 97702 : return result < limits::min() || result > limits::max();
97 : }
98 :
99 : } // namespace bits
100 : } // namespace base
101 : } // namespace v8
|