Skip to content

[SYCL] Add clang implementation for accessor property no_alias #3452

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 13 commits into from
Apr 9, 2021
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2771,7 +2771,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
if (Arg->getType().isRestrictQualified() ||
(CurCodeDecl &&
CurCodeDecl->hasAttr<SYCLIntelKernelArgsRestrictAttr>() &&
Arg->getType()->isPointerType()))
Arg->getType()->isPointerType()) ||
(Arg->hasAttr<RestrictAttr>() && Arg->getType()->isPointerType()))
AI->addAttr(llvm::Attribute::NoAlias);
}

Expand Down
24 changes: 24 additions & 0 deletions clang/lib/Sema/SemaSYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ class Util {
/// accessor_property_list class.
static bool isAccessorPropertyListType(const QualType &Ty);

/// Checks whether given clang type is a full specialization of the SYCL
/// no_alias class.
static bool isSyclAccessorNoAliasPropertyType(QualType Ty);

/// Checks whether given clang type is a full specialization of the SYCL
/// buffer_location class.
static bool isSyclBufferLocationType(const QualType &Ty);
Expand Down Expand Up @@ -1742,11 +1746,19 @@ class SyclKernelDeclCreator : public SyclKernelFieldHandler {
for (TemplateArgument::pack_iterator Prop = TemplArg.pack_begin();
Prop != TemplArg.pack_end(); ++Prop) {
QualType PropTy = Prop->getAsType();
if (Util::isSyclAccessorNoAliasPropertyType(PropTy))
handleNoAliasProperty(Param, PropTy, Loc);
if (Util::isSyclBufferLocationType(PropTy))
handleBufferLocationProperty(Param, PropTy, Loc);
}
}

void handleNoAliasProperty(ParmVarDecl *Param, QualType PropTy,
SourceLocation Loc) {
ASTContext &Ctx = SemaRef.getASTContext();
Param->addAttr(RestrictAttr::CreateImplicit(Ctx, Loc));
}

// Obtain an integer value stored in a template parameter of buffer_location
// property to pass it to buffer_location kernel attribute
void handleBufferLocationProperty(ParmVarDecl *Param, QualType PropTy,
Expand Down Expand Up @@ -4313,6 +4325,18 @@ bool Util::isSyclKernelHandlerType(const QualType &Ty) {
return matchQualifiedTypeName(Ty, Scopes);
}

bool Util::isSyclAccessorNoAliasPropertyType(QualType Ty) {
std::array<DeclContextDesc, 6> Scopes = {
Util::DeclContextDesc{Decl::Kind::Namespace, "cl"},
Util::DeclContextDesc{Decl::Kind::Namespace, "sycl"},
Util::DeclContextDesc{Decl::Kind::Namespace, "ONEAPI"},
Util::DeclContextDesc{Decl::Kind::Namespace, "property"},
Util::DeclContextDesc{Decl::Kind::CXXRecord, "no_alias"},
Util::DeclContextDesc{Decl::Kind::ClassTemplateSpecialization,
"instance"}};
return matchQualifiedTypeName(Ty, Scopes);
}

bool Util::isSyclBufferLocationType(const QualType &Ty) {
const StringRef &PropertyName = "buffer_location";
const StringRef &InstanceName = "instance";
Expand Down
9 changes: 9 additions & 0 deletions clang/test/CodeGenSYCL/Inputs/sycl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,15 @@ struct buffer_location {
} // namespace property
} // namespace INTEL

namespace ONEAPI {
namespace property {
// Compile time known accessor property
struct no_alias {
template <bool> class instance {};
};
} // namespace property
} // namespace ONEAPI

namespace ONEAPI {
template <typename... properties>
class accessor_property_list {};
Expand Down
36 changes: 36 additions & 0 deletions clang/test/CodeGenSYCL/accessor_no_alias_property.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// RUN: %clang_cc1 -fsycl-is-device -triple spir64-unknown-unknown-sycldevice -emit-llvm %s -o - | FileCheck %s
// check that noalias parameter attribute is emitted when no_alias accessor property is used
// CHECK: define {{.*}}spir_kernel void @_ZTSZ4mainE16kernel_function1({{.*}} noalias {{.*}} %_arg_, {{.*}})

// check that noalias parameter attribute is NOT emitted when it is not used
// CHECK: define {{.*}}spir_kernel void @_ZTSZ4mainE16kernel_function2{{.*}} !kernel_arg_buffer_location
// CHECK-NOT: define {{.*}}spir_kernel void @_ZTSZ4mainE16kernel_function2({{.*}} noalias {{.*}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines 6 and 7 here are broken. The first checks to see if that kernel is defined, and the 2nd just checks to see if it is defined AGAIN. This is not correct. Presumably there needs to be a 'CHECK-NOT'/'CHECK-SAME' combo, like in the example here:
https://llvm.org/docs/CommandGuide/FileCheck.html#the-check-same-directive

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR - #4283


#include "Inputs/sycl.hpp"

int main() {
cl::sycl::accessor<int, 1, cl::sycl::access::mode::read_write,
cl::sycl::access::target::global_buffer,
cl::sycl::access::placeholder::false_t,
cl::sycl::ONEAPI::accessor_property_list<
cl::sycl::ONEAPI::property::no_alias::instance<true>>>
accessorA;

cl::sycl::accessor<int, 1, cl::sycl::access::mode::read_write,
cl::sycl::access::target::global_buffer,
cl::sycl::access::placeholder::false_t,
cl::sycl::ONEAPI::accessor_property_list<
cl::sycl::INTEL::property::buffer_location::instance<1>>>
accessorB;

cl::sycl::kernel_single_task<class kernel_function1>(
[=]() {
accessorA.use();
});

cl::sycl::kernel_single_task<class kernel_function2>(
[=]() {
accessorB.use();
});
return 0;
}