Skip to content

Commit 1a5e532

Browse files
authored
[SYCL][ESIMD] Add new raw_send APIs moving compile time params to template params (#10167)
The arguments moved from runtime params to template params need to be compile time constant. Often they end up as compile time constant after constant folding, but not in all cases such as -O0, and if they are not constant it will lead to an IGC error. Add new APIs to enforce this requirement. I also updated three LSC APIs to use the new version, but these were already passing in constexpr arguments. --------- Signed-off-by: Sarnie, Nick <[email protected]>
1 parent c9da5c7 commit 1a5e532

File tree

3 files changed

+179
-10
lines changed

3 files changed

+179
-10
lines changed

sycl/include/sycl/ext/intel/experimental/esimd/memory.hpp

Lines changed: 151 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,50 @@ raw_sends(__ESIMD_NS::simd<T1, n1> msgDst, __ESIMD_NS::simd<T2, n2> msgSrc0,
8888
msgDesc, msgSrc0.data(), msgSrc1.data(), msgDst.data());
8989
}
9090

91+
/// Raw sends. "s" suffix designates "split" variant - i.e. two sources.
92+
///
93+
/// @tparam execSize is the execution size.
94+
/// @tparam sfid is the shared function ID.
95+
/// @tparam numSrc0 is the number of GRFs for source-0.
96+
/// @tparam numSrc1 is the number of GRFs for source-1.
97+
/// @tparam numDst is the number of GRFs for destination.
98+
/// @tparam isEOT is the flag that indicates whether this is an EOT message
99+
/// (optional - default to 0).
100+
/// @tparam isSendc is the flag that indicates whether sendc should be used
101+
/// (optional - default to 0).
102+
/// @param msgDst is the old value of the destination operand.
103+
/// @param msgSrc0 is the first source operand of send message.
104+
/// @param msgSrc1 is the second source operand of send message.
105+
/// @param exDesc is the extended message descriptor.
106+
/// @param msgDesc is the message descriptor.
107+
/// @param mask is the predicate to specify enabled channels (optional - default
108+
/// to on).
109+
/// @return the vector value read from memory.
110+
template <uint8_t execSize, uint8_t sfid, uint8_t numSrc0, uint8_t numSrc1,
111+
uint8_t numDst, uint8_t isEOT = 0, uint8_t isSendc = 0, typename T1,
112+
int n1, typename T2, int n2, typename T3, int n3, int N = 16>
113+
__ESIMD_API __ESIMD_NS::simd<T1, n1>
114+
raw_sends(__ESIMD_NS::simd<T1, n1> msgDst, __ESIMD_NS::simd<T2, n2> msgSrc0,
115+
__ESIMD_NS::simd<T3, n3> msgSrc1, uint32_t exDesc, uint32_t msgDesc,
116+
__ESIMD_NS::simd_mask<N> mask = 1) {
117+
constexpr unsigned _Width1 = n1 * sizeof(T1);
118+
static_assert(_Width1 % 32 == 0, "Invalid size for raw send rspVar");
119+
constexpr unsigned _Width2 = n2 * sizeof(T2);
120+
static_assert(_Width2 % 32 == 0, "Invalid size for raw send msgSrc0");
121+
constexpr unsigned _Width3 = n3 * sizeof(T3);
122+
static_assert(_Width3 % 32 == 0, "Invalid size for raw send msgSrc1");
123+
124+
using ElemT1 = __ESIMD_DNS::__raw_t<T1>;
125+
using ElemT2 = __ESIMD_DNS::__raw_t<T2>;
126+
using ElemT3 = __ESIMD_DNS::__raw_t<T3>;
127+
128+
constexpr uint8_t modifier = ((isEOT & 0x1) << 1) | (isSendc & 0x1);
129+
130+
return __esimd_raw_sends2<ElemT1, n1, ElemT2, n2, ElemT3, n3, N>(
131+
modifier, execSize, mask.data(), numSrc0, numSrc1, numDst, sfid, exDesc,
132+
msgDesc, msgSrc0.data(), msgSrc1.data(), msgDst.data());
133+
}
134+
91135
/// Raw send.
92136
///
93137
/// @param msgDst is the old value of the destination operand.
@@ -129,6 +173,43 @@ raw_send(__ESIMD_NS::simd<T1, n1> msgDst, __ESIMD_NS::simd<T2, n2> msgSrc0,
129173
msgSrc0.data(), msgDst.data());
130174
}
131175

176+
/// Raw send.
177+
///
178+
/// @tparam execSize is the execution size.
179+
/// @tparam sfid is the shared function ID.
180+
/// @tparam numSrc0 is the number of GRFs for source-0.
181+
/// @tparam numDst is the number of GRFs for destination.
182+
/// @tparam isEOT is the flag that indicates whether this is an EOT message
183+
/// (optional - default to 0).
184+
/// @tparam isSendc is the flag that indicates whether sendc should be used
185+
/// (optional - default to 0).
186+
/// @param msgDst is the old value of the destination operand.
187+
/// @param msgSrc0 is the first source operand of send message.
188+
/// @param exDesc is the extended message descriptor.
189+
/// @param msgDesc is the message descriptor.
190+
/// @param mask is the predicate to specify enabled channels (optional - default
191+
/// to on).
192+
/// @return the vector value read from memory
193+
template <uint8_t execSize, uint8_t sfid, uint8_t numSrc0, uint8_t numDst,
194+
uint8_t isEOT = 0, uint8_t isSendc = 0, typename T1, int n1,
195+
typename T2, int n2, int N = 16>
196+
__ESIMD_API __ESIMD_NS::simd<T1, n1>
197+
raw_send(__ESIMD_NS::simd<T1, n1> msgDst, __ESIMD_NS::simd<T2, n2> msgSrc0,
198+
uint32_t exDesc, uint32_t msgDesc, __ESIMD_NS::simd_mask<N> mask = 1) {
199+
constexpr unsigned _Width1 = n1 * sizeof(T1);
200+
static_assert(_Width1 % 32 == 0, "Invalid size for raw send rspVar");
201+
constexpr unsigned _Width2 = n2 * sizeof(T2);
202+
static_assert(_Width2 % 32 == 0, "Invalid size for raw send msgSrc0");
203+
204+
using ElemT1 = __ESIMD_DNS::__raw_t<T1>;
205+
using ElemT2 = __ESIMD_DNS::__raw_t<T2>;
206+
207+
constexpr uint8_t modifier = ((isEOT & 0x1) << 1) | (isSendc & 0x1);
208+
return __esimd_raw_send2<ElemT1, n1, ElemT2, n2, N>(
209+
modifier, execSize, mask.data(), numSrc0, numDst, sfid, exDesc, msgDesc,
210+
msgSrc0.data(), msgDst.data());
211+
}
212+
132213
/// Raw sends. "s" suffix designates "split" variant - i.e. two sources.
133214
///
134215
/// @param msgSrc0 is the first source operand of send message.
@@ -169,6 +250,43 @@ raw_sends(__ESIMD_NS::simd<T1, n1> msgSrc0, __ESIMD_NS::simd<T2, n2> msgSrc1,
169250
msgSrc0.data(), msgSrc1.data());
170251
}
171252

253+
/// Raw sends. "s" suffix designates "split" variant - i.e. two sources.
254+
///
255+
/// @tparam execSize is the execution size.
256+
/// @tparam sfid is the shared function ID.
257+
/// @tparam numSrc0 is the number of GRFs for source-0.
258+
/// @tparam numSrc1 is the number of GRFs for source-1.
259+
/// @tparam isEOT is the flag that indicates whether this is an EOT message
260+
/// (optional - default to 0).
261+
/// @tparam isSendc is the flag that indicates whether sendc should be used
262+
/// (optional - default to 0).
263+
/// @param msgSrc0 is the first source operand of send message.
264+
/// @param msgSrc1 is the second source operand of send message.
265+
/// @param exDesc is the extended message descriptor.
266+
/// @param msgDesc is the message descriptor.
267+
/// @param mask is the predicate to specify enabled channels (optional - default
268+
/// to on).
269+
template <uint8_t execSize, uint8_t sfid, uint8_t numSrc0, uint8_t numSrc1,
270+
uint8_t isEOT = 0, uint8_t isSendc = 0, typename T1, int n1,
271+
typename T2, int n2, int N = 16>
272+
__ESIMD_API void raw_sends(__ESIMD_NS::simd<T1, n1> msgSrc0,
273+
__ESIMD_NS::simd<T2, n2> msgSrc1, uint32_t exDesc,
274+
uint32_t msgDesc,
275+
__ESIMD_NS::simd_mask<N> mask = 1) {
276+
constexpr unsigned _Width1 = n1 * sizeof(T1);
277+
static_assert(_Width1 % 32 == 0, "Invalid size for raw send msgSrc0");
278+
constexpr unsigned _Width2 = n2 * sizeof(T2);
279+
static_assert(_Width2 % 32 == 0, "Invalid size for raw send msgSrc1");
280+
281+
using ElemT1 = __ESIMD_DNS::__raw_t<T1>;
282+
using ElemT2 = __ESIMD_DNS::__raw_t<T2>;
283+
284+
constexpr uint8_t modifier = ((isEOT & 0x1) << 1) | (isSendc & 0x1);
285+
__esimd_raw_sends2_noresult<ElemT1, n1, ElemT2, n2, N>(
286+
modifier, execSize, mask.data(), numSrc0, numSrc1, sfid, exDesc, msgDesc,
287+
msgSrc0.data(), msgSrc1.data());
288+
}
289+
172290
/// Raw send. Generates a \c send or \c sendc instruction for the message
173291
/// gateway.
174292
///
@@ -201,6 +319,34 @@ raw_send(__ESIMD_NS::simd<T1, n1> msgSrc0, uint32_t exDesc, uint32_t msgDesc,
201319
msgSrc0.data());
202320
}
203321

322+
/// Raw send. Generates a \c send or \c sendc instruction for the message
323+
/// gateway.
324+
///
325+
/// @tparam execSize is the execution size.
326+
/// @tparam sfid is the shared function ID.
327+
/// @tparam numSrc0 is the number of GRFs for source-0.
328+
/// @tparam isEOT is the flag that indicates whether this is an EOT message
329+
/// (optional - default to 0).
330+
/// @tparam isSendc is the flag that indicates whether sendc should be used
331+
/// (optional - default to 0).
332+
/// @param msgSrc0 is the first source operand of send message.
333+
/// @param exDesc is the extended message descriptor.
334+
/// @param msgDesc is the message descriptor.
335+
/// @param mask is the predicate to specify enabled channels (optional - default
336+
/// to on).
337+
template <uint8_t execSize, uint8_t sfid, uint8_t numSrc0, uint8_t isEOT = 0,
338+
uint8_t isSendc = 0, typename T1, int n1, int N = 16>
339+
__ESIMD_API void raw_send(__ESIMD_NS::simd<T1, n1> msgSrc0, uint32_t exDesc,
340+
uint32_t msgDesc, __ESIMD_NS::simd_mask<N> mask = 1) {
341+
constexpr unsigned _Width1 = n1 * sizeof(T1);
342+
static_assert(_Width1 % 32 == 0, "Invalid size for raw send msgSrc0");
343+
using ElemT1 = __ESIMD_DNS::__raw_t<T1>;
344+
constexpr uint8_t modifier = ((isEOT & 0x1) << 1) | (isSendc & 0x1);
345+
__esimd_raw_send2_noresult<ElemT1, n1, N>(modifier, execSize, mask.data(),
346+
numSrc0, sfid, exDesc, msgDesc,
347+
msgSrc0.data());
348+
}
349+
204350
/// @} sycl_esimd_raw_send
205351

206352
/// @defgroup sycl_esimd_memory_nbarrier Named barrier APIs.
@@ -2729,9 +2875,8 @@ ESIMD_INLINE SYCL_ESIMD_FUNCTION __ESIMD_NS::simd<T, N> lsc_load_2d(
27292875
constexpr uint8_t sfid = 0xF;
27302876
constexpr uint8_t numSrc0 = 0x1;
27312877
constexpr uint8_t numDst = (N * sizeof(T)) / 64;
2732-
__ESIMD_NS::simd<T, ActualN> Raw =
2733-
raw_send(oldDst, payload.get_raw_data(), exDesc, desc, execSize, sfid,
2734-
numSrc0, numDst);
2878+
__ESIMD_NS::simd<T, ActualN> Raw = raw_send<execSize, numSrc0, numDst, sfid>(
2879+
oldDst, payload.get_raw_data(), exDesc, desc);
27352880

27362881
if constexpr (ActualN == N) {
27372882
return Raw;
@@ -2794,7 +2939,7 @@ ESIMD_INLINE SYCL_ESIMD_FUNCTION void lsc_prefetch_2d(
27942939
constexpr uint8_t execSize = 0x0;
27952940
constexpr uint8_t sfid = 0xF;
27962941
constexpr uint8_t numDst = (N * sizeof(T)) / 64;
2797-
raw_send(payload.get_raw_data(), exDesc, desc, execSize, sfid, numDst);
2942+
raw_send<execSize, numDst, sfid>(payload.get_raw_data(), exDesc, desc);
27982943
}
27992944

28002945
/// A variation of \c 2D stateless block store \c with parameters passed as
@@ -2834,8 +2979,8 @@ lsc_store_2d(config_2d_mem_access<T, BlockWidth, BlockHeight, NBlocks> &payload,
28342979
constexpr uint8_t numSrc0 = 0x1;
28352980
constexpr uint8_t numSrc1 = (N * sizeof(T)) / 64;
28362981

2837-
raw_sends(payload.get_raw_data(), Data, exDesc, desc, execSize, sfid, numSrc0,
2838-
numSrc1);
2982+
raw_sends<execSize, numSrc0, numSrc1, sfid>(payload.get_raw_data(), Data,
2983+
exDesc, desc);
28392984
}
28402985

28412986
/// SLM atomic.

sycl/test-e2e/ESIMD/histogram_raw_send.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
//==------------ histogram_raw_send.cpp - DPC++ ESIMD on-device test
2-
//-------==//
1+
//==-histogram_raw_send.cpp - DPC++ ESIMD on-device test-==//
32
//
43
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
54
// See https://llvm.org/LICENSE.txt for license information.
65
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
76
//
8-
//===----------------------------------------------------------------------===//
7+
//===----------------------------------------------------===//
98
// REQUIRES: gpu-intel-gen9
109
// UNSUPPORTED: gpu-intel-dg1,gpu-intel-dg2,gpu-intel-pvc
1110
// UNSUPPORTED: ze_debug
1211
// RUN: %{build} -o %t1.out
1312
// RUN: %{run} %t1.out
13+
// RUN: %{build} -DUSE_CONSTEXPR_API -o %t2.out
14+
// RUN: %{run} %t2.out
1415

1516
// The test checks raw send functionality with atomic write implementation
1617
// on SKL. It does not work on DG1 due to send instruction incompatibility.
@@ -85,9 +86,16 @@ ESIMD_INLINE void atomic_write(T *bins, simd<unsigned, n> offset,
8586
constexpr uint8_t numSrc1 = 0x1;
8687
constexpr uint8_t isEOT = 0;
8788
constexpr uint8_t isSendc = 0;
89+
90+
#ifdef USE_CONSTEXPR_API
91+
experimental::esimd::raw_sends<execSize, sfid, numSrc0, numSrc1, numDst,
92+
isEOT, isSendc>(oldDst, vAddr, src0, exDesc,
93+
desc, pred);
94+
#else
8895
experimental::esimd::raw_sends(oldDst, vAddr, src0, exDesc, desc, execSize,
8996
sfid, numSrc0, numSrc1, numDst, isEOT, isSendc,
9097
pred);
98+
#endif
9199
}
92100

93101
int main(int argc, char *argv[]) {

sycl/test-e2e/ESIMD/vadd_raw_send.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
// XFAIL: esimd_emulator
1212
// RUN: %{build} -fno-sycl-esimd-force-stateless-mem -o %t1.out
1313
// RUN: %{run} %t1.out
14-
14+
// RUN: %{build} -fno-sycl-esimd-force-stateless-mem -DUSE_CONSTEXPR_API -o %t2.out
15+
// RUN: %{run} %t2.out
1516
// The test checks raw send functionality with block read/write implementation
1617
// on SKL. It does not work on DG1 due to send instruction incompatibility.
1718

@@ -40,8 +41,13 @@ ESIMD_INLINE simd<T, N> dwaligned_block_read(AccessorTy acc,
4041
constexpr uint8_t sfid = 0x0;
4142
constexpr uint8_t numSrc0 = 0x1;
4243
constexpr uint8_t numDst = 0x2;
44+
#ifdef USE_CONSTEXPR_API
45+
return experimental::esimd::raw_send<execSize, sfid, numSrc0, numDst>(
46+
oldDst, src0, exDesc, desc);
47+
#else
4348
return experimental::esimd::raw_send(oldDst, src0, exDesc, desc, execSize,
4449
sfid, numSrc0, numDst);
50+
#endif
4551
}
4652

4753
template <typename T, int N, typename AccessorTy>
@@ -57,8 +63,13 @@ ESIMD_INLINE void block_write1(AccessorTy acc, unsigned int offset,
5763
constexpr uint8_t sfid = 0x0;
5864
constexpr uint8_t numSrc0 = 0x1;
5965
constexpr uint8_t numSrc1 = 0x1;
66+
#ifdef USE_CONSTEXPR_API
67+
return experimental::esimd::raw_sends<execSize, sfid, numSrc0, numSrc1>(
68+
src0, data, exDesc, desc);
69+
#else
6070
return experimental::esimd::raw_sends(src0, data, exDesc, desc, execSize,
6171
sfid, numSrc0, numSrc1);
72+
#endif
6273
}
6374

6475
template <typename T, int N, typename AccessorTy>
@@ -77,8 +88,13 @@ ESIMD_INLINE void block_write2(AccessorTy acc, unsigned int offset,
7788
constexpr uint8_t execSize = 0x83;
7889
constexpr uint8_t sfid = 0x0;
7990
constexpr uint8_t numSrc0 = 0x2;
91+
#ifdef USE_CONSTEXPR_API
92+
return experimental::esimd::raw_send<execSize, sfid, numSrc0>(src0, exDesc,
93+
desc);
94+
#else
8095
return experimental::esimd::raw_send(src0, exDesc, desc, execSize, sfid,
8196
numSrc0);
97+
#endif
8298
}
8399

84100
template <typename T> int test(queue q) {

0 commit comments

Comments
 (0)