Skip to content

Commit 861161a

Browse files
kbobrovsv-klochkov
andauthored
[ESIMD] Add compile-time parameter checks to lsc APIs. (#6106)
* [ESIMD] Add compile-time parameter checks to lsc APIs. Signed-off-by: Konstantin S Bobrovsky <konstantin.s.bobrovsky@intel.com> Co-authored-by: Vyacheslav Klochkov <vyacheslav.n.klochkov@intel.com>
1 parent 6dbdf92 commit 861161a

File tree

2 files changed

+115
-10
lines changed

2 files changed

+115
-10
lines changed

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

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,51 @@ __ESIMD_API void lsc_block_store(T *p, __ESIMD_NS::simd<T, NElts> vals) {
915915
vals.data());
916916
}
917917

918+
namespace detail {
919+
// Compile-time checks for lsc_load2d/store2d restrictions.
920+
template <typename T, int BlockWidth, int BlockHeight, int NBlocks,
921+
bool Transposed, bool Transformed, bool IsStore = false>
922+
constexpr void check_lsc_block_2d_restrictions() {
923+
constexpr int GRFByteSize = BlockWidth * BlockHeight * NBlocks * sizeof(T);
924+
static_assert(!IsStore || GRFByteSize <= 512,
925+
"2D store supports 512 bytes max");
926+
static_assert(IsStore || GRFByteSize <= 2048,
927+
"2D load supports 2048 bytes max");
928+
static_assert(!Transposed || !Transformed,
929+
"Transposed and transformed is not supported");
930+
if constexpr (Transposed) {
931+
static_assert(NBlocks == 1, "Transposed expected to be 1 block only");
932+
static_assert(sizeof(T) == 4 || sizeof(T) == 8,
933+
"Transposed load is supported only for data size u32 or u64");
934+
static_assert(sizeof(T) == 64 ? BlockHeight == 8
935+
: BlockHeight >= 1 && BlockHeight <= 32,
936+
"Unsupported block height");
937+
static_assert(sizeof(T) == 64 ? __ESIMD_DNS::isPowerOf2(BlockWidth, 4)
938+
: BlockWidth >= 1 && BlockWidth <= 8,
939+
"Unsupported block width");
940+
} else if constexpr (Transformed) {
941+
static_assert(sizeof(T) == 1 || sizeof(T) == 2,
942+
"VNNI transform is supported only for data size u8 or u16");
943+
static_assert(__ESIMD_DNS::isPowerOf2(NBlocks, 4),
944+
"Unsupported number of blocks");
945+
static_assert(BlockHeight * sizeof(T) >= 4 && BlockHeight <= 32,
946+
"Unsupported block height");
947+
static_assert(BlockWidth * sizeof(T) >= 4 &&
948+
BlockWidth * NBlocks * sizeof(T) <= 64,
949+
"Unsupported block width");
950+
} else {
951+
static_assert(
952+
__ESIMD_DNS::isPowerOf2(NBlocks, sizeof(T) == 1 ? 4 : 8 / sizeof(T)),
953+
"Unsupported number of blocks");
954+
static_assert(BlockHeight >= 1 && BlockHeight <= 32,
955+
"Unsupported block height");
956+
static_assert(BlockWidth * sizeof(T) >= 4 &&
957+
BlockWidth * NBlocks * sizeof(T) <= 64,
958+
"Unsupported block width");
959+
}
960+
}
961+
} // namespace detail
962+
918963
/// 2D USM pointer block load.
919964
/// Supported platforms: PVC
920965
/// VISA instruction: lsc_load_block2d.ugm
@@ -953,11 +998,9 @@ template <typename T, int BlockWidth, int BlockHeight = 1, int NBlocks = 1,
953998
__ESIMD_API __ESIMD_NS::simd<T, N>
954999
lsc_load2d(const T *Ptr, unsigned SurfaceWidth, unsigned SurfaceHeight,
9551000
unsigned SurfacePitch, int X, int Y) {
956-
static_assert(!Transposed || !Transformed,
957-
"Transposed and transformed is not supported");
958-
static_assert(!Transposed || (Transposed && NBlocks == 1),
959-
"Transposed expected to be 1 block only");
9601001
detail::check_lsc_cache_hint<detail::lsc_action::load, L1H, L3H>();
1002+
detail::check_lsc_block_2d_restrictions<T, BlockWidth, BlockHeight, NBlocks,
1003+
Transposed, Transformed>();
9611004
constexpr int ElemsPerDword = 4 / sizeof(T);
9621005
constexpr int GRFRowSize = Transposed ? BlockHeight : BlockWidth;
9631006
constexpr int GRFRowPitch = __ESIMD_DNS::getNextPowerOf2<GRFRowSize>();
@@ -971,12 +1014,6 @@ lsc_load2d(const T *Ptr, unsigned SurfaceWidth, unsigned SurfaceHeight,
9711014
"These parameters require unpadding. It is not implemented yet");
9721015
constexpr lsc_data_size DS =
9731016
detail::finalize_data_size<T, lsc_data_size::default_size>();
974-
static_assert(!Transformed ||
975-
(DS == lsc_data_size::u8 || DS == lsc_data_size::u16),
976-
"VNNI transform is supported only for data size U8 or U16");
977-
static_assert(!Transposed ||
978-
(DS == lsc_data_size::u32 || DS == lsc_data_size::u64),
979-
"Transposed load is supported only for data size u32 or u64");
9801017
__ESIMD_NS::simd_mask<N> pred = 1;
9811018
uintptr_t surf_addr = reinterpret_cast<uintptr_t>(Ptr);
9821019
constexpr detail::lsc_data_order _Transposed =
@@ -1017,6 +1054,8 @@ __ESIMD_API void lsc_prefetch2d(const T *Ptr, unsigned SurfaceWidth,
10171054
unsigned SurfaceHeight, unsigned SurfacePitch,
10181055
int X, int Y) {
10191056
detail::check_lsc_cache_hint<detail::lsc_action::prefetch, L1H, L3H>();
1057+
detail::check_lsc_block_2d_restrictions<T, BlockWidth, BlockHeight, NBlocks,
1058+
false, false>();
10201059
constexpr lsc_data_size DS =
10211060
detail::finalize_data_size<T, lsc_data_size::default_size>();
10221061
__ESIMD_NS::simd_mask<N> pred = 1;
@@ -1060,6 +1099,8 @@ __ESIMD_API void lsc_store2d(T *Ptr, unsigned SurfaceWidth,
10601099
unsigned SurfaceHeight, unsigned SurfacePitch,
10611100
int X, int Y, __ESIMD_NS::simd<T, N> Vals) {
10621101
detail::check_lsc_cache_hint<detail::lsc_action::store, L1H, L3H>();
1102+
detail::check_lsc_block_2d_restrictions<T, BlockWidth, BlockHeight, 1, false,
1103+
false, true /*IsStore*/>();
10631104
constexpr lsc_data_size DS =
10641105
detail::finalize_data_size<T, lsc_data_size::default_size>();
10651106
__ESIMD_NS::simd_mask<N> pred = 1;

sycl/test/esimd/check_lsc.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// RUN: not %clangxx -fsycl -fsycl-device-only -fsyntax-only -Wno-unused-command-line-argument %s 2>&1 | FileCheck %s --implicit-check-not="error:"
2+
// RUN: not %clangxx %fsycl-host-only -fsyntax-only -Wno-unused-command-line-argument %s 2>&1 | FileCheck %s --implicit-check-not="error:"
3+
4+
// This test checks that both host and device compilers can:
5+
// - successfully compile lsc_load2d/lsc_store2d APIs
6+
// - emit an error if some of the restrictions on template parameters are
7+
// violated
8+
9+
#include <CL/sycl.hpp>
10+
#include <limits>
11+
#include <sycl/ext/intel/esimd.hpp>
12+
#include <utility>
13+
14+
using namespace sycl::ext::intel::esimd;
15+
using namespace sycl::ext::intel::experimental::esimd;
16+
using namespace cl::sycl;
17+
18+
// --- Postive tests.
19+
20+
template <class T, int BLOCK_WIDTH, int BLOCK_HEIGHT, int NUM_BLOCKS,
21+
bool TRANSPOSE, bool TRANSFORM, cache_hint L1H, cache_hint L3H,
22+
int N = __ESIMD_EDNS::get_lsc_block_2d_data_size<
23+
T, NUM_BLOCKS, BLOCK_HEIGHT, BLOCK_WIDTH, TRANSPOSE, TRANSFORM>()>
24+
SYCL_EXTERNAL auto test_load(T *ptr, int width, int height,
25+
int pitch) SYCL_ESIMD_FUNCTION {
26+
return lsc_load2d<T, BLOCK_WIDTH, BLOCK_HEIGHT, NUM_BLOCKS, TRANSPOSE,
27+
TRANSFORM, L1H, L3H>(ptr, width * sizeof(T) - 1, height - 1,
28+
pitch * sizeof(T) - 1, 0, 0);
29+
}
30+
31+
template <class T, int BLOCK_WIDTH, int BLOCK_HEIGHT, int NUM_BLOCKS,
32+
cache_hint L1H, cache_hint L3H,
33+
int N = __ESIMD_EDNS::get_lsc_block_2d_data_size<
34+
T, NUM_BLOCKS, BLOCK_HEIGHT, BLOCK_WIDTH, false, false>()>
35+
SYCL_EXTERNAL void test_store(T *ptr, simd<T, N> v, int width, int height,
36+
int pitch) SYCL_ESIMD_FUNCTION {
37+
lsc_store2d<T, BLOCK_WIDTH, BLOCK_HEIGHT, L1H, L3H>(
38+
ptr, width * sizeof(T) - 1, height - 1, pitch * sizeof(T) - 1, 0, 0, v);
39+
}
40+
41+
// --- Positive tests.
42+
43+
template auto
44+
test_load<float, 16, 16, 1, false, false, cache_hint::none, cache_hint::none>(
45+
float *, int, int, int) SYCL_ESIMD_FUNCTION;
46+
47+
constexpr int N16_8 =
48+
__ESIMD_EDNS::get_lsc_block_2d_data_size<float, 1, 16, 8, false, false>();
49+
template void test_store<float, 8, 16, 1, cache_hint::none, cache_hint::none>(
50+
float *, simd<float, N16_8>, int, int, int) SYCL_ESIMD_FUNCTION;
51+
52+
// --- Negative tests.
53+
54+
template auto
55+
test_load<float, 32, 32, 1, false, false, cache_hint::none, cache_hint::none>(
56+
float *, int, int, int) SYCL_ESIMD_FUNCTION;
57+
// CHECK: {{.*}}error: {{.*}}2D load supports 2048 bytes max
58+
59+
constexpr int N16_16 =
60+
__ESIMD_EDNS::get_lsc_block_2d_data_size<float, 1, 16, 16, false, false>();
61+
template void test_store<float, 16, 16, 1, cache_hint::none, cache_hint::none>(
62+
float *, simd<float, N16_16>, int, int, int) SYCL_ESIMD_FUNCTION;
63+
// CHECK: {{.*}}error: {{.*}}Unsupported block width
64+
// CHECK: {{.*}}error: {{.*}}2D store supports 512 bytes max

0 commit comments

Comments
 (0)