1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef BERBERIS_INTRINSICS_COMMON_INTRINSICS_H_
18 #define BERBERIS_INTRINSICS_COMMON_INTRINSICS_H_
19 
20 #include <cstdint>
21 
22 #include "berberis/base/dependent_false.h"
23 #include "berberis/intrinsics/common/intrinsics_float.h"  // Float16/Float32/Float64
24 
25 namespace berberis {
26 
27 class SIMD128Register;
28 
29 namespace intrinsics {
30 #if !defined(__aarch64__)
31 enum EnumFromTemplateType {
32   kInt8T,
33   kUInt8T,
34   kInt16T,
35   kUInt16T,
36   kInt32T,
37   kUInt32T,
38   kInt64T,
39   kUInt64T,
40   kFloat16,
41   kFloat32,
42   kFloat64,
43   kSIMD128Register,
44 };
45 
46 template <typename Type>
TypeToEnumFromTemplateType()47 constexpr EnumFromTemplateType TypeToEnumFromTemplateType() {
48   if constexpr (std::is_same_v<int8_t, std::decay_t<Type>>) {
49     return EnumFromTemplateType::kInt8T;
50   } else if constexpr (std::is_same_v<uint8_t, std::decay_t<Type>>) {
51     return EnumFromTemplateType::kUInt8T;
52   } else if constexpr (std::is_same_v<int16_t, std::decay_t<Type>>) {
53     return EnumFromTemplateType::kUInt16T;
54   } else if constexpr (std::is_same_v<uint16_t, std::decay_t<Type>>) {
55     return EnumFromTemplateType::kUInt16T;
56   } else if constexpr (std::is_same_v<int32_t, std::decay_t<Type>>) {
57     return EnumFromTemplateType::kUInt32T;
58   } else if constexpr (std::is_same_v<uint32_t, std::decay_t<Type>>) {
59     return EnumFromTemplateType::kUInt32T;
60   } else if constexpr (std::is_same_v<int64_t, std::decay_t<Type>>) {
61     return EnumFromTemplateType::kUInt64T;
62   } else if constexpr (std::is_same_v<uint64_t, std::decay_t<Type>>) {
63     return EnumFromTemplateType::kUInt64T;
64   } else if constexpr (std::is_same_v<Float16, std::decay_t<Type>>) {
65     return EnumFromTemplateType::kFloat16;
66   } else if constexpr (std::is_same_v<Float32, std::decay_t<Type>>) {
67     return EnumFromTemplateType::kFloat32;
68   } else if constexpr (std::is_same_v<Float64, std::decay_t<Type>>) {
69     return EnumFromTemplateType::kFloat64;
70   } else if constexpr (std::is_same_v<Float64, std::decay_t<Type>>) {
71     return EnumFromTemplateType::kSIMD128Register;
72   } else {
73     static_assert(kDependentTypeFalse<Type>);
74   }
75 }
76 
77 template <typename Type>
78 constexpr EnumFromTemplateType kEnumFromTemplateType = TypeToEnumFromTemplateType<Type>();
79 #endif
80 // A solution for the inability to call generic implementation from specialization.
81 // Declaration:
82 //   template <typename Type,
83 //             int size,
84 //             enum PreferredIntrinsicsImplementation = kUseAssemblerImplementationIfPossible>
85 //   inline std::tuple<SIMD128Register> VectorMultiplyByScalarInt(SIMD128Register op1,
86 //                                                                SIMD128Register op2);
87 // Normal use only specifies two arguments, e.g. VectorMultiplyByScalarInt<uint32_t, 2>,
88 // but assembler implementation can (if SSE 4.1 is not available) do the following call:
89 //   return VectorMultiplyByScalarInt<uint32_t, 2, kUseCppImplementation>(in0, in1);
90 //
91 // Because PreferredIntrinsicsImplementation argument has non-default value we have call to the
92 // generic C-based implementation here.
93 
94 enum PreferredIntrinsicsImplementation {
95   kUseAssemblerImplementationIfPossible,
96   kUseCppImplementation
97 };
98 
99 }  // namespace intrinsics
100 
101 }  // namespace berberis
102 
103 #endif  // BERBERIS_INTRINSICS_COMMON_INTRINSICS_H_
104