Skip to content

[SYCL] Re-use OpenCL sampler in SYCL mode #1

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

Closed
wants to merge 15 commits into from
Closed
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
3 changes: 3 additions & 0 deletions buildbot/dependency.sh
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,8 @@ else
fi

cd ${BUILD_DIR}/OpenCL-ICD-Loader
mkdir build
cd build
cmake ..
make C_INCLUDE_PATH=${OPENCL_HEADERS}
exit_if_err $? "failed to build OpenCL-ICD-Loader"
2 changes: 1 addition & 1 deletion clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1283,7 +1283,7 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass);
InitBuiltinType(ObjCBuiltinSelTy, BuiltinType::ObjCSel);

if (LangOpts.OpenCL) {
if (LangOpts.OpenCL || LangOpts.SYCLIsDevice) {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
InitBuiltinType(SingletonId, BuiltinType::Id);
#include "clang/Basic/OpenCLImageTypes.def"
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,

if (LangOpts.ObjC)
createObjCRuntime();
if (LangOpts.OpenCL)
if (LangOpts.OpenCL || LangOpts.SYCLIsDevice)
createOpenCLRuntime();
if (LangOpts.OpenMP)
createOpenMPRuntime();
Expand Down
11 changes: 6 additions & 5 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3420,17 +3420,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
assert(Inputs.size() >= 1 && "Must have at least one input.");
// CUDA/HIP compilation may have multiple inputs (source file + results of
// device-side compilations). OpenMP and SYCL device jobs also take the host
// IR as a second input. All other jobs are expected to have exactly one
// include as part of the module. All other jobs are expected to have exactly
// one input.
// IR as a second input. Module precompilation accepts a list of header files
// to include as part of the module. All other jobs are expected to have
// exactly one input.
bool IsCuda = JA.isOffloading(Action::OFK_Cuda);
bool IsHIP = JA.isOffloading(Action::OFK_HIP);
bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
bool IsSYCLOffloadDevice = JA.isDeviceOffloading(Action::OFK_SYCL);
bool IsSYCL = JA.isOffloading(Action::OFK_SYCL);
bool IsHeaderModulePrecompile = isa<HeaderModulePrecompileJobAction>(JA);
assert((IsCuda || IsHIP || (IsOpenMPDevice && Inputs.size() == 2) ||
IsSYCL || Inputs.size() == 1) && "Unable to handle multiple inputs.");
assert((IsCuda || IsHIP || (IsOpenMPDevice && Inputs.size() == 2) || IsSYCL ||
IsHeaderModulePrecompile || Inputs.size() == 1) &&
"Unable to handle multiple inputs.");

// A header module compilation doesn't have a main input file, so invent a
// fake one as a placeholder.
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Sema/Sema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ void Sema::Initialize() {
if (IdResolver.begin(Class) == IdResolver.end())
PushOnScopeChains(Context.getObjCClassDecl(), TUScope);

// Create the built-in forward declaratino for 'Protocol'.
// Create the built-in forward declaration for 'Protocol'.
DeclarationName Protocol = &Context.Idents.get("Protocol");
if (IdResolver.begin(Protocol) == IdResolver.end())
PushOnScopeChains(Context.getObjCProtocolDecl(), TUScope);
Expand All @@ -267,6 +267,9 @@ void Sema::Initialize() {

// Initialize predefined OpenCL types and supported extensions and (optional)
// core features.
if (getLangOpts().SYCLIsDevice) {
addImplicitTypedef("__ocl_sampler_t", Context.OCLSamplerTy);
}
if (getLangOpts().OpenCL) {
getOpenCLOptions().addSupport(
Context.getTargetInfo().getSupportedOpenCLOpts());
Expand Down
40 changes: 20 additions & 20 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6327,6 +6327,26 @@ NamedDecl *Sema::ActOnVariableDeclarator(
return nullptr;
}

if (R->isSamplerT()) {
// OpenCL v1.2 s6.9.b p4:
// The sampler type cannot be used with the __local and __global address
// space qualifiers.
if (R.getAddressSpace() == LangAS::opencl_local ||
R.getAddressSpace() == LangAS::opencl_global) {
Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace);
}

// OpenCL v1.2 s6.12.14.1:
// A global sampler must be declared with either the constant address
// space qualifier or with the const qualifier.
if (DC->isTranslationUnit() &&
!(R.getAddressSpace() == LangAS::opencl_constant ||
R.isConstQualified())) {
Diag(D.getIdentifierLoc(), diag::err_opencl_nonconst_global_sampler);
D.setInvalidType();
}
}

if (getLangOpts().OpenCL) {
// OpenCL v2.0 s6.9.b - Image type can only be used as a function argument.
// OpenCL v2.0 s6.13.16.1 - Pipe type can only be used as a function
Expand Down Expand Up @@ -6372,26 +6392,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}

if (R->isSamplerT()) {
// OpenCL v1.2 s6.9.b p4:
// The sampler type cannot be used with the __local and __global address
// space qualifiers.
if (R.getAddressSpace() == LangAS::opencl_local ||
R.getAddressSpace() == LangAS::opencl_global) {
Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace);
}

// OpenCL v1.2 s6.12.14.1:
// A global sampler must be declared with either the constant address
// space qualifier or with the const qualifier.
if (DC->isTranslationUnit() &&
!(R.getAddressSpace() == LangAS::opencl_constant ||
R.isConstQualified())) {
Diag(D.getIdentifierLoc(), diag::err_opencl_nonconst_global_sampler);
D.setInvalidType();
}
}

// OpenCL v1.2 s6.9.r:
// The event type cannot be used with the __local, __constant and __global
// address space qualifiers.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13019,7 +13019,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
bool CanOverflow = false;

bool ConvertHalfVec = false;
if (getLangOpts().OpenCL) {
if (getLangOpts().OpenCL || getLangOpts().SYCLIsDevice) {
QualType Ty = InputExpr->getType();
// The only legal unary operation for atomics is '&'.
if ((Opc != UO_AddrOf && Ty->isAtomicType()) ||
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5305,9 +5305,9 @@ static bool TryOCLSamplerInitialization(Sema &S,
InitializationSequence &Sequence,
QualType DestType,
Expr *Initializer) {
if (!S.getLangOpts().OpenCL || !DestType->isSamplerT() ||
if (!DestType->isSamplerT() ||
(!Initializer->isIntegerConstantExpr(S.Context) &&
!Initializer->getType()->isSamplerT()))
!Initializer->getType()->isSamplerT()))
return false;

Sequence.AddOCLSamplerInitStep(DestType);
Expand Down Expand Up @@ -5620,6 +5620,9 @@ void InitializationSequence::InitializeFrom(Sema &S,
bool allowObjCWritebackConversion = S.getLangOpts().ObjCAutoRefCount &&
Entity.isParameterKind();

if (TryOCLSamplerInitialization(S, *this, DestType, Initializer))
return;

// We're at the end of the line for C: it's either a write-back conversion
// or it's a C assignment. There's no need to check anything else.
if (!S.getLangOpts().CPlusPlus) {
Expand All @@ -5629,9 +5632,6 @@ void InitializationSequence::InitializeFrom(Sema &S,
return;
}

if (TryOCLSamplerInitialization(S, *this, DestType, Initializer))
return;

if (TryOCLZeroOpaqueTypeInitialization(S, *this, DestType, Initializer))
return;

Expand Down
86 changes: 51 additions & 35 deletions clang/lib/Sema/SemaSYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,16 @@ static FunctionDecl *CreateSYCLKernelFunction(ASTContext &Context,
DC->addDecl(SYCLKernel);
return SYCLKernel;
}
/// Return __init method
static CXXMethodDecl *getInitMethod(const CXXRecordDecl *CRD) {
CXXMethodDecl *InitMethod;
auto It = std::find_if(CRD->methods().begin(), CRD->methods().end(),
[](const CXXMethodDecl *Method) {
return Method->getNameAsString() == "__init";
});
InitMethod = (It != CRD->methods().end()) ? *It : nullptr;
return InitMethod;
}

static CompoundStmt *
CreateSYCLKernelBody(Sema &S, FunctionDecl *KernelCallerFunc, DeclContext *DC) {
Expand Down Expand Up @@ -479,13 +489,7 @@ CreateSYCLKernelBody(Sema &S, FunctionDecl *KernelCallerFunc, DeclContext *DC) {
DeclarationNameInfo(Field->getDeclName(), SourceLocation()),
nullptr, Field->getType(), VK_LValue, OK_Ordinary);

CXXMethodDecl *InitMethod = nullptr;
for (auto Method : CRD->methods()) {
if (Method->getNameInfo().getName().getAsString() == "__init") {
InitMethod = Method;
break;
}
}
CXXMethodDecl *InitMethod = getInitMethod(CRD);
assert(InitMethod && "The accessor must have the __init method");

// [kenrel_obj or wrapper object].accessor.__init
Expand Down Expand Up @@ -581,13 +585,7 @@ CreateSYCLKernelBody(Sema &S, FunctionDecl *KernelCallerFunc, DeclContext *DC) {
DeclarationNameInfo(Field->getDeclName(), SourceLocation()),
nullptr, Field->getType(), VK_LValue, OK_Ordinary);

CXXMethodDecl *InitMethod = nullptr;
for (auto Method : CRD->methods()) {
if (Method->getNameInfo().getName().getAsString() == "__init") {
InitMethod = Method;
break;
}
}
CXXMethodDecl *InitMethod = getInitMethod(CRD);
assert(InitMethod && "The sampler must have the __init method");

// kernel_obj.sampler.__init
Expand Down Expand Up @@ -755,20 +753,27 @@ static void buildArgTys(ASTContext &Context, CXXRecordDecl *KernelObj,

CreateAndAddPrmDsc(Fld, PointerType);

FieldDecl *AccessRangeFld =
getFieldDeclByName(RecordDecl, {"impl", "AccessRange"});
assert(AccessRangeFld &&
"The accessor.impl must contain the AccessRange field");
CreateAndAddPrmDsc(AccessRangeFld, AccessRangeFld->getType());
CXXMethodDecl *InitMethod = getInitMethod(RecordDecl);
assert(InitMethod && "accessor must have __init method");

FieldDecl *MemRangeFld =
getFieldDeclByName(RecordDecl, {"impl", "MemRange"});
assert(MemRangeFld && "The accessor.impl must contain the MemRange field");
CreateAndAddPrmDsc(MemRangeFld, MemRangeFld->getType());
// Expected accessor __init method has four parameters
// void __init(_ValueType *Ptr, range<dimensions> AccessRange,
// range<dimensions> MemRange, id<dimensions> Offset)
auto *FuncDecl = cast<FunctionDecl>(InitMethod);
ParmVarDecl *AccessRangeFld = FuncDecl->getParamDecl(1);
ParmVarDecl *MemRangeFld = FuncDecl->getParamDecl(2);
ParmVarDecl *OffsetFld = FuncDecl->getParamDecl(3);

FieldDecl *OffsetFld = getFieldDeclByName(RecordDecl, {"impl", "Offset"});
assert(OffsetFld && "The accessor.impl must contain the Offset field");
CreateAndAddPrmDsc(OffsetFld, OffsetFld->getType());
assert(AccessRangeFld &&
"The accessor __init method must contain the AccessRange parameter");
assert(MemRangeFld &&
"The accessor __init method must contain the MemRange parameter");
assert(OffsetFld &&
"The accessor __init method must contain the Offset parameter");

CreateAndAddPrmDsc(Fld, AccessRangeFld->getType());
CreateAndAddPrmDsc(Fld, MemRangeFld->getType());
CreateAndAddPrmDsc(Fld, OffsetFld->getType());
};

std::function<void(const FieldDecl *, const QualType &ArgTy)>
Expand Down Expand Up @@ -799,10 +804,16 @@ static void buildArgTys(ASTContext &Context, CXXRecordDecl *KernelObj,
const auto *RecordDecl = ArgTy->getAsCXXRecordDecl();
assert(RecordDecl && "sampler must be of a record type");

FieldDecl *ImplFld =
getFieldDeclByName(RecordDecl, {"impl", "m_Sampler"});
assert(ImplFld && "The sampler must contain impl field");
CreateAndAddPrmDsc(ImplFld, ImplFld->getType());
CXXMethodDecl *InitMethod = getInitMethod(RecordDecl);
assert(InitMethod && "sampler must have __init method");

// sampler __init method has only one parameter
// void __init(__spirv::OpTypeSampler *Sampler)
auto *FuncDecl = cast<FunctionDecl>(InitMethod);
ParmVarDecl *SamplerArg = FuncDecl->getParamDecl(0);
assert(SamplerArg && "sampler __init method must have sampler parameter");

CreateAndAddPrmDsc(Fld, SamplerArg->getType());
} else if (Util::isSyclStreamType(ArgTy)) {
// the parameter is a SYCL stream object
llvm_unreachable("streams not supported yet");
Expand Down Expand Up @@ -893,13 +904,18 @@ static void populateIntHeader(SYCLIntegrationHeader &H, const StringRef Name,
populateHeaderForAccessor(ArgTy, Offset);
} else if (Util::isSyclSamplerType(ArgTy)) {
// The parameter is a SYCL sampler object
// It has only one descriptor, "m_Sampler"
const auto *SamplerTy = ArgTy->getAsCXXRecordDecl();
assert(SamplerTy && "sampler must be of a record type");
FieldDecl *ImplFld =
getFieldDeclByName(SamplerTy, {"impl", "m_Sampler"}, &Offset);
uint64_t Sz =
Ctx.getTypeSizeInChars(ImplFld->getType()).getQuantity();

CXXMethodDecl *InitMethod = getInitMethod(SamplerTy);
assert(InitMethod && "sampler must have __init method");

// sampler __init method has only one argument
// void __init(__spirv::OpTypeSampler *Sampler)
auto *FuncDecl = cast<FunctionDecl>(InitMethod);
ParmVarDecl *SamplerArg = FuncDecl->getParamDecl(0);
assert(SamplerArg && "sampler __init method must have sampler parameter");
uint64_t Sz = Ctx.getTypeSizeInChars(SamplerArg->getType()).getQuantity();
H.addParamDesc(SYCLIntegrationHeader::kind_sampler,
static_cast<unsigned>(Sz), static_cast<unsigned>(Offset));
} else if (Util::isSyclStreamType(ArgTy)) {
Expand Down
8 changes: 5 additions & 3 deletions clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2303,7 +2303,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
// OpenCL v2.0 s6.12.5 - Arrays of blocks are not supported.
// OpenCL v2.0 s6.16.13.1 - Arrays of pipe type are not supported.
// OpenCL v2.0 s6.9.b - Arrays of image/sampler type are not supported.
if (getLangOpts().OpenCL) {
if (getLangOpts().OpenCL || getLangOpts().SYCLIsDevice) {
const QualType ArrType = Context.getBaseElementType(T);
if (ArrType->isBlockPointerType() || ArrType->isPipeType() ||
ArrType->isSamplerT() || ArrType->isImageType()) {
Expand Down Expand Up @@ -4389,7 +4389,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// OpenCL v2.0 s6.9b - Pointer to image/sampler cannot be used.
// OpenCL v2.0 s6.13.16.1 - Pointer to pipe cannot be used.
// OpenCL v2.0 s6.12.5 - Pointers to Blocks are not allowed.
if (LangOpts.OpenCL) {
if (LangOpts.OpenCL || LangOpts.SYCLIsDevice) {
if (T->isImageType() || T->isSamplerT() || T->isPipeType() ||
T->isBlockPointerType()) {
S.Diag(D.getIdentifierLoc(), diag::err_opencl_pointer_to_type) << T;
Expand Down Expand Up @@ -4587,7 +4587,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}

if (LangOpts.OpenCL) {
if (LangOpts.OpenCL || LangOpts.SYCLIsDevice) {
// OpenCL v2.0 s6.12.5 - A block cannot be the return value of a
// function.
if (T->isBlockPointerType() || T->isImageType() || T->isSamplerT() ||
Expand All @@ -4599,7 +4599,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// OpenCL doesn't support variadic functions and blocks
// (s6.9.e and s6.12.5 OpenCL v2.0) except for printf.
// We also allow here any toolchain reserved identifiers.
// FIXME: Use deferred diagnostics engine to skip host side issues.
if (FTI.isVariadic &&
!LangOpts.SYCLIsDevice &&
!(D.getIdentifier() &&
((D.getIdentifier()->getName() == "printf" &&
(LangOpts.OpenCLCPlusPlus || LangOpts.OpenCLVersion >= 120)) ||
Expand Down
1 change: 0 additions & 1 deletion clang/test/CodeGenSYCL/int_header1.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// RUN: %clang -I %S/Inputs --sycl -Xclang -fsycl-int-header=%t.h %s -c -o kernel.spv
// RUN: %clang -I %S/Inputs --sycl -Xclang -fsycl-int-header=%t.h %s -c -o kernel.spv
// RUN: FileCheck -input-file=%t.h %s

// CHECK:template <> struct KernelInfo<class KernelName> {
Expand Down
10 changes: 5 additions & 5 deletions clang/test/Driver/clang-offload-bundler.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Generate all the types of files we can bundle.
//
// generate the emulated fat object:
// RUN: %clangxx -O0 -target powerpc64le-ibm-linux-gnu -DEMULATE_FAT_OBJ %s -c -o %s.o
// RUN: %clangxx -O0 -target powerpc64le-ibm-linux-gnu -DEMULATE_FAT_OBJ %s -c -o %t.2.o
//
// RUN: %clang -O0 -target powerpc64le-ibm-linux-gnu %s -E -o %t.i
// RUN: %clangxx -O0 -target powerpc64le-ibm-linux-gnu -x c++ %s -E -o %t.ii
Expand Down Expand Up @@ -237,12 +237,12 @@
// CK-OBJ-CMD: private constant [{{[0-9]+}} x i8] c"Content of device file 2{{.+}}", section "__CLANG_OFFLOAD_BUNDLE__openmp-x86_64-pc-linux-gnu"
// CK-OBJ-CMD: clang{{(.exe)?}}" "-r" "-target" "powerpc64le-ibm-linux-gnu" "-o" "{{.+}}.o" "{{.+}}.o" "{{.+}}.bc" "-nostdlib"

// RUN: clang-offload-bundler -type=o -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.o,%t.res.tgt1,%t.res.tgt2 -inputs=%s.o -unbundle
// RUN: diff %s.o %t.res.o
// RUN: clang-offload-bundler -type=o -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.o,%t.res.tgt1,%t.res.tgt2 -inputs=%t.2.o -unbundle
// RUN: diff %t.2.o %t.res.o
// RUN: diff %t.tgt1 %t.res.tgt1
// RUN: diff %t.tgt2 %t.res.tgt2
// RUN: clang-offload-bundler -type=o -targets=openmp-powerpc64le-ibm-linux-gnu,host-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.tgt1,%t.res.o,%t.res.tgt2 -inputs=%s.o -unbundle
// RUN: diff %s.o %t.res.o
// RUN: clang-offload-bundler -type=o -targets=openmp-powerpc64le-ibm-linux-gnu,host-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.tgt1,%t.res.o,%t.res.tgt2 -inputs=%t.2.o -unbundle
// RUN: diff %t.2.o %t.res.o
// RUN: diff %t.tgt1 %t.res.tgt1
// RUN: diff %t.tgt2 %t.res.tgt2

Expand Down
4 changes: 2 additions & 2 deletions clang/test/SemaSYCL/sampler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ int main() {
// CHECK: FunctionDecl {{.*}}use_kernel_for_test 'void (__spirv::OpTypeSampler *)'
//
// Check parameters of the test kernel
// CHECK: ParmVarDecl {{.*}} used _arg_m_Sampler '__spirv::OpTypeSampler *'
// CHECK: ParmVarDecl {{.*}} used [[_arg_sampler:[0-9a-zA-Z_]+]] '__spirv::OpTypeSampler *'
//
// Check that sampler field of the test kernel object is initialized using __init method
// CHECK: CXXMemberCallExpr {{.*}} 'void'
Expand All @@ -30,4 +30,4 @@ int main() {
// Check the parameters of __init method
// CHECK-NEXT: ImplicitCastExpr {{.*}} '__spirv::OpTypeSampler *' <LValueToRValue>
// CHECK-NEXT: ImplicitCastExpr {{.*}} '__spirv::OpTypeSampler *' lvalue <NoOp>
// CHECK-NEXT: DeclRefExpr {{.*}} '__spirv::OpTypeSampler *' lvalue ParmVar {{.*}} '_arg_m_Sampler' '__spirv::OpTypeSampler
// CHECK-NEXT: DeclRefExpr {{.*}} '__spirv::OpTypeSampler *' lvalue ParmVar {{.*}} '[[_arg_sampler]]' '__spirv::OpTypeSampler
Loading