Flutter Engine
The Flutter Engine
safe_math_arm_impl.h
Go to the documentation of this file.
1// Copyright 2017 The Chromium 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#ifndef BASE_NUMERICS_SAFE_MATH_ARM_IMPL_H_
6#define BASE_NUMERICS_SAFE_MATH_ARM_IMPL_H_
7
8#include <cassert>
9#include <limits>
10#include <type_traits>
11
13
14namespace base {
15namespace internal {
16
17template <typename T, typename U>
19 static const bool is_supported =
21
22 // The following is much more efficient than the Clang and GCC builtins for
23 // performing overflow-checked multiplication when a twice wider type is
24 // available. The below compiles down to 2-3 instructions, depending on the
25 // width of the types in use.
26 // As an example, an int32_t multiply compiles to:
27 // smull r0, r1, r0, r1
28 // cmp r1, r1, asr #31
29 // And an int16_t multiply compiles to:
30 // smulbb r1, r1, r0
31 // asr r2, r1, #16
32 // cmp r2, r1, asr #15
33 template <typename V>
34 __attribute__((always_inline)) static bool Do(T x, U y, V* result) {
35 using Promotion = typename FastIntegerArithmeticPromotion<T, U>::type;
36 Promotion presult;
37
38 presult = static_cast<Promotion>(x) * static_cast<Promotion>(y);
39 *result = static_cast<V>(presult);
40 return IsValueInRangeForNumericType<V>(presult);
41 }
42};
43
44template <typename T, typename U>
46 static const bool is_supported =
49 int32_t,
51
52 template <typename V>
53 __attribute__((always_inline)) static V Do(T x, U y) {
54 // This will get promoted to an int, so let the compiler do whatever is
55 // clever and rely on the saturated cast to bounds check.
57 return saturated_cast<V>(x + y);
58
59 int32_t result;
60 int32_t x_i32 = checked_cast<int32_t>(x);
61 int32_t y_i32 = checked_cast<int32_t>(y);
62
63 asm("qadd %[result], %[first], %[second]"
64 : [result] "=r"(result)
65 : [first] "r"(x_i32), [second] "r"(y_i32));
66 return saturated_cast<V>(result);
67 }
68};
69
70template <typename T, typename U>
72 static const bool is_supported =
75 int32_t,
77
78 template <typename V>
79 __attribute__((always_inline)) static V Do(T x, U y) {
80 // This will get promoted to an int, so let the compiler do whatever is
81 // clever and rely on the saturated cast to bounds check.
83 return saturated_cast<V>(x - y);
84
85 int32_t result;
86 int32_t x_i32 = checked_cast<int32_t>(x);
87 int32_t y_i32 = checked_cast<int32_t>(y);
88
89 asm("qsub %[result], %[first], %[second]"
90 : [result] "=r"(result)
91 : [first] "r"(x_i32), [second] "r"(y_i32));
92 return saturated_cast<V>(result);
93 }
94};
95
96template <typename T, typename U>
99
100 template <typename V>
101 __attribute__((always_inline)) static V Do(T x, U y) {
102 // Use the CheckedMulFastAsmOp for full-width 32-bit values, because
103 // it's fewer instructions than promoting and then saturating.
106 V result;
108 return result;
109 return CommonMaxOrMin<V>(IsValueNegative(x) ^ IsValueNegative(y));
110 }
111
114 return saturated_cast<V>(static_cast<Promotion>(x) *
115 static_cast<Promotion>(y));
116 }
117};
118
119} // namespace internal
120} // namespace base
121
122#endif // BASE_NUMERICS_SAFE_MATH_ARM_IMPL_H_
uint8_t value
GAsyncResult * result
T __attribute__((ext_vector_type(N))) V
double x
constexpr bool IsValueNegative(T value)
#define T
Definition: precompiler.cc:65
static constexpr bool Do(T, U, V *)
__attribute__((always_inline)) static bool Do(T x
__attribute__((always_inline)) static V Do(T x
typename FastIntegerArithmeticPromotion< T, U >::type Promotion
__attribute__((always_inline)) static V Do(T x
__attribute__((always_inline)) static V Do(T x