Skip to content

[SYCL] Add local_accessor and deprecate target::local #6341

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Aug 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 41 additions & 25 deletions clang/lib/Sema/SemaSYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ class Util {
/// \param Tmpl whether the class is template instantiation or simple record
static bool isSyclType(QualType Ty, StringRef Name, bool Tmpl = false);

/// Checks whether given clang type is a standard SYCL API accessor class,
/// the check assumes the type is templated.
/// \param Ty the clang type being checked
static bool isSyclAccessorType(QualType Ty);

/// Checks whether given clang type is a full specialization of the SYCL
/// specialization constant class.
static bool isSyclSpecConstantType(QualType Ty);
Expand Down Expand Up @@ -1021,7 +1026,11 @@ static ParamDesc makeParamDesc(ASTContext &Ctx, StringRef Name, QualType Ty) {
}

/// \return the target of given SYCL accessor type
static target getAccessTarget(const ClassTemplateSpecializationDecl *AccTy) {
static target getAccessTarget(QualType FieldTy,
const ClassTemplateSpecializationDecl *AccTy) {
if (Util::isSyclType(FieldTy, "local_accessor", true /*Tmpl*/))
return local;

return static_cast<target>(
AccTy->getTemplateArgs()[3].getAsIntegral().getExtValue());
}
Expand Down Expand Up @@ -1615,7 +1624,7 @@ class SyclKernelFieldChecker : public SyclKernelFieldHandler {
assert(Util::isSyclSpecialType(Ty) &&
"Should only be called on sycl special class types.");
const RecordDecl *RecD = Ty->getAsRecordDecl();
if (IsSIMD && !Util::isSyclType(Ty, "accessor", true /*Tmp*/))
if (IsSIMD && !Util::isSyclAccessorType(Ty))
return SemaRef.Diag(Loc.getBegin(),
diag::err_sycl_esimd_not_supported_for_type)
<< RecD;
Expand Down Expand Up @@ -1927,19 +1936,24 @@ class SyclKernelDeclCreator : public SyclKernelFieldHandler {
}

// Additional processing is required for accessor type.
void handleAccessorType(const CXXRecordDecl *RecordDecl, SourceLocation Loc) {
void handleAccessorType(QualType FieldTy, const CXXRecordDecl *RecordDecl,
SourceLocation Loc) {
handleAccessorPropertyList(Params.back(), RecordDecl, Loc);
// Get access mode of accessor.
const auto *AccessorSpecializationDecl =
cast<ClassTemplateSpecializationDecl>(RecordDecl);
const TemplateArgument &AccessModeArg =
AccessorSpecializationDecl->getTemplateArgs().get(2);

// If "accessor" type check if read only
if (Util::isSyclType(FieldTy, "accessor", true /*Tmpl*/)) {
// Get access mode of accessor.
const auto *AccessorSpecializationDecl =
cast<ClassTemplateSpecializationDecl>(RecordDecl);
const TemplateArgument &AccessModeArg =
AccessorSpecializationDecl->getTemplateArgs().get(2);
if (isReadOnlyAccessor(AccessModeArg))
Params.back()->addAttr(
SYCLAccessorReadonlyAttr::CreateImplicit(SemaRef.getASTContext()));
}

// Add implicit attribute to parameter decl when it is a read only
// SYCL accessor.
if (isReadOnlyAccessor(AccessModeArg))
Params.back()->addAttr(
SYCLAccessorReadonlyAttr::CreateImplicit(SemaRef.getASTContext()));
Params.back()->addAttr(
SYCLAccessorPtrAttr::CreateImplicit(SemaRef.getASTContext()));
}
Expand All @@ -1952,8 +1966,7 @@ class SyclKernelDeclCreator : public SyclKernelFieldHandler {
const auto *RecordDecl = FieldTy->getAsCXXRecordDecl();
assert(RecordDecl && "The type must be a RecordDecl");
llvm::StringLiteral MethodName =
KernelDecl->hasAttr<SYCLSimdAttr>() &&
Util::isSyclType(FieldTy, "accessor", true /*Tmp*/)
KernelDecl->hasAttr<SYCLSimdAttr>() && Util::isSyclAccessorType(FieldTy)
? InitESIMDMethodName
: InitMethodName;
CXXMethodDecl *InitMethod = getMethodByName(RecordDecl, MethodName);
Expand All @@ -1978,8 +1991,8 @@ class SyclKernelDeclCreator : public SyclKernelFieldHandler {
// added, this code needs to be refactored to call
// handleAccessorPropertyList for each class which requires it.
if (ParamTy.getTypePtr()->isPointerType() &&
Util::isSyclType(FieldTy, "accessor", true /*Tmp*/))
handleAccessorType(RecordDecl, FD->getBeginLoc());
Util::isSyclAccessorType(FieldTy))
handleAccessorType(FieldTy, RecordDecl, FD->getBeginLoc());
}
LastParamIndex = ParamIndex;
return true;
Expand Down Expand Up @@ -2073,8 +2086,7 @@ class SyclKernelDeclCreator : public SyclKernelFieldHandler {
const auto *RecordDecl = FieldTy->getAsCXXRecordDecl();
assert(RecordDecl && "The type must be a RecordDecl");
llvm::StringLiteral MethodName =
KernelDecl->hasAttr<SYCLSimdAttr>() &&
Util::isSyclType(FieldTy, "accessor", true /*Tmp*/)
KernelDecl->hasAttr<SYCLSimdAttr>() && Util::isSyclAccessorType(FieldTy)
? InitESIMDMethodName
: InitMethodName;
CXXMethodDecl *InitMethod = getMethodByName(RecordDecl, MethodName);
Expand All @@ -2093,8 +2105,8 @@ class SyclKernelDeclCreator : public SyclKernelFieldHandler {
// added, this code needs to be refactored to call
// handleAccessorPropertyList for each class which requires it.
if (ParamTy.getTypePtr()->isPointerType() &&
Util::isSyclType(FieldTy, "accessor", true /*Tmp*/))
handleAccessorType(RecordDecl, BS.getBeginLoc());
Util::isSyclAccessorType(FieldTy))
handleAccessorType(FieldTy, RecordDecl, BS.getBeginLoc());
}
LastParamIndex = ParamIndex;
return true;
Expand Down Expand Up @@ -2215,9 +2227,8 @@ class SyclKernelArgsSizeChecker : public SyclKernelFieldHandler {
const CXXRecordDecl *RecordDecl = FieldTy->getAsCXXRecordDecl();
assert(RecordDecl && "The type must be a RecordDecl");
llvm::StringLiteral MethodName =
(IsSIMD && Util::isSyclType(FieldTy, "accessor", true /*Tmp*/))
? InitESIMDMethodName
: InitMethodName;
(IsSIMD && Util::isSyclAccessorType(FieldTy)) ? InitESIMDMethodName
: InitMethodName;
CXXMethodDecl *InitMethod = getMethodByName(RecordDecl, MethodName);
assert(InitMethod && "The type must have the __init method");
for (const ParmVarDecl *Param : InitMethod->parameters())
Expand Down Expand Up @@ -3124,7 +3135,7 @@ class SyclKernelIntHeaderCreator : public SyclKernelFieldHandler {
"Incorrect template args for Accessor Type");
int Dims = static_cast<int>(
AccTy->getTemplateArgs()[1].getAsIntegral().getExtValue());
int Info = getAccessTarget(AccTy) | (Dims << 11);
int Info = getAccessTarget(FieldTy, AccTy) | (Dims << 11);
Header.addParamDesc(SYCLIntegrationHeader::kind_accessor, Info,
CurOffset +
offsetOf(RD, BC.getType()->getAsCXXRecordDecl()));
Expand All @@ -3134,14 +3145,14 @@ class SyclKernelIntHeaderCreator : public SyclKernelFieldHandler {
bool handleSyclSpecialType(FieldDecl *FD, QualType FieldTy) final {
const auto *ClassTy = FieldTy->getAsCXXRecordDecl();
assert(ClassTy && "Type must be a C++ record type");
if (Util::isSyclType(FieldTy, "accessor", true /*Tmp*/)) {
if (Util::isSyclAccessorType(FieldTy)) {
const auto *AccTy =
cast<ClassTemplateSpecializationDecl>(FieldTy->getAsRecordDecl());
assert(AccTy->getTemplateArgs().size() >= 2 &&
"Incorrect template args for Accessor Type");
int Dims = static_cast<int>(
AccTy->getTemplateArgs()[1].getAsIntegral().getExtValue());
int Info = getAccessTarget(AccTy) | (Dims << 11);
int Info = getAccessTarget(FieldTy, AccTy) | (Dims << 11);

Header.addParamDesc(SYCLIntegrationHeader::kind_accessor, Info,
CurOffset + offsetOf(FD, FieldTy));
Expand Down Expand Up @@ -5195,6 +5206,11 @@ bool Util::isSyclType(QualType Ty, StringRef Name, bool Tmpl) {
return matchQualifiedTypeName(Ty, Scopes);
}

bool Util::isSyclAccessorType(QualType Ty) {
return isSyclType(Ty, "accessor", true /* Tmpl */) ||
isSyclType(Ty, "local_accessor", true /* Tmpl */);
}

bool Util::isAccessorPropertyListType(QualType Ty) {
std::array<DeclContextDesc, 5> Scopes = {
Util::MakeDeclContextDesc(Decl::Kind::Namespace, "sycl"),
Expand Down
20 changes: 20 additions & 0 deletions clang/test/CodeGenSYCL/Inputs/sycl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,26 @@ class accessor<dataT, dimensions, accessmode, access::target::host_image, access
_ImageImplT<dimensions, accessmode, access::target::host_image> impl;
};

template <typename dataT, int dimensions>
class __attribute__((sycl_special_class))
local_accessor: public accessor<dataT,
dimensions, access::mode::read_write,
access::target::local> {
public:
void use(void) const {}
template <typename... T>
void use(T... args) {}
template <typename... T>
void use(T... args) const {}
_ImplT<dimensions> impl;

private:
#ifdef __SYCL_DEVICE_ONLY__
void __init(__attribute__((opencl_local)) dataT *Ptr, range<dimensions> AccessRange,
range<dimensions> MemRange, id<dimensions> Offset) {}
#endif
};

// TODO: Add support for image_array accessor.
// template <typename dataT, int dimensions, access::mode accessmode>
//class accessor<dataT, dimensions, accessmode, access::target::image_array, access::placeholder::false_t>
Expand Down
22 changes: 20 additions & 2 deletions clang/test/CodeGenSYCL/kernel-arg-accessor-pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ int main() {
access::placeholder::true_t>
acc3;

local_accessor<float, 2> acc4;

// kernel_A parameters : int*, sycl::range<1>, sycl::range<1>, sycl::id<1>,
// int*, sycl::range<1>, sycl::range<1>,sycl::id<1>.
q.submit([&](handler &h) {
Expand Down Expand Up @@ -67,11 +69,19 @@ int main() {
// Using local accessor as a kernel parameter.
// kernel_arg_runtime_aligned is generated for pointers from local accessors.
q.submit([&](handler &h) {
h.single_task<class localAccessor>([=]() {
h.single_task<class localAccessorDep>([=]() {
acc3.use();
});
});

// Using local_accessor as a kernel parameter.
// kernel_arg_runtime_aligned is generated for pointers from local accessors.
q.submit([&](handler &h) {
h.single_task<class localAccessor>([=]() {
acc4.use();
});
});

// kernel_acc_raw_ptr parameters : int*, sycl::range<1>, sycl::range<1>, sycl::id<1>, int*.
int *rawPtr;
q.submit([&](handler &h) {
Expand Down Expand Up @@ -130,14 +140,22 @@ int main() {
// CHECK-NOT: kernel_arg_runtime_aligned
// CHECK-NOT: kernel_arg_exclusive_ptr

// CHECK: define {{.*}}spir_kernel void @{{.*}}localAccessor
// CHECK: define {{.*}}spir_kernel void @{{.*}}localAccessorDep
// CHECK-SAME: ptr addrspace(1) noundef align 4 [[MEM_ARG1:%[a-zA-Z0-9_]+]],
// CHECK-SAME: ptr noundef byval{{.*}}align 4 [[ACC_RANGE1:%[a-zA-Z0-9_]+1]],
// CHECK-SAME: ptr noundef byval{{.*}}align 4 [[MEM_RANGE1:%[a-zA-Z0-9_]+2]],
// CHECK-SAME: ptr noundef byval{{.*}}align 4 [[OFFSET1:%[a-zA-Z0-9_]+3]]
// CHECK-SAME: !kernel_arg_runtime_aligned ![[#ACCESSORMD2]]
// CHECK-SAME: !kernel_arg_exclusive_ptr ![[#ACCESSORMD2]]

// CHECK: define {{.*}}spir_kernel void @{{.*}}localAccessor
// CHECK-SAME: ptr addrspace(3) noundef align 4 [[MEM_ARG1:%[a-zA-Z0-9_]+]],
// CHECK-SAME: ptr noundef byval{{.*}}align 4 [[ACC_RANGE1:%[a-zA-Z0-9_]+1]],
// CHECK-SAME: ptr noundef byval{{.*}}align 4 [[MEM_RANGE1:%[a-zA-Z0-9_]+2]],
// CHECK-SAME: ptr noundef byval{{.*}}align 4 [[OFFSET1:%[a-zA-Z0-9_]+3]]
// CHECK-SAME: !kernel_arg_runtime_aligned ![[#ACCESSORMD2]]
// CHECK-SAME: !kernel_arg_exclusive_ptr ![[#ACCESSORMD2]]

// Check kernel_acc_raw_ptr parameters
// CHECK: define {{.*}}spir_kernel void @{{.*}}kernel_acc_raw_ptr
// CHECK-SAME: ptr addrspace(1) noundef readonly align 4 [[MEM_ARG1:%[a-zA-Z0-9_]+]],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ int main() {
access::placeholder::true_t>
acc3;

local_accessor<float, 2> acc4;

// kernel_A parameters : int*, sycl::range<1>, sycl::range<1>, sycl::id<1>,
// int*, sycl::range<1>, sycl::range<1>,sycl::id<1>.
q.submit([&](handler &h) {
Expand Down Expand Up @@ -67,11 +69,19 @@ int main() {
// Using local accessor as a kernel parameter.
// kernel_arg_runtime_aligned is generated for pointers from local accessors.
q.submit([&](handler &h) {
h.single_task<class localAccessor>([=]() {
h.single_task<class localAccessorDep>([=]() {
acc3.use();
});
});

// Using local accessor as a kernel parameter.
// kernel_arg_runtime_aligned is generated for pointers from local accessors.
q.submit([&](handler &h) {
h.single_task<class localAccessor>([=]() {
acc4.use();
});
});

// kernel_acc_raw_ptr parameters : int*, sycl::range<1>, sycl::range<1>, sycl::id<1>, int*.
int *rawPtr;
q.submit([&](handler &h) {
Expand Down Expand Up @@ -125,13 +135,20 @@ int main() {
// CHECK-SAME: float addrspace(1)* noundef align 4 [[MEM_ARG1:%[a-zA-Z0-9_]+]]
// CHECK-NOT: kernel_arg_runtime_aligned

// CHECK: define {{.*}}spir_kernel void @{{.*}}localAccessor
// CHECK: define {{.*}}spir_kernel void @{{.*}}localAccessorDep
// CHECK-SAME: float addrspace(1)* noundef align 4 [[MEM_ARG1:%[a-zA-Z0-9_]+]],
// CHECK-SAME: %"struct.sycl::_V1::range.5"* noundef byval{{.*}}align 4 [[ACC_RANGE1:%[a-zA-Z0-9_]+1]],
// CHECK-SAME: %"struct.sycl::_V1::range.5"* noundef byval{{.*}}align 4 [[MEM_RANGE1:%[a-zA-Z0-9_]+2]],
// CHECK-SAME: %"struct.sycl::_V1::id.6"* noundef byval{{.*}}align 4 [[OFFSET1:%[a-zA-Z0-9_]+3]]
// CHECK-SAME: !kernel_arg_runtime_aligned ![[#RTALIGNED2]]

// CHECK: define {{.*}}spir_kernel void @{{.*}}localAccessor
// CHECK-SAME: float addrspace(3)* noundef align 4 [[MEM_ARG1:%[a-zA-Z0-9_]+]],
// CHECK-SAME: %"struct.sycl::_V1::range.5"* noundef byval{{.*}}align 4 [[ACC_RANGE1:%[a-zA-Z0-9_]+1]],
// CHECK-SAME: %"struct.sycl::_V1::range.5"* noundef byval{{.*}}align 4 [[MEM_RANGE1:%[a-zA-Z0-9_]+2]],
// CHECK-SAME: %"struct.sycl::_V1::id.6"* noundef byval{{.*}}align 4 [[OFFSET1:%[a-zA-Z0-9_]+3]]
// CHECK-SAME: !kernel_arg_runtime_aligned ![[#RTALIGNED2]]

// Check kernel_acc_raw_ptr parameters
// CHECK: define {{.*}}spir_kernel void @{{.*}}kernel_acc_raw_ptr
// CHECK-SAME: i32 addrspace(1)* noundef readonly align 4 [[MEM_ARG1:%[a-zA-Z0-9_]+]],
Expand Down
20 changes: 20 additions & 0 deletions clang/test/SemaSYCL/Inputs/sycl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,26 @@ class __attribute__((sycl_special_class)) accessor<dataT, dimensions, accessmode
#endif
};

template <typename dataT, int dimensions>
class __attribute__((sycl_special_class))
local_accessor: public accessor<dataT,
dimensions, access::mode::read_write,
access::target::local> {
public:
void use(void) const {}
template <typename... T>
void use(T... args) {}
template <typename... T>
void use(T... args) const {}
_ImplT<dimensions> impl;

private:
#ifdef __SYCL_DEVICE_ONLY__
void __init(__attribute__((opencl_local)) dataT *Ptr, range<dimensions> AccessRange,
range<dimensions> MemRange, id<dimensions> Offset) {}
#endif
};

struct sampler_impl {
#ifdef __SYCL_DEVICE_ONLY__
__ocl_sampler_t m_Sampler;
Expand Down
12 changes: 11 additions & 1 deletion clang/test/SemaSYCL/accessors-targets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ int main() {
// Access work-group local memory with read and write access.
sycl::accessor<int, 1, sycl::access::mode::read_write,
sycl::access::target::local>
local_acc;
local_acc_dep;
// Access work-group local memory with read and write access.
sycl::local_accessor<int, 1> local_acc;
// Access buffer via global memory with read and write access.
sycl::accessor<int, 1, sycl::access::mode::read_write,
sycl::access::target::global_buffer>
Expand All @@ -21,6 +23,13 @@ int main() {
sycl::access::target::constant_buffer>
constant_acc;

q.submit([&](sycl::handler &h) {
h.single_task<class use_local_dep>(
[=] {
local_acc_dep.use();
});
});

q.submit([&](sycl::handler &h) {
h.single_task<class use_local>(
[=] {
Expand All @@ -42,6 +51,7 @@ int main() {
});
});
}
// CHECK: {{.*}}use_local_dep{{.*}} 'void (__local int *, sycl::range<1>, sycl::range<1>, sycl::id<1>)'
// CHECK: {{.*}}use_local{{.*}} 'void (__local int *, sycl::range<1>, sycl::range<1>, sycl::id<1>)'
// CHECK: {{.*}}use_global{{.*}} 'void (__global int *, sycl::range<1>, sycl::range<1>, sycl::id<1>)'
// CHECK: {{.*}}use_constant{{.*}} 'void (__constant int *, sycl::range<1>, sycl::range<1>, sycl::id<1>)'
2 changes: 1 addition & 1 deletion sycl/include/sycl/access/access.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace access {
enum class target {
global_buffer __SYCL2020_DEPRECATED("use 'target::device' instead") = 2014,
constant_buffer = 2015,
local = 2016,
local __SYCL2020_DEPRECATED("use `local_accessor` instead") = 2016,
image = 2017,
host_buffer = 2018,
host_image = 2019,
Expand Down
Loading