isa.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. // Copyright 2009-2020 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "../../common/sys/platform.h"
  5. #include "../../common/sys/sysinfo.h"
  6. namespace embree
  7. {
  8. #define DEFINE_SYMBOL2(type,name) \
  9. typedef type (*name##Func)(); \
  10. name##Func name;
  11. #define DECLARE_SYMBOL2(type,name) \
  12. namespace sse2 { extern type name(); } \
  13. namespace sse42 { extern type name(); } \
  14. namespace avx { extern type name(); } \
  15. namespace avx2 { extern type name(); } \
  16. namespace avx512knl { extern type name(); } \
  17. namespace avx512skx { extern type name(); } \
  18. void name##_error2() { throw_RTCError(RTC_ERROR_UNKNOWN,"internal error in ISA selection for " TOSTRING(name)); } \
  19. type name##_error() { return type(name##_error2); } \
  20. type name##_zero() { return type(nullptr); }
  21. #define DECLARE_ISA_FUNCTION(type,symbol,args) \
  22. namespace sse2 { extern type symbol(args); } \
  23. namespace sse42 { extern type symbol(args); } \
  24. namespace avx { extern type symbol(args); } \
  25. namespace avx2 { extern type symbol(args); } \
  26. namespace avx512knl { extern type symbol(args); } \
  27. namespace avx512skx { extern type symbol(args); } \
  28. inline type symbol##_error(args) { throw_RTCError(RTC_ERROR_UNSUPPORTED_CPU,"function " TOSTRING(symbol) " not supported by your CPU"); } \
  29. typedef type (*symbol##Ty)(args); \
  30. #define DEFINE_ISA_FUNCTION(type,symbol,args) \
  31. typedef type (*symbol##Func)(args); \
  32. symbol##Func symbol;
  33. #define ZERO_SYMBOL(features,intersector) \
  34. intersector = intersector##_zero;
  35. #define INIT_SYMBOL(features,intersector) \
  36. intersector = decltype(intersector)(intersector##_error);
  37. #define SELECT_SYMBOL_DEFAULT(features,intersector) \
  38. intersector = isa::intersector;
  39. #if defined(__SSE__) || defined(__ARM_NEON)
  40. #if !defined(EMBREE_TARGET_SIMD4)
  41. #define EMBREE_TARGET_SIMD4
  42. #endif
  43. #endif
  44. #if defined(EMBREE_TARGET_SSE42)
  45. #define SELECT_SYMBOL_SSE42(features,intersector) \
  46. if ((features & SSE42) == SSE42) intersector = sse42::intersector;
  47. #else
  48. #define SELECT_SYMBOL_SSE42(features,intersector)
  49. #endif
  50. #if defined(EMBREE_TARGET_AVX) || defined(__AVX__)
  51. #if !defined(EMBREE_TARGET_SIMD8)
  52. #define EMBREE_TARGET_SIMD8
  53. #endif
  54. #if defined(__AVX__) // if default ISA is >= AVX we treat AVX target as default target
  55. #define SELECT_SYMBOL_AVX(features,intersector) \
  56. if ((features & ISA) == ISA) intersector = isa::intersector;
  57. #else
  58. #define SELECT_SYMBOL_AVX(features,intersector) \
  59. if ((features & AVX) == AVX) intersector = avx::intersector;
  60. #endif
  61. #else
  62. #define SELECT_SYMBOL_AVX(features,intersector)
  63. #endif
  64. #if defined(EMBREE_TARGET_AVX2)
  65. #if !defined(EMBREE_TARGET_SIMD8)
  66. #define EMBREE_TARGET_SIMD8
  67. #endif
  68. #define SELECT_SYMBOL_AVX2(features,intersector) \
  69. if ((features & AVX2) == AVX2) intersector = avx2::intersector;
  70. #else
  71. #define SELECT_SYMBOL_AVX2(features,intersector)
  72. #endif
  73. #if defined(EMBREE_TARGET_AVX512KNL)
  74. #if !defined(EMBREE_TARGET_SIMD16)
  75. #define EMBREE_TARGET_SIMD16
  76. #endif
  77. #define SELECT_SYMBOL_AVX512KNL(features,intersector) \
  78. if ((features & AVX512KNL) == AVX512KNL) intersector = avx512knl::intersector;
  79. #else
  80. #define SELECT_SYMBOL_AVX512KNL(features,intersector)
  81. #endif
  82. #if defined(EMBREE_TARGET_AVX512SKX)
  83. #if !defined(EMBREE_TARGET_SIMD16)
  84. #define EMBREE_TARGET_SIMD16
  85. #endif
  86. #define SELECT_SYMBOL_AVX512SKX(features,intersector) \
  87. if ((features & AVX512SKX) == AVX512SKX) intersector = avx512skx::intersector;
  88. #else
  89. #define SELECT_SYMBOL_AVX512SKX(features,intersector)
  90. #endif
  91. #define SELECT_SYMBOL_DEFAULT_SSE42(features,intersector) \
  92. SELECT_SYMBOL_DEFAULT(features,intersector); \
  93. SELECT_SYMBOL_SSE42(features,intersector);
  94. #define SELECT_SYMBOL_DEFAULT_SSE42_AVX(features,intersector) \
  95. SELECT_SYMBOL_DEFAULT(features,intersector); \
  96. SELECT_SYMBOL_SSE42(features,intersector); \
  97. SELECT_SYMBOL_AVX(features,intersector);
  98. #define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2(features,intersector) \
  99. SELECT_SYMBOL_DEFAULT(features,intersector); \
  100. SELECT_SYMBOL_SSE42(features,intersector); \
  101. SELECT_SYMBOL_AVX(features,intersector); \
  102. SELECT_SYMBOL_AVX2(features,intersector);
  103. #define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX512SKX(features,intersector) \
  104. SELECT_SYMBOL_DEFAULT(features,intersector); \
  105. SELECT_SYMBOL_SSE42(features,intersector); \
  106. SELECT_SYMBOL_AVX(features,intersector); \
  107. SELECT_SYMBOL_AVX512SKX(features,intersector);
  108. #define SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \
  109. SELECT_SYMBOL_DEFAULT(features,intersector); \
  110. SELECT_SYMBOL_AVX(features,intersector); \
  111. SELECT_SYMBOL_AVX2(features,intersector); \
  112. SELECT_SYMBOL_AVX512KNL(features,intersector); \
  113. SELECT_SYMBOL_AVX512SKX(features,intersector);
  114. #define SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512SKX(features,intersector) \
  115. SELECT_SYMBOL_DEFAULT(features,intersector); \
  116. SELECT_SYMBOL_AVX(features,intersector); \
  117. SELECT_SYMBOL_AVX2(features,intersector); \
  118. SELECT_SYMBOL_AVX512SKX(features,intersector);
  119. #define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \
  120. SELECT_SYMBOL_DEFAULT(features,intersector); \
  121. SELECT_SYMBOL_SSE42(features,intersector); \
  122. SELECT_SYMBOL_AVX(features,intersector); \
  123. SELECT_SYMBOL_AVX2(features,intersector); \
  124. SELECT_SYMBOL_AVX512KNL(features,intersector); \
  125. SELECT_SYMBOL_AVX512SKX(features,intersector);
  126. #define SELECT_SYMBOL_DEFAULT_SSE42_AVX_AVX2_AVX512SKX(features,intersector) \
  127. SELECT_SYMBOL_DEFAULT(features,intersector); \
  128. SELECT_SYMBOL_SSE42(features,intersector); \
  129. SELECT_SYMBOL_AVX(features,intersector); \
  130. SELECT_SYMBOL_AVX2(features,intersector); \
  131. SELECT_SYMBOL_AVX512SKX(features,intersector);
  132. #define SELECT_SYMBOL_DEFAULT_AVX(features,intersector) \
  133. SELECT_SYMBOL_DEFAULT(features,intersector); \
  134. SELECT_SYMBOL_AVX(features,intersector);
  135. #define SELECT_SYMBOL_DEFAULT_AVX_AVX2(features,intersector) \
  136. SELECT_SYMBOL_DEFAULT(features,intersector); \
  137. SELECT_SYMBOL_AVX(features,intersector); \
  138. SELECT_SYMBOL_AVX2(features,intersector);
  139. #define SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL(features,intersector) \
  140. SELECT_SYMBOL_DEFAULT(features,intersector); \
  141. SELECT_SYMBOL_AVX(features,intersector); \
  142. SELECT_SYMBOL_AVX512KNL(features,intersector);
  143. #define SELECT_SYMBOL_DEFAULT_AVX_AVX512KNL_AVX512SKX(features,intersector) \
  144. SELECT_SYMBOL_DEFAULT(features,intersector); \
  145. SELECT_SYMBOL_AVX(features,intersector); \
  146. SELECT_SYMBOL_AVX512KNL(features,intersector); \
  147. SELECT_SYMBOL_AVX512SKX(features,intersector);
  148. #define SELECT_SYMBOL_DEFAULT_AVX_AVX512SKX(features,intersector) \
  149. SELECT_SYMBOL_DEFAULT(features,intersector); \
  150. SELECT_SYMBOL_AVX(features,intersector); \
  151. SELECT_SYMBOL_AVX512SKX(features,intersector);
  152. #define SELECT_SYMBOL_INIT_AVX(features,intersector) \
  153. INIT_SYMBOL(features,intersector); \
  154. SELECT_SYMBOL_AVX(features,intersector);
  155. #define SELECT_SYMBOL_INIT_AVX_AVX2(features,intersector) \
  156. INIT_SYMBOL(features,intersector); \
  157. SELECT_SYMBOL_AVX(features,intersector); \
  158. SELECT_SYMBOL_AVX2(features,intersector);
  159. #define SELECT_SYMBOL_INIT_AVX_AVX2_AVX512SKX(features,intersector) \
  160. INIT_SYMBOL(features,intersector); \
  161. SELECT_SYMBOL_AVX(features,intersector); \
  162. SELECT_SYMBOL_AVX2(features,intersector); \
  163. SELECT_SYMBOL_AVX512SKX(features,intersector);
  164. #define SELECT_SYMBOL_INIT_SSE42_AVX_AVX2(features,intersector) \
  165. INIT_SYMBOL(features,intersector); \
  166. SELECT_SYMBOL_SSE42(features,intersector); \
  167. SELECT_SYMBOL_AVX(features,intersector); \
  168. SELECT_SYMBOL_AVX2(features,intersector);
  169. #define SELECT_SYMBOL_INIT_AVX_AVX512KNL(features,intersector) \
  170. INIT_SYMBOL(features,intersector); \
  171. SELECT_SYMBOL_AVX(features,intersector); \
  172. SELECT_SYMBOL_AVX512KNL(features,intersector);
  173. #define SELECT_SYMBOL_INIT_AVX_AVX512KNL_AVX512SKX(features,intersector) \
  174. INIT_SYMBOL(features,intersector); \
  175. SELECT_SYMBOL_AVX(features,intersector); \
  176. SELECT_SYMBOL_AVX512KNL(features,intersector); \
  177. SELECT_SYMBOL_AVX512SKX(features,intersector);
  178. #define SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL(features,intersector) \
  179. INIT_SYMBOL(features,intersector); \
  180. SELECT_SYMBOL_AVX(features,intersector); \
  181. SELECT_SYMBOL_AVX2(features,intersector); \
  182. SELECT_SYMBOL_AVX512KNL(features,intersector);
  183. #define SELECT_SYMBOL_INIT_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \
  184. INIT_SYMBOL(features,intersector); \
  185. SELECT_SYMBOL_AVX(features,intersector); \
  186. SELECT_SYMBOL_AVX2(features,intersector); \
  187. SELECT_SYMBOL_AVX512KNL(features,intersector); \
  188. SELECT_SYMBOL_AVX512SKX(features,intersector);
  189. #define SELECT_SYMBOL_INIT_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \
  190. INIT_SYMBOL(features,intersector); \
  191. SELECT_SYMBOL_SSE42(features,intersector); \
  192. SELECT_SYMBOL_AVX(features,intersector); \
  193. SELECT_SYMBOL_AVX2(features,intersector); \
  194. SELECT_SYMBOL_AVX512KNL(features,intersector); \
  195. SELECT_SYMBOL_AVX512SKX(features,intersector);
  196. #define SELECT_SYMBOL_ZERO_SSE42_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \
  197. ZERO_SYMBOL(features,intersector); \
  198. SELECT_SYMBOL_SSE42(features,intersector); \
  199. SELECT_SYMBOL_AVX(features,intersector); \
  200. SELECT_SYMBOL_AVX2(features,intersector); \
  201. SELECT_SYMBOL_AVX512KNL(features,intersector); \
  202. SELECT_SYMBOL_AVX512SKX(features,intersector);
  203. #define SELECT_SYMBOL_DEFAULT_AVX_AVX2_AVX512KNL_AVX512SKX(features,intersector) \
  204. SELECT_SYMBOL_DEFAULT(features,intersector); \
  205. SELECT_SYMBOL_AVX(features,intersector); \
  206. SELECT_SYMBOL_AVX2(features,intersector); \
  207. SELECT_SYMBOL_AVX512KNL(features,intersector); \
  208. SELECT_SYMBOL_AVX512SKX(features,intersector);
  209. #define SELECT_SYMBOL_INIT_AVX512KNL_AVX512SKX(features,intersector) \
  210. INIT_SYMBOL(features,intersector); \
  211. SELECT_SYMBOL_AVX512KNL(features,intersector); \
  212. SELECT_SYMBOL_AVX512SKX(features,intersector);
  213. #define SELECT_SYMBOL_SSE42_AVX_AVX2(features,intersector) \
  214. SELECT_SYMBOL_SSE42(features,intersector); \
  215. SELECT_SYMBOL_AVX(features,intersector); \
  216. SELECT_SYMBOL_AVX2(features,intersector);
  217. struct VerifyMultiTargetLinking {
  218. static __noinline int getISA(int depth = 5) {
  219. if (depth == 0) return ISA;
  220. else return getISA(depth-1);
  221. }
  222. };
  223. namespace sse2 { int getISA(); };
  224. namespace sse42 { int getISA(); };
  225. namespace avx { int getISA(); };
  226. namespace avx2 { int getISA(); };
  227. namespace avx512knl { int getISA(); };
  228. namespace avx512skx { int getISA(); };
  229. }