algebramix_doc 0.3
|
00001 00002 /****************************************************************************** 00003 * MODULE : vector_sse.hpp 00004 * DESCRIPTION: SSE instructions support for aligned vectors 00005 * COPYRIGHT : (C) 2008 Joris van der Hoeven and Gregoire Lecerf 00006 ******************************************************************************* 00007 * This software falls under the GNU general public license and comes WITHOUT 00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details. 00009 * If you don't have this file, write to the Free Software Foundation, Inc., 00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00011 ******************************************************************************/ 00012 00013 #ifndef __MMX__VECTOR_SSE__HPP 00014 #define __MMX__VECTOR_SSE__HPP 00015 00016 #include <basix/operators.hpp> 00017 #include <basix/double.hpp> 00018 #include <numerix/sse.hpp> 00019 #include <algebramix/algebramix-config.hpp> 00020 #include <algebramix/vector_aligned.hpp> 00021 00022 #ifndef NUMERIX_ENABLE_SIMD 00023 #undef ALGEBRAMIX_ENABLE_SIMD 00024 #endif 00025 00026 namespace mmx { 00027 #ifdef ALGEBRAMIX_ENABLE_SIMD 00028 00029 /****************************************************************************** 00030 * SSE features helpers 00031 ******************************************************************************/ 00032 00033 // According to basix/fast_new.hpp, any allocation of size 00034 // being a multiple of 16 bytes is aligned. 00035 00036 #ifdef __SSE2__ 00037 00038 template<typename Op, typename C> 00039 struct sse_has_helper { static const bool value= false;}; 00040 00041 template<typename C> 00042 struct sse_has_helper<id_op, C> {static const bool value= true;}; 00043 00044 STMPL 00045 struct sse_has_helper<equal_op, double> {static const bool value= true;}; 00046 STMPL 00047 struct sse_has_helper<equal_op, int8_t> {static const bool value= true;}; 00048 STMPL 00049 struct sse_has_helper<equal_op, uint8_t> {static const bool value= true;}; 00050 STMPL 00051 struct sse_has_helper<equal_op, int16_t> {static const bool value= true;}; 00052 STMPL 00053 struct sse_has_helper<equal_op, uint16_t> {static const bool value= true;}; 00054 STMPL 00055 struct sse_has_helper<equal_op, int32_t> {static const bool value= true;}; 00056 STMPL 00057 struct sse_has_helper<equal_op, uint32_t> {static const bool value= true;}; 00058 STMPL 00059 struct sse_has_helper<equal_op, int64_t> {static const bool value= true;}; 00060 STMPL 00061 struct sse_has_helper<equal_op, uint64_t> {static const bool value= true;}; 00062 00063 template<typename C> 00064 struct sse_has_helper<neg_op, C> {static const bool value= true;}; 00065 00066 template<typename C> 00067 struct sse_has_helper<add_op, C> {static const bool value= true;}; 00068 00069 template<typename C> 00070 struct sse_has_helper<sub_op, C> {static const bool value= true;}; 00071 00072 STMPL 00073 struct sse_has_helper<mul_op, double> {static const bool value= true;}; 00074 STMPL 00075 struct sse_has_helper<mul_op, int8_t> {static const bool value= true;}; 00076 STMPL 00077 struct sse_has_helper<mul_op, uint8_t> {static const bool value= true;}; 00078 STMPL 00079 struct sse_has_helper<mul_op, int16_t> {static const bool value= true;}; 00080 STMPL 00081 struct sse_has_helper<mul_op, uint16_t> {static const bool value= true;}; 00082 00083 template<typename C> 00084 struct sse_has_helper<lmul_op, C> { 00085 static const bool value= sse_has_helper<mul_op,C>::value; }; 00086 00087 template<typename C> 00088 struct sse_has_helper<rmul_op, C> { 00089 static const bool value= sse_has_helper<mul_op,C>::value; }; 00090 00091 STMPL 00092 struct sse_has_helper<div_op, double> {static const bool value= true;}; 00093 00094 template<typename C> 00095 struct sse_has_helper<ldiv_op, C> { 00096 static const bool value= sse_has_helper<div_op,C>::value; }; 00097 00098 template<typename C> 00099 struct sse_has_helper<rdiv_op, C> { 00100 static const bool value= sse_has_helper<div_op,C>::value; }; 00101 00102 template<typename C> 00103 struct sse_has_helper<mul_add_op, C> { 00104 static const bool value= sse_has_helper<add_op,C>::value && 00105 sse_has_helper<mul_op,C>::value; }; 00106 00107 STMPL 00108 struct sse_has_helper<min_op, uint8_t> {static const bool value= true;}; 00109 STMPL 00110 struct sse_has_helper<min_op, int16_t> {static const bool value= true;}; 00111 00112 STMPL 00113 struct sse_has_helper<max_op, uint8_t> {static const bool value= true;}; 00114 STMPL 00115 struct sse_has_helper<max_op, int16_t> {static const bool value= true;}; 00116 00117 /****************************************************************************** 00118 * SSE support for aligned vectors 00119 ******************************************************************************/ 00120 00121 // Unary 00122 template<bool b, typename V, typename W, typename Op, typename C> 00123 struct vec_unary_simd_helper { 00124 typedef implementation<vector_abstractions,V> Vec; 00125 static inline void op (C* dest, const C* s, nat n) { 00126 Vec::template vec_unary<Op, C, C> (dest, s, n); } 00127 }; 00128 00129 template<typename V, typename W, typename Op, typename C> 00130 struct vec_unary_simd_helper <true,V,W,Op,C> { 00131 static inline void op (C* dest, const C* s, nat n) { 00132 typedef typename Simd_type (C) simd_C; 00133 typedef implementation<vector_abstractions,W> SVec; 00134 static const nat m= Simd_size (C); 00135 SVec::template vec_unary<Op, simd_C, simd_C> 00136 ((simd_C*) dest, (simd_C*) s, n / m); } 00137 }; 00138 00139 template<typename V, typename W, typename Op, typename C> 00140 struct vec_unary_aligned_helper <V,W,Op,C,C> : 00141 vec_unary_simd_helper <sse_has_helper<Op, C>::value,V,W,Op,C> {}; 00142 00143 // Binary 00144 template<bool b, typename V, typename W, typename Op, typename C> 00145 struct vec_binary_simd_helper { 00146 static inline void op (C* dest, const C* s1, const C* s2, nat n) { 00147 typedef implementation<vector_abstractions,V> Vec; 00148 Vec::template vec_binary<Op, C, C, C> (dest, s1, s2, n); } 00149 }; 00150 00151 template<typename V, typename W, typename Op, typename C> 00152 struct vec_binary_simd_helper <true,V,W,Op,C> { 00153 static inline void op (C* dest, const C* s1, const C* s2, nat n) { 00154 typedef typename Simd_type (C) simd_C; 00155 typedef implementation<vector_abstractions,W> SVec; 00156 static const nat m= Simd_size (C); 00157 SVec::template vec_binary<Op, simd_C, simd_C, simd_C> 00158 ((simd_C*) dest, (simd_C*) s1, (simd_C*) s2, n / m); } 00159 }; 00160 00161 template<typename V, typename W,typename Op, typename C> 00162 struct vec_binary_aligned_helper <V,W,Op,C,C,C> : 00163 vec_binary_simd_helper <sse_has_helper<Op, C>::value,V,W,Op,C> {}; 00164 00165 // Binary scalar 00166 template<bool b, typename V, typename W, typename Op, typename C> 00167 struct vec_binary_scalar_simd_helper { 00168 static inline void op (C* dest, const C* s, const C& x, nat n) { 00169 typedef implementation<vector_abstractions,V> Vec; 00170 Vec::template vec_binary_scalar<Op, C, C, C > (dest, s, x, n); } 00171 }; 00172 00173 template<typename V, typename W, typename Op, typename C> 00174 struct vec_binary_scalar_simd_helper <true,V,W,Op,C> { 00175 static inline void op (C* dest, const C* s, const C& x, nat n) { 00176 typedef typename Simd_type (C) simd_C; 00177 typedef implementation<vector_abstractions,W> SVec; 00178 static const nat m= Simd_size (C); 00179 simd_C vx= simd_set_duplicate (x); 00180 SVec::template vec_binary_scalar<Op, simd_C, simd_C, simd_C > 00181 ((simd_C*) dest, (simd_C*) s, vx, n / m); } 00182 }; 00183 00184 template<typename V, typename W, typename Op, typename C> 00185 struct vec_binary_scalar_aligned_helper <V,W,Op,C,C,C> : 00186 vec_binary_scalar_simd_helper <sse_has_helper<Op, C>::value,V,W,Op,C> {}; 00187 00188 #if 0 00189 // problem with neutral on simd types. FIXME 00190 template<typename V, typename W, typename C> 00191 struct vec_binary_big_aligned_helper<V,W,mul_add_op,C,C> { 00192 static inline C op (const C* s1, const C* s2, nat n) { 00193 typedef typename Simd_type (C) simd_C; 00194 typedef implementation<vector_abstractions,V> Vec; 00195 typedef implementation<vector_abstractions,W> SVec; 00196 static const nat m= Simd_size (C); 00197 if (sse_has_helper<mul_add_op, C>::value && m > 1) { 00198 simd_C vr= SVec::template vec_binary_big<mul_add_op, simd_C, simd_C> 00199 ((simd_C*) s1, (simd_C*) s2, n / m); 00200 return simd_big_add<C> (vr); 00201 } 00202 else 00203 return Vec::template vec_binary_big<mul_add_op, C, C> (s1, s2, n); } 00204 }; 00205 #endif 00206 #endif // __SSE2__ 00207 #endif // ALGEBRAMIX_ENABLE_SIMD 00208 } // namespace mmx 00209 00210 #endif // __MMX__VECTOR_SSE__HPP