DPC++ Runtime
Runtime libraries for oneAPI DPC++
host_helper_macros.hpp
Go to the documentation of this file.
1 //==-- host_helper_macros.hpp -- Utility macros to implement sycl builtins -==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #pragma once
10 
11 #define FOR_VEC_1_16(MACRO, ...) \
12  MACRO(__VA_ARGS__, 1) \
13  MACRO(__VA_ARGS__, 2) \
14  MACRO(__VA_ARGS__, 3) \
15  MACRO(__VA_ARGS__, 4) \
16  MACRO(__VA_ARGS__, 8) \
17  MACRO(__VA_ARGS__, 16)
18 
19 #define FOR_VEC_2_4(MACRO, ...) \
20  MACRO(__VA_ARGS__, 2) \
21  MACRO(__VA_ARGS__, 3) \
22  MACRO(__VA_ARGS__, 4)
23 
24 #define FOR_VEC_3_4(MACRO, ...) \
25  MACRO(__VA_ARGS__, 3) \
26  MACRO(__VA_ARGS__, 4)
27 
28 // For both macros below NS is the namespace of the original sycl builtin
29 // function (e.g., sycl::cos vs native::cos). Headers implementation uses
30 // something like
31 //
32 // float sin(float x) {
33 // extern __sin_impl(float);
34 // return __sin_impl(x);
35 // }
36 //
37 // and that "extern" declaration isn't automatically matched against the symbol
38 // we export. As such, verify the return type consistency using static_assert.
39 #define EXPORT_SCALAR_NS(NUM_ARGS, NAME, NS, TYPE) \
40  __SYCL_EXPORT auto __##NAME##_impl(NUM_ARGS##_TYPE_ARG(TYPE)) \
41  -> decltype(NAME##_host_impl(NUM_ARGS##_ARG)) { \
42  static_assert(std::is_same_v<decltype(NAME##_host_impl(NUM_ARGS##_ARG)), \
43  decltype(NS::NAME(NUM_ARGS##_ARG))>); \
44  return NAME##_host_impl(NUM_ARGS##_ARG); \
45  }
46 #define EXPORT_VEC_NS(NUM_ARGS, NAME, NS, TYPE, VL) \
47  __SYCL_EXPORT auto __##NAME##_impl(NUM_ARGS##_VEC_TYPE_ARG(TYPE, VL)) \
48  -> decltype(NAME##_host_impl(NUM_ARGS##_ARG)) { \
49  static_assert(std::is_same_v<decltype(NAME##_host_impl(NUM_ARGS##_ARG)), \
50  decltype(NS::NAME(NUM_ARGS##_ARG))>); \
51  return NAME##_host_impl(NUM_ARGS##_ARG); \
52  }
53 
54 #define EXPORT_SCALAR(NUM_ARGS, NAME, TYPE) \
55  EXPORT_SCALAR_NS(NUM_ARGS, NAME, sycl, TYPE)
56 #define EXPORT_VEC(NUM_ARGS, NAME, TYPE, VL) \
57  EXPORT_VEC_NS(NUM_ARGS, NAME, sycl, TYPE, VL)
58 
59 #define EXPORT_VEC_1_16_IMPL(NUM_ARGS, NAME, NS, TYPE) \
60  FOR_VEC_1_16(EXPORT_VEC_NS, NUM_ARGS, NAME, NS, TYPE)
61 
62 #define EXPORT_SCALAR_AND_VEC_1_16_IMPL(NUM_ARGS, NAME, NS, TYPE) \
63  EXPORT_SCALAR_NS(NUM_ARGS, NAME, NS, TYPE) \
64  FOR_VEC_1_16(EXPORT_VEC_NS, NUM_ARGS, NAME, NS, TYPE)
65 
66 #define EXPORT_SCALAR_AND_VEC_2_4_IMPL(NUM_ARGS, NAME, TYPE) \
67  EXPORT_SCALAR(NUM_ARGS, NAME, TYPE) \
68  FOR_VEC_2_4(EXPORT_VEC, NUM_ARGS, NAME, TYPE)
69 
70 #define EXPORT_VEC_3_4_IMPL(NUM_ARGS, NAME, TYPE) \
71  FOR_VEC_3_4(EXPORT_VEC, NUM_ARGS, NAME, TYPE)
72 
73 #define EXPORT_SCALAR_AND_VEC_1_16_NS(NUM_ARGS, NAME, NS, ...) \
74  FOR_EACH3(EXPORT_SCALAR_AND_VEC_1_16_IMPL, NUM_ARGS, NAME, NS, __VA_ARGS__)
75 #define EXPORT_VEC_1_16_NS(NUM_ARGS, NAME, NS, ...) \
76  FOR_EACH3(EXPORT_VEC_1_16_IMPL, NUM_ARGS, NAME, NS, __VA_ARGS__)
77 #define EXPORT_SCALAR_AND_VEC_1_16(NUM_ARGS, NAME, ...) \
78  EXPORT_SCALAR_AND_VEC_1_16_NS(NUM_ARGS, NAME, sycl, __VA_ARGS__)
79 #define EXPORT_VEC_1_16(NUM_ARGS, NAME, ...) \
80  EXPORT_VEC_1_16_NS(NUM_ARGS, NAME, sycl, __VA_ARGS__)
81 
82 #define EXPORT_SCALAR_AND_VEC_2_4(NUM_ARGS, NAME, ...) \
83  FOR_EACH2(EXPORT_SCALAR_AND_VEC_2_4_IMPL, NUM_ARGS, NAME, __VA_ARGS__)
84 #define EXPORT_VEC_3_4(NUM_ARGS, NAME, ...) \
85  FOR_EACH2(EXPORT_VEC_3_4_IMPL, NUM_ARGS, NAME, __VA_ARGS__)
86 
87 #define HOST_IMPL(NAME, ...) \
88  template <typename... Ts> static auto NAME##_host_impl(Ts... xs) { \
89  using namespace detail; \
90  if constexpr ((... || is_vec_v<Ts>)) { \
91  using ret_elem_type = decltype(NAME##_host_impl(xs[0]...)); \
92  using T = typename first_type<Ts...>::type; \
93  vec<ret_elem_type, T::size()> r{}; \
94  loop<T::size()>( \
95  [&](auto idx) { r[idx] = NAME##_host_impl(xs[idx]...); }); \
96  return r; \
97  } else { \
98  return __VA_ARGS__(xs...); \
99  } \
100  }