v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
safe_math_arm_impl.h
Go to the documentation of this file.
1// Copyright 2017 The Chromium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Slightly adapted for inclusion in V8.
6// Copyright 2025 the V8 project authors. All rights reserved.
7
8#ifndef V8_BASE_NUMERICS_SAFE_MATH_ARM_IMPL_H_
9#define V8_BASE_NUMERICS_SAFE_MATH_ARM_IMPL_H_
10
11// IWYU pragma: private
12
13#include <stdint.h>
14
15#include <cassert>
16
18
19namespace v8::base::internal {
20
21template <typename T, typename U>
22struct CheckedMulFastAsmOp {
23 static constexpr bool is_supported =
25
26 // The following is not an assembler routine and is thus constexpr safe, it
27 // just emits much more efficient code than the Clang and GCC builtins for
28 // performing overflow-checked multiplication when a twice wider type is
29 // available. The below compiles down to 2-3 instructions, depending on the
30 // width of the types in use.
31 // As an example, an int32_t multiply compiles to:
32 // smull r0, r1, r0, r1
33 // cmp r1, r1, asr #31
34 // And an int16_t multiply compiles to:
35 // smulbb r1, r1, r0
36 // asr r2, r1, #16
37 // cmp r2, r1, asr #15
38 template <typename V>
39 static constexpr bool Do(T x, U y, V* result) {
41 Promotion presult;
42
43 presult = static_cast<Promotion>(x) * static_cast<Promotion>(y);
44 if (!IsValueInRangeForNumericType<V>(presult)) {
45 return false;
46 }
47 *result = static_cast<V>(presult);
48 return true;
49 }
50};
51
52template <typename T, typename U>
53struct ClampedAddFastAsmOp {
54 static constexpr bool is_supported =
56 kIsTypeInRangeForNumericType<int32_t, BigEnoughPromotion<T, U>>;
57
58 template <typename V>
59 __attribute__((always_inline)) static V Do(T x, U y) {
60 // This will get promoted to an int, so let the compiler do whatever is
61 // clever and rely on the saturated cast to bounds check.
63 return saturated_cast<V>(static_cast<int>(x) + static_cast<int>(y));
64 } else {
65 int32_t result;
66 int32_t x_i32 = checked_cast<int32_t>(x);
67 int32_t y_i32 = checked_cast<int32_t>(y);
68
69 asm("qadd %[result], %[first], %[second]"
70 : [result] "=r"(result)
71 : [first] "r"(x_i32), [second] "r"(y_i32));
73 }
74 }
75};
76
77template <typename T, typename U>
78struct ClampedSubFastAsmOp {
79 static constexpr bool is_supported =
81 kIsTypeInRangeForNumericType<int32_t, BigEnoughPromotion<T, U>>;
82
83 template <typename V>
84 __attribute__((always_inline)) static V Do(T x, U y) {
85 // This will get promoted to an int, so let the compiler do whatever is
86 // clever and rely on the saturated cast to bounds check.
88 return saturated_cast<V>(static_cast<int>(x) - static_cast<int>(y));
89 } else {
90 int32_t result;
91 int32_t x_i32 = checked_cast<int32_t>(x);
92 int32_t y_i32 = checked_cast<int32_t>(y);
93
94 asm("qsub %[result], %[first], %[second]"
95 : [result] "=r"(result)
96 : [first] "r"(x_i32), [second] "r"(y_i32));
98 }
99 }
100};
101
102template <typename T, typename U>
103struct ClampedMulFastAsmOp {
104 static constexpr bool is_supported =
106
107 template <typename V>
108 __attribute__((always_inline)) static V Do(T x, U y) {
109 // Use the CheckedMulFastAsmOp for full-width 32-bit values, because
110 // it's fewer instructions than promoting and then saturating.
113 V result;
115 ? result
117 } else {
119 using Promotion = FastIntegerArithmeticPromotion<T, U>;
120 return saturated_cast<V>(static_cast<Promotion>(x) *
121 static_cast<Promotion>(y));
122 }
123 }
124};
125
126} // namespace v8::base::internal
127
128#endif // V8_BASE_NUMERICS_SAFE_MATH_ARM_IMPL_H_
#define V(Name)
double second
ZoneVector< RpoNumber > & result
int y
int x
constexpr bool IsValueNegative(T value)
constexpr bool kEnableAsmCode
constexpr bool kIsBigEnoughPromotionContained
constexpr Dst checked_cast(Src value)
constexpr bool kIsIntegerArithmeticSafe
constexpr bool kIsFastIntegerArithmeticPromotionContained
constexpr Dst CommonMaxOrMin(bool is_min)
FastIntegerArithmeticPromotionImpl< Lhs, Rhs >::type FastIntegerArithmeticPromotion
constexpr Dst saturated_cast(Src value)
static constexpr bool Do(T x, U y, V *result)
__attribute__((always_inline)) static V Do(T x
__attribute__((always_inline)) static V Do(T x
__attribute__((always_inline)) static V Do(T x