#ifndef GPU_INTEL_INCLUDE_IO_H
#define GPU_INTEL_INCLUDE_IO_H
#include "gpu/intel/include/conversion.h"
#include "gpu/intel/include/custom_types.h"
#include "gpu/intel/include/utils.h"
#define BLOCK_READ_FUNC_0 get_half_byte
#define BLOCK_READ_FUNC_1 intel_sub_group_block_read_uc
#define BLOCK_READ_FUNC_2 intel_sub_group_block_read_us
#define BLOCK_READ_FUNC_4 intel_sub_group_block_read
#define BLOCK_READ_FUNC_8 intel_sub_group_block_read_ul
#define BLOCK_WRITE_FUNC_0 intel_sub_group_block_write_uc
#define BLOCK_WRITE_FUNC_1 intel_sub_group_block_write_uc
#define BLOCK_WRITE_FUNC_2 intel_sub_group_block_write_us
#define BLOCK_WRITE_FUNC_4 intel_sub_group_block_write
#define BLOCK_WRITE_FUNC_8 intel_sub_group_block_write_ul
#define BLOCK_DT_0 uchar
#define BLOCK_DT_1 uchar
#define BLOCK_DT_2 ushort
#define BLOCK_DT_4 uint
#define BLOCK_DT_8 ulong
#define SIZE_undef_data 1
#define SIZE_char 1
#define SIZE_uchar 1
#define SIZE_f8_e5m2 1
#define SIZE_f8_e4m3 1
#define SIZE_f4_e2m1 0
#define SIZE_f4_e3m0 0
#define SIZE_e8m0 1
#define SIZE_bf16 2
#define SIZE_half 2
#define SIZE_int 4
#define SIZE_float 4
#define SIZE_double 8
#define SIZE(dt) CONCAT2(SIZE_, dt)
#define BLOCK_DT(dt) CONCAT2(BLOCK_DT_, SIZE(dt))
#define BLOCK_READ_FUNC(dt) CONCAT2(BLOCK_READ_FUNC_, SIZE(dt))
#define BLOCK_WRITE_FUNC(dt) CONCAT2(BLOCK_WRITE_FUNC_, SIZE(dt))
#define BLOCK_DT_N(dt, n) CONCAT2(BLOCK_DT(dt), n)
#define BLOCK_READ_FUNC_N(dt, n) CONCAT2(BLOCK_READ_FUNC(dt), n)
#define BLOCK_WRITE_FUNC_N(dt, n) CONCAT2(BLOCK_WRITE_FUNC(dt), n)
#define DECLARE_AS_BLOCK(t) \
BLOCK_DT(t) __attribute__((overloadable)) as_block_data(t a) { \
return CONCAT2(as_, BLOCK_DT(t))(a); \
}
#define DECLARE_AS_STRUCT_BLOCK(t) \
BLOCK_DT(t) __attribute__((overloadable)) as_block_data(t a) { \
return CONCAT2(as_, BLOCK_DT(t))(a.data); \
}
#ifdef MATH_UTILS_DECLARE_F4_E2M1
DECLARE_AS_STRUCT_BLOCK(f4_e2m1)
#endif
#ifdef MATH_UTILS_DECLARE_F4_E3M0
DECLARE_AS_STRUCT_BLOCK(f4_e3m0)
#endif
DECLARE_AS_BLOCK(char)
DECLARE_AS_BLOCK(uchar)
DECLARE_AS_STRUCT_BLOCK(f8_e5m2)
DECLARE_AS_STRUCT_BLOCK(f8_e4m3)
DECLARE_AS_STRUCT_BLOCK(e8m0)
DECLARE_AS_STRUCT_BLOCK(bf16)
DECLARE_AS_BLOCK(half)
DECLARE_AS_BLOCK(int)
DECLARE_AS_BLOCK(float)
#ifdef cl_khr_fp64
DECLARE_AS_BLOCK(double)
#endif
#undef DECLARE_AS_BLOCK
#undef DECLARE_AS_STRUCT_BLOCK
#define DEF_load(dst_dt, src_dt) \
void __attribute__((overloadable)) load( \
__private dst_dt *dst, __global const src_dt *val) { \
*dst = CONCAT2(into_, dst_dt)(*val); \
} \
dst_dt __attribute__((overloadable, warn_unused_result)) load( \
dst_dt dst, __global const src_dt *val) { \
return CONCAT2(into_, dst_dt)(*val); \
} \
void __attribute__((overloadable)) load( \
__private dst_dt *dst, __global const src_dt *val, off_t off) { \
*dst = CONCAT2(into_, dst_dt)(val[off]); \
} \
dst_dt __attribute__((overloadable, warn_unused_result)) load( \
dst_dt dst, __global const src_dt *val, off_t off) { \
return CONCAT2(into_, dst_dt)(val[off]); \
} \
void __attribute__((overloadable)) load( \
__private dst_dt *dst, __private const src_dt *val) { \
*dst = CONCAT2(into_, dst_dt)(*val); \
} \
dst_dt __attribute__((overloadable, warn_unused_result)) load( \
dst_dt dst, __private const src_dt *val) { \
return CONCAT2(into_, dst_dt)(*val); \
} \
__attribute__((overloadable)) void block_load( \
__private dst_dt *dst, __global const src_dt *src, int n) { \
__attribute__((opencl_unroll_hint)) while (n >= 8) { \
__global BLOCK_DT(src_dt) *data \
= (__global BLOCK_DT(src_dt) *)(src); \
BLOCK_DT_N(src_dt, 8) \
block_val = BLOCK_READ_FUNC_N(src_dt, 8)(data); \
for (int i = 0; i < 8; i++) { \
src_dt src_val = CONCAT2(as_, src_dt)(block_val[i]); \
dst[i] = CONCAT2(into_, dst_dt)(src_val); \
} \
dst += 8; \
src += 8 * get_max_sub_group_size(); \
n -= 8; \
} \
if (n >= 4) { \
__global BLOCK_DT(src_dt) *data \
= (__global BLOCK_DT(src_dt) *)(src); \
BLOCK_DT_N(src_dt, 4) \
block_val = BLOCK_READ_FUNC_N(src_dt, 4)(data); \
for (int i = 0; i < 4; i++) { \
src_dt src_val = CONCAT2(as_, src_dt)(block_val[i]); \
dst[i] = CONCAT2(into_, dst_dt)(src_val); \
} \
dst += 4; \
src += 4 * get_max_sub_group_size(); \
n -= 4; \
} \
if (n >= 2) { \
__global BLOCK_DT(src_dt) *data \
= (__global BLOCK_DT(src_dt) *)(src); \
BLOCK_DT_N(src_dt, 2) \
block_val = BLOCK_READ_FUNC_N(src_dt, 2)(data); \
for (int i = 0; i < 2; i++) { \
src_dt src_val = CONCAT2(as_, src_dt)(block_val[i]); \
dst[i] = CONCAT2(into_, dst_dt)(src_val); \
} \
dst += 2; \
src += 2 * get_max_sub_group_size(); \
n -= 2; \
} \
if (n >= 1) { \
__global BLOCK_DT(src_dt) *data \
= (__global BLOCK_DT(src_dt) *)(src); \
BLOCK_DT(src_dt) \
block_val = BLOCK_READ_FUNC(src_dt)(data); \
src_dt src_val = CONCAT2(as_, src_dt)(block_val); \
*dst = CONCAT2(into_, dst_dt)(src_val); \
} \
} \
__attribute__((overloadable)) void block_load( \
__private dst_dt *dst, __global src_dt *src) { \
__global BLOCK_DT(src_dt) *data = (__global BLOCK_DT(src_dt) *)(src); \
BLOCK_DT(src_dt) block_val = BLOCK_READ_FUNC(src_dt)(data); \
src_dt src_val = CONCAT2(as_, src_dt)(block_val); \
*dst = CONCAT2(into_, dst_dt)(src_val); \
}
#define DEF_load_half_byte(dst_dt, src_dt) \
dst_dt __attribute__((overloadable, warn_unused_result)) load( \
dst_dt dst, __global const src_dt *val, off_t off) { \
src_dt data = CONCAT2(as_, src_dt)( \
get_half_byte((__global const uchar *)val, off)); \
return CONCAT2(into_, dst_dt)(data); \
} \
void __attribute__((overloadable)) load( \
__private dst_dt *dst, __global const src_dt *val, off_t off) { \
*dst = load(*dst, val, off); \
}
#define DEF_write(dst_dt, src_dt) \
void __attribute__((overloadable)) write( \
__global dst_dt *dst, __private const src_dt *val) { \
*dst = CONCAT2(into_, dst_dt)(*val); \
} \
void __attribute__((overloadable)) write( \
__global dst_dt *dst, __private src_dt val) { \
*dst = CONCAT2(into_, dst_dt)(val); \
} \
void __attribute__((overloadable)) write( \
__private dst_dt *dst, __private const src_dt *val) { \
*dst = CONCAT2(into_, dst_dt)(*val); \
} \
void __attribute__((overloadable)) write( \
__private dst_dt *dst, __private src_dt val) { \
*dst = CONCAT2(into_, dst_dt)(val); \
} \
__attribute__((overloadable)) void block_write( \
__global dst_dt *dst, __private const src_dt *src, int n) { \
__attribute__((opencl_unroll_hint)) while (n >= 8) { \
BLOCK_DT_N(dst_dt, 8) block_val; \
for (int i = 0; i < 8; i++) { \
dst_dt val = CONCAT2(into_, dst_dt)(src[i]); \
block_val[i] = as_block_data(val); \
} \
__global BLOCK_DT(dst_dt) *data \
= (__global BLOCK_DT(dst_dt) *)(dst); \
BLOCK_WRITE_FUNC_N(dst_dt, 8)(data, block_val); \
dst += 8 * get_max_sub_group_size(); \
src += 8; \
n -= 8; \
} \
if (n >= 4) { \
BLOCK_DT_N(dst_dt, 4) block_val; \
for (int i = 0; i < 4; i++) { \
dst_dt val = CONCAT2(into_, dst_dt)(src[i]); \
block_val[i] = as_block_data(val); \
} \
__global BLOCK_DT(dst_dt) *data \
= (__global BLOCK_DT(dst_dt) *)(dst); \
BLOCK_WRITE_FUNC_N(dst_dt, 4)(data, block_val); \
dst += 4 * get_max_sub_group_size(); \
src += 4; \
n -= 4; \
} \
if (n >= 2) { \
BLOCK_DT_N(dst_dt, 2) block_val; \
for (int i = 0; i < 2; i++) { \
dst_dt val = CONCAT2(into_, dst_dt)(src[i]); \
block_val[i] = as_block_data(val); \
} \
__global BLOCK_DT(dst_dt) *data \
= (__global BLOCK_DT(dst_dt) *)(dst); \
BLOCK_WRITE_FUNC_N(dst_dt, 2)(data, block_val); \
dst += 2 * get_max_sub_group_size(); \
src += 2; \
n -= 2; \
} \
if (n >= 1) { \
BLOCK_DT(dst_dt) block_val; \
dst_dt val = CONCAT2(into_, dst_dt)(*src); \
block_val = as_block_data(val); \
__global BLOCK_DT(dst_dt) *data \
= (__global BLOCK_DT(dst_dt) *)(dst); \
BLOCK_WRITE_FUNC(dst_dt)(data, block_val); \
} \
}
DEF_load(float, int);
DEF_load(float, float);
DEF_load(float, char);
DEF_load(float, uchar);
DEF_load(int, char);
DEF_load(int, uchar);
DEF_load(int, int);
DEF_load(float, bf16);
DEF_load(int, undef_data);
DEF_load(float, undef_data);
DEF_write(char, float);
DEF_write(uchar, float);
DEF_write(bf16, float);
DEF_write(float, float);
DEF_write(char, int);
DEF_write(uchar, int);
DEF_write(bf16, int);
DEF_write(int, int);
DEF_write(float, int);
DEF_write(int, float);
#ifdef cl_khr_fp16
DEF_load(half, half);
DEF_load(float, half);
DEF_write(half, float);
DEF_write(half, int);
DEF_write(half, half);
DEF_write(char, half);
DEF_write(uchar, half);
DEF_write(float, half);
DEF_write(bf16, half);
#ifdef MATH_UTILS_DECLARE_BF8
DEF_load(half, f8_e5m2);
DEF_load(float, f8_e5m2);
DEF_write(f8_e5m2, half);
DEF_write(f8_e5m2, float);
DEF_write(f8_e5m2, int);
#endif
#ifdef MATH_UTILS_DECLARE_HF8
DEF_load(half, f8_e4m3);
DEF_load(float, f8_e4m3);
DEF_write(f8_e4m3, half);
DEF_write(f8_e4m3, float);
DEF_write(f8_e4m3, int);
#endif
#ifdef MATH_UTILS_DECLARE_F4_E2M1
DEF_load_half_byte(half, f4_e2m1);
DEF_load_half_byte(float, f4_e2m1);
DEF_write(f4_e2m1, half);
DEF_write(f4_e2m1, float);
DEF_write(f4_e2m1, int);
#endif
#ifdef MATH_UTILS_DECLARE_F4_E3M0
DEF_load_half_byte(half, f4_e3m0);
DEF_load_half_byte(float, f4_e3m0);
DEF_write(f4_e3m0, half);
DEF_write(f4_e3m0, float);
DEF_write(f4_e3m0, int);
#endif
#ifdef MATH_UTILS_DECLARE_E8M0
DEF_load(float, e8m0);
#endif
#endif
#ifdef cl_khr_fp64
DEF_load(double, undef_data);
DEF_load(float, double);
DEF_load(double, char);
DEF_load(double, uchar);
DEF_load(double, int);
DEF_load(double, bf16);
DEF_load(double, float);
DEF_load(double, double);
DEF_write(char, double);
DEF_write(uchar, double);
DEF_write(bf16, double);
DEF_write(float, double);
DEF_write(double, double);
DEF_write(double, float);
#endif
#if defined(cl_khr_fp16) && defined(cl_khr_fp64)
DEF_load(double, half);
DEF_write(half, double);
#ifdef MATH_UTILS_DECLARE_BF8
DEF_load(double, f8_e5m2);
DEF_write(f8_e5m2, double);
#endif
#ifdef MATH_UTILS_DECLARE_HF8
DEF_load(double, f8_e4m3);
DEF_write(f8_e4m3, double);
#endif #endif
#endif