1 /*
2 Copyright (c) 2005-2021 Intel Corporation
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 // Header that sets HAVE_m128/HAVE_m256 if vector types (__m128/__m256) are available
18
19 //! Class for testing safety of using vector types.
20 /** Uses circuitous logic forces compiler to put __m128/__m256 objects on stack while
21 executing various methods, and thus tempt it to use aligned loads and stores
22 on the stack. */
23 // Do not create file-scope objects of the class, because MinGW (as of May 2010)
24 // did not always provide proper stack alignment in destructors of such objects.
25
26 #ifndef __TBB_test_common_vector_types_H_
27 #define __TBB_test_common_vector_types_H_
28
29 #include "config.h"
30
31 #if (_MSC_VER>=1600)
32 //TODO: handle /arch:AVX in the right way.
33 #pragma warning (push)
34 #pragma warning (disable: 4752)
35 #endif
36
37 #if __TBB_GCC_WARNING_IGNORED_ATTRIBUTES_PRESENT
38 #pragma GCC diagnostic push
39 #pragma GCC diagnostic ignored "-Wignored-attributes"
40 #endif
41
42 template <typename Mvec>
43 class ClassWithVectorType {
44 static constexpr int n = 16;
45 static constexpr int F = sizeof(Mvec)/sizeof(float);
46 Mvec field[n];
47
48 void init( int );
49 public:
ClassWithVectorType()50 ClassWithVectorType() { init(-n); }
ClassWithVectorType(int i)51 ClassWithVectorType( int i ) { init(i); }
ClassWithVectorType(const ClassWithVectorType & src)52 ClassWithVectorType( const ClassWithVectorType& src ) {
53 for (int i = 0; i < n; ++i) {
54 field[i] = src.field[i];
55 }
56 }
57
58 ClassWithVectorType& operator=( const ClassWithVectorType& src ) {
59 Mvec stack[n];
60 for (int i = 0; i < n; ++i) {
61 stack[i^5] = src.field[i];
62 }
63 for (int i = 0; i < n; ++i) {
64 field[i^5] = stack[i];
65 }
66 return *this;
67 }
68
~ClassWithVectorType()69 ~ClassWithVectorType() { init(-2 * n); }
70
71 friend bool operator==( const ClassWithVectorType& x, const ClassWithVectorType& y ) {
72 for( int i = 0; i < F*n; ++i ) {
73 if( ((const float*)x.field)[i] != ((const float*)y.field)[i] )
74 return false;
75 }
76 return true;
77 }
78
79 friend bool operator!=( const ClassWithVectorType& x, const ClassWithVectorType& y ) {
80 return !(x == y);
81 }
82 }; // class ClassWithVectorType
83
84 template <typename Mvec>
init(int start)85 void ClassWithVectorType<Mvec>::init( int start ) {
86 Mvec stack[n];
87 for( int i = 0; i < n; ++i ) {
88 // Declaring value as a one-element array instead of a scalar quites
89 // gratuitous warnings about possible use of "value" before it was set.
90 Mvec value[1];
91 for( int j = 0; j < F; ++j )
92 ((float*)value)[j] = float(n*start+F*i+j);
93 stack[i^5] = value[0];
94 }
95 for( int i = 0; i < n; ++i )
96 field[i^5] = stack[i];
97 }
98
99 #if (defined(__AVX__) || (_MSC_VER >= 1600 && defined(_M_X64))) && !defined(__sun)
100 #include <immintrin.h>
101 #if __clang__
102 #include <avxintrin.h>
103 #endif
104 #define HAVE_m256 1
105 using ClassWithAVX = ClassWithVectorType<__m256>;
106 #if _MSC_VER
107 #include <intrin.h> // for __cpuid
108 #endif
have_AVX()109 bool have_AVX() {
110 bool result = false;
111 const int avx_mask = 1 << 28;
112 #if _MSC_VER || defined(__INTEL_COMPILER)
113 int info[4] = {0, 0, 0, 0};
114 const int ECX = 2;
115 __cpuid(info, 1);
116 result = (info[ECX] & avx_mask) != 0;
117 #elif defined(__GNUC__)
118 int ECX;
119 __asm__( "cpuid"
120 : "=c"(ECX)
121 : "a" (1)
122 : "ebx", "edx" );
123 result = (ECX & avx_mask);
124 #endif
125 return result;
126 }
127 #endif // __AVX__ etc
128
129 #if (defined(__SSE__) || defined(_M_IX86_FP) || defined(_M_X64)) && !defined(__sun)
130 #include <xmmintrin.h>
131 #define HAVE_m128 1
132 using ClassWithSSE = ClassWithVectorType<__m128>;
133 #endif
134
135 #if __TBB_GCC_WARNING_IGNORED_ATTRIBUTES_PRESENT
136 #pragma GCC diagnostic pop
137 #endif
138
139 #if (_MSC_VER>=1600)
140 #pragma warning (pop)
141 #endif
142 #endif // __TBB_test_common_vector_types_H_
143