xref: /oneTBB/test/common/vector_types.h (revision 478de5b1)
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