diff --git a/clang/include/clang/Basic/Builtins.h b/clang/include/clang/Basic/Builtins.h index 89f65682ae5b4..714e584ef0d01 100644 --- a/clang/include/clang/Basic/Builtins.h +++ b/clang/include/clang/Basic/Builtins.h @@ -43,6 +43,7 @@ enum LanguageID : uint16_t { OCL_DSE = 0x400, // builtin requires OpenCL device side enqueue. ALL_OCL_LANGUAGES = 0x800, // builtin for OCL languages. HLSL_LANG = 0x1000, // builtin requires HLSL. + SYCL_LANG = 0x2000, // builtin requires SYCL. ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages. ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode. ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode. diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 2edad0ee11be3..583c2f51dfe8e 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4731,6 +4731,25 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> { let Prototype = "char const*(...)"; } +// SYCL +def SYCLIsKernel : LangBuiltin<"SYCL_LANG"> { + let Spellings = ["__builtin_sycl_is_kernel"]; + let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking]; + let Prototype = "bool(...)"; +} + +def SYCLIsSingleTaskKernel : LangBuiltin<"SYCL_LANG"> { + let Spellings = ["__builtin_sycl_is_single_task_kernel"]; + let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking]; + let Prototype = "bool(...)"; +} + +def SYCLIsNDRangeKernel : LangBuiltin<"SYCL_LANG"> { + let Spellings = ["__builtin_sycl_is_nd_range_kernel"]; + let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking]; + let Prototype = "bool(...)"; +} + // HLSL def HLSLAll : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_all"]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 55f0917a99ac4..ac12006aa3434 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -827,6 +827,9 @@ def warn_unreachable_association : Warning< InGroup; /// Built-in functions. +def err_builtin_invalid_argument_count : Error< + "builtin %plural{0:takes no arguments|1:takes one argument|" + ":requires exactly %0 arguments}0">; def ext_implicit_lib_function_decl : ExtWarn< "implicitly declaring library function '%0' with type %1">, InGroup; @@ -12388,7 +12391,11 @@ def err_builtin_invalid_arg_type: Error < "a vector of integers|" "an unsigned integer|" "an 'int'|" - "a vector of floating points}1 (was %2)">; + "a vector of floating points|" + "a function pointer}1 (was %2)">; + +def err_builtin_invalid_arg_value: Error< + "%ordinal0 argument must be a strictly positive value (was %1)">; def err_builtin_matrix_disabled: Error< "matrix types extension is disabled. Pass -fenable-matrix to enable it">; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 2bdeaf1737972..f6cd894aba4e3 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -12726,6 +12726,45 @@ static bool getBuiltinAlignArguments(const CallExpr *E, EvalInfo &Info, return true; } +static bool isSYCLFreeFunctionKernel(IntExprEvaluator &IEV, + const EvalInfo &Info, const CallExpr *E, + StringRef NameStr1, StringRef NameStr2, + bool CheckNDRangeKernelDim = false) { + const Expr *ArgExpr = E->getArg(0)->IgnoreParenImpCasts(); + while (isa(ArgExpr)) + ArgExpr = cast(ArgExpr)->getSubExpr(); + auto *DRE = dyn_cast(ArgExpr); + if (DRE) { + const FunctionDecl *FD = dyn_cast(DRE->getDecl()); + if (FD) { + auto *SAIRAttr = FD->getAttr(); + if (!SAIRAttr) + return IEV.Success(false, E); + SmallVector, 4> NameValuePairs = + SAIRAttr->getFilteredAttributeNameValuePairs(Info.Ctx); + for (const auto &NVPair : NameValuePairs) { + if (!NVPair.first.compare(NameStr1) || + (!NameStr2.empty() && !NVPair.first.compare(NameStr2))) { + if (CheckNDRangeKernelDim) { + uint64_t Dim = + E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue(); + // Return true only if the dimensions match. + if (std::stoul(NVPair.second) == Dim) + return IEV.Success(true, E); + else + return IEV.Success(false, E); + } + // Return true if it has the sycl-single-task-kernel or the + // sycl-nd-range-kernel attribute. + return IEV.Success(true, E); + } + } + return IEV.Success(false, E); + } + } + return false; +} + bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp) { switch (BuiltinOp) { @@ -13671,6 +13710,19 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, Result.setBitVal(P++, Val[I]); return Success(Result, E); } + + case Builtin::BI__builtin_sycl_is_kernel: { + return isSYCLFreeFunctionKernel(*this, Info, E, "sycl-single-task-kernel", + "sycl-nd-range-kernel"); + } + case Builtin::BI__builtin_sycl_is_single_task_kernel: { + return isSYCLFreeFunctionKernel(*this, Info, E, "sycl-single-task-kernel", + ""); + } + case Builtin::BI__builtin_sycl_is_nd_range_kernel: { + return isSYCLFreeFunctionKernel(*this, Info, E, "sycl-nd-range-kernel", "", + /*CheckNDRangeDim=*/true); + } } } diff --git a/clang/lib/Basic/Builtins.cpp b/clang/lib/Basic/Builtins.cpp index 25a601573698e..1f5cbbfebcdca 100644 --- a/clang/lib/Basic/Builtins.cpp +++ b/clang/lib/Basic/Builtins.cpp @@ -119,6 +119,9 @@ static bool builtinIsSupported(const Builtin::Info &BuiltinInfo, /* CUDA Unsupported */ if (!LangOpts.CUDA && BuiltinInfo.Langs == CUDA_LANG) return false; + /* SYCL Unsupported */ + if (!LangOpts.isSYCL() && BuiltinInfo.Langs == SYCL_LANG) + return false; /* CPlusPlus Unsupported */ if (!LangOpts.CPlusPlus && BuiltinInfo.Langs == CXX_LANG) return false; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 3ed10cb07041e..5b90f7a4238c9 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2642,6 +2642,53 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } +static RValue EmitSYCLFreeFunctionKernelBuiltin(CodeGenFunction &CGF, + const CallExpr *E, + StringRef NameStr1, + StringRef NameStr2, + bool CheckNDRangeDim = false) { + const Expr *ArgExpr = E->getArg(0)->IgnoreImpCasts(); + auto *UO = dyn_cast(ArgExpr); + // If this is of the form &function or *function, get to the function + // sub-expression. + if (UO && (UO->getOpcode() == UO_AddrOf || UO->getOpcode() == UO_Deref)) + ArgExpr = UO->getSubExpr()->IgnoreParenImpCasts(); + while (isa(ArgExpr)) + ArgExpr = cast(ArgExpr)->getSubExpr(); + auto *DRE = dyn_cast(ArgExpr); + if (DRE) { + const FunctionDecl *FD = dyn_cast(DRE->getDecl()); + if (FD && FD->hasAttr()) { + auto *SAIRAttr = FD->getAttr(); + SmallVector, 4> NameValuePairs = + SAIRAttr->getFilteredAttributeNameValuePairs(CGF.CGM.getContext()); + for (const auto &NVPair : NameValuePairs) { + if (!NVPair.first.compare(NameStr1) || + (!NameStr2.empty() && !!NVPair.first.compare(NameStr2))) { + if (CheckNDRangeDim) { + uint64_t Dim = E->getArg(1) + ->EvaluateKnownConstInt(CGF.CGM.getContext()) + .getZExtValue(); + // Return true only if the dimensions match. + if (std::stoul(NVPair.second) == Dim) + return RValue::get( + llvm::ConstantInt::getTrue(CGF.ConvertType(E->getType()))); + else + return RValue::get( + llvm::ConstantInt::getFalse(CGF.ConvertType(E->getType()))); + } + // Return true if the kernel type matches. + return RValue::get( + llvm::ConstantInt::getTrue(CGF.ConvertType(E->getType()))); + } + } + } + } + // Return false otherwise. + return RValue::get( + llvm::ConstantInt::getFalse(CGF.ConvertType(E->getType()))); +} + RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { @@ -6282,6 +6329,18 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, auto Str = CGM.GetAddrOfConstantCString(Name, ""); return RValue::get(Str.getPointer()); } + case Builtin::BI__builtin_sycl_is_kernel: { + return EmitSYCLFreeFunctionKernelBuiltin( + *this, E, "sycl-single-task-kernel", "sycl-nd-range-kernel"); + } + case Builtin::BI__builtin_sycl_is_single_task_kernel: { + return EmitSYCLFreeFunctionKernelBuiltin(*this, E, + "sycl-single-task-kernel", ""); + } + case Builtin::BI__builtin_sycl_is_nd_range_kernel: { + return EmitSYCLFreeFunctionKernelBuiltin(*this, E, "sycl-nd-range-kernel", + "", /*CheckNDRangeDim=*/true); + } } // If this is an alias for a lib function (e.g. __builtin_sin), emit diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 409da07e4154c..253fdf7c6d49a 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3024,6 +3024,40 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, } break; } + + case Builtin::BI__builtin_sycl_is_kernel: + case Builtin::BI__builtin_sycl_is_single_task_kernel: + case Builtin::BI__builtin_sycl_is_nd_range_kernel: { + unsigned int ExpNumArgs = + BuiltinID == Builtin::BI__builtin_sycl_is_nd_range_kernel ? 2 : 1; + // Builtin takes either 1 or 2 arguments. + if (TheCall->getNumArgs() != ExpNumArgs) { + Diag(TheCall->getBeginLoc(), diag::err_builtin_invalid_argument_count) + << ExpNumArgs; + return ExprError(); + } + + const Expr *Arg = TheCall->getArg(0); + QualType ArgTy = Arg->getType(); + + if (!ArgTy->isFunctionProtoType() && !ArgTy->isFunctionPointerType()) { + Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type) + << 1 << /* pointer to function type */ 10 << ArgTy; + return ExprError(); + } + + if (ExpNumArgs == 2) { + int64_t DimArg = + TheCall->getArg(1)->EvaluateKnownConstInt(Context).getSExtValue(); + if (DimArg <= 0) { + Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_value) + << 2 << DimArg; + return ExprError(); + } + } + + break; + } } if (getLangOpts().HLSL && HLSL().CheckBuiltinFunctionCall(BuiltinID, TheCall)) diff --git a/clang/test/CodeGenSYCL/builtin_sycl_kernel.cpp b/clang/test/CodeGenSYCL/builtin_sycl_kernel.cpp new file mode 100644 index 0000000000000..6f947621a5937 --- /dev/null +++ b/clang/test/CodeGenSYCL/builtin_sycl_kernel.cpp @@ -0,0 +1,79 @@ +// RUN: %clang_cc1 -internal-isystem %S/Inputs -fsycl-is-device -triple spir64-unknown-unknown -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s + +// This test tests the builtin __builtin_sycl_is_kernel + +#include "sycl.hpp" + +using namespace sycl; +queue q; + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 0)]] +void sstk_free_func() { +} + +template +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 4)]] +void sstk_free_func_tmpl(T *ptr) { + for (int i = 0; i <= 7; i++) + ptr[i] = i + 11; +} + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 1)]] +void ovl_free_func(int *ptr) { + for (int i = 0; i <= 7; i++) + ptr[i] = i; +} + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 1)]] +void ovl_free_func(int *ptr, int val) { + for (int i = 0; i <= 7; i++) + ptr[i] = i + val; +} + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 4)]] +void sndrk_free_func() { +} + +void func() {} + +void foo() { + bool b1 = __builtin_sycl_is_kernel(sstk_free_func); + // CHECK: store i8 1, ptr addrspace(4) %b1{{.*}}, align 1 + bool b2 = __builtin_sycl_is_kernel(*sstk_free_func); + // CHECK: store i8 1, ptr addrspace(4) %b2{{.*}}, align 1 + bool b3 = __builtin_sycl_is_kernel(&sstk_free_func); + // CHECK: store i8 1, ptr addrspace(4) %b3{{.*}}, align 1 + bool b4 = __builtin_sycl_is_kernel(func); + // CHECK: store i8 0, ptr addrspace(4) %b4{{.*}}, align 1 + bool b5 = __builtin_sycl_is_kernel(sndrk_free_func); + // CHECK: store i8 1, ptr addrspace(4) %b5{{.*}}, align 1 + + // Constexpr forms of the valid cases. + constexpr bool b6 = __builtin_sycl_is_kernel(sstk_free_func); // Okay and true. + // CHECK: store i8 1, ptr addrspace(4) %b6{{.*}}, align 1 + constexpr bool b7 = __builtin_sycl_is_kernel(func); // Okay, but false. + // CHECK: store i8 0, ptr addrspace(4) %b7{{.*}}, align 1 + constexpr bool b8 = __builtin_sycl_is_kernel(sndrk_free_func); // Okay, but false. + // CHECK: store i8 1, ptr addrspace(4) %b8{{.*}}, align 1 + + // Test function template. + constexpr bool b9 = __builtin_sycl_is_kernel((void(*)(int *))sstk_free_func_tmpl); // Okay + // CHECK: store i8 1, ptr addrspace(4) %b9{{.*}}, align 1 + + // Test overloaded functions. + constexpr bool b10 = __builtin_sycl_is_kernel((void(*)(int *))ovl_free_func); // Okay + // CHECK: store i8 1, ptr addrspace(4) %b10{{.*}}, align 1 + constexpr bool b11 = __builtin_sycl_is_kernel((void(*)(int *, int))ovl_free_func); // Okay + // CHECK: store i8 1, ptr addrspace(4) %b11{{.*}}, align 1 +} + +void f() { + auto L = []() { foo(); }; + q.submit([&](handler &h) { + h.single_task(L); + }); +} diff --git a/clang/test/CodeGenSYCL/builtin_sycl_nd_range_kernel.cpp b/clang/test/CodeGenSYCL/builtin_sycl_nd_range_kernel.cpp new file mode 100644 index 0000000000000..8982c129c0e46 --- /dev/null +++ b/clang/test/CodeGenSYCL/builtin_sycl_nd_range_kernel.cpp @@ -0,0 +1,79 @@ +// RUN: %clang_cc1 -internal-isystem %S/Inputs -fsycl-is-device -triple spir64-unknown-unknown -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s + +// This test tests the builtin __builtin_sycl_is_nd_range_kernel + +#include "sycl.hpp" + +using namespace sycl; +queue q; + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 2)]] +void sndrk_free_func() { +} + +template +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 4)]] +void sndrk_free_func_tmpl(T *ptr) { + for (int i = 0; i <= 7; i++) + ptr[i] = i + 11; +} + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 1)]] +void ovl_free_func(int *ptr) { + for (int i = 0; i <= 7; i++) + ptr[i] = i; +} + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 3)]] +void ovl_free_func(int *ptr, int val) { + for (int i = 0; i <= 7; i++) + ptr[i] = i + val; +} + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 4)]] +void sstk_free_func() { +} + +void func() {} + +void foo() { + bool b1 = __builtin_sycl_is_nd_range_kernel(sndrk_free_func, 2); + // CHECK: store i8 1, ptr addrspace(4) %b1{{.*}}, align 1 + bool b2 = __builtin_sycl_is_nd_range_kernel(*sndrk_free_func, 2); + // CHECK: store i8 1, ptr addrspace(4) %b2{{.*}}, align 1 + bool b3 = __builtin_sycl_is_nd_range_kernel(&sndrk_free_func, 2); + // CHECK: store i8 1, ptr addrspace(4) %b3{{.*}}, align 1 + bool b4 = __builtin_sycl_is_nd_range_kernel(func, 3); + // CHECK: store i8 0, ptr addrspace(4) %b4{{.*}}, align 1 + constexpr bool b5 = __builtin_sycl_is_nd_range_kernel(sstk_free_func, 4); + // CHECK: store i8 0, ptr addrspace(4) %b5{{.*}}, align 1 + + // Constexpr forms of the valid cases. + constexpr bool b6 = __builtin_sycl_is_nd_range_kernel(sndrk_free_func, 2); // Okay and true. + // CHECK: store i8 1, ptr addrspace(4) %b6{{.*}}, align 1 + constexpr bool b7 = __builtin_sycl_is_nd_range_kernel(func, 3); // Okay, but false. + // CHECK: store i8 0, ptr addrspace(4) %b7{{.*}}, align 1 + constexpr bool b8 = __builtin_sycl_is_nd_range_kernel(sstk_free_func, 2); // Okay, but false. + // CHECK: store i8 0, ptr addrspace(4) %b8{{.*}}, align 1 + + // Test function template. + constexpr bool b9 = __builtin_sycl_is_nd_range_kernel((void(*)(int *))sndrk_free_func_tmpl, 4); // Okay + // CHECK: store i8 1, ptr addrspace(4) %b9{{.*}}, align 1 + + // Test overloaded functions. + constexpr bool b10 = __builtin_sycl_is_nd_range_kernel((void(*)(int *))ovl_free_func, 1); // Okay + // CHECK: store i8 1, ptr addrspace(4) %b10{{.*}}, align 1 + constexpr bool b11 = __builtin_sycl_is_nd_range_kernel((void(*)(int *, int))ovl_free_func, 1); // Okay + // CHECK: store i8 0, ptr addrspace(4) %b11{{.*}}, align 1 +} + +void f() { + auto L = []() { foo(); }; + q.submit([&](handler &h) { + h.single_task(L); + }); +} diff --git a/clang/test/CodeGenSYCL/builtin_sycl_single_task_kernel.cpp b/clang/test/CodeGenSYCL/builtin_sycl_single_task_kernel.cpp new file mode 100644 index 0000000000000..0f9ce56a05d39 --- /dev/null +++ b/clang/test/CodeGenSYCL/builtin_sycl_single_task_kernel.cpp @@ -0,0 +1,79 @@ +// RUN: %clang_cc1 -internal-isystem %S/Inputs -fsycl-is-device -triple spir64-unknown-unknown -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s + +// This test tests the builtin __builtin_sycl_is_single_task_kernel + +#include "sycl.hpp" + +using namespace sycl; +queue q; + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 0)]] +void sstk_free_func() { +} + +template +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 4)]] +void sstk_free_func_tmpl(T *ptr) { + for (int i = 0; i <= 7; i++) + ptr[i] = i + 11; +} + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 1)]] +void ovl_free_func(int *ptr) { + for (int i = 0; i <= 7; i++) + ptr[i] = i; +} + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 1)]] +void ovl_free_func(int *ptr, int val) { + for (int i = 0; i <= 7; i++) + ptr[i] = i + val; +} + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 4)]] +void sndrk_free_func() { +} + +void func() {} + +void foo() { + bool b1 = __builtin_sycl_is_single_task_kernel(sstk_free_func); + // CHECK: store i8 1, ptr addrspace(4) %b1{{.*}}, align 1 + bool b2 = __builtin_sycl_is_single_task_kernel(*sstk_free_func); + // CHECK: store i8 1, ptr addrspace(4) %b2{{.*}}, align 1 + bool b3 = __builtin_sycl_is_single_task_kernel(&sstk_free_func); + // CHECK: store i8 1, ptr addrspace(4) %b3{{.*}}, align 1 + bool b4 = __builtin_sycl_is_single_task_kernel(func); + // CHECK: store i8 0, ptr addrspace(4) %b4{{.*}}, align 1 + bool b5 = __builtin_sycl_is_single_task_kernel(sndrk_free_func); + // CHECK: store i8 0, ptr addrspace(4) %b5{{.*}}, align 1 + + // Constexpr forms of the valid cases. + constexpr bool b6 = __builtin_sycl_is_single_task_kernel(sstk_free_func); // Okay and true. + // CHECK: store i8 1, ptr addrspace(4) %b6{{.*}}, align 1 + constexpr bool b7 = __builtin_sycl_is_single_task_kernel(func); // Okay, but false. + // CHECK: store i8 0, ptr addrspace(4) %b7{{.*}}, align 1 + constexpr bool b8 = __builtin_sycl_is_single_task_kernel(sndrk_free_func); // Okay, but false. + // CHECK: store i8 0, ptr addrspace(4) %b8{{.*}}, align 1 + + // Test function template. + constexpr bool b9 = __builtin_sycl_is_single_task_kernel((void(*)(int *))sstk_free_func_tmpl); // Okay + // CHECK: store i8 1, ptr addrspace(4) %b9{{.*}}, align 1 + + // Test overloaded functions. + constexpr bool b10 = __builtin_sycl_is_single_task_kernel((void(*)(int *))ovl_free_func); // Okay + // CHECK: store i8 1, ptr addrspace(4) %b10{{.*}}, align 1 + constexpr bool b11 = __builtin_sycl_is_single_task_kernel((void(*)(int *, int))ovl_free_func); // Okay + // CHECK: store i8 0, ptr addrspace(4) %b11{{.*}}, align 1 +} + +void f() { + auto L = []() { foo(); }; + q.submit([&](handler &h) { + h.single_task(L); + }); +} diff --git a/clang/test/SemaSYCL/builtin_sycl_kernel.cpp b/clang/test/SemaSYCL/builtin_sycl_kernel.cpp new file mode 100644 index 0000000000000..2b41307286cde --- /dev/null +++ b/clang/test/SemaSYCL/builtin_sycl_kernel.cpp @@ -0,0 +1,90 @@ +// RUN: %clang_cc1 -internal-isystem %S/Inputs -fsycl-is-device %s -verify + +// This test tests the builtin __builtin_sycl_is_kernel + +#include "sycl.hpp" + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 4)]] +void sndrk_free_func1(int *ptr, int start, int end) { + for (int i = start; i <= end; i++) + ptr[i] = start; +} + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", "")]] +void sstk_free_func1(int *ptr, int start, int end) { + for (int i = start; i <= end; i++) + ptr[i] = start; +} + +template +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 4)]] +void sndrk_free_func_tmpl1(T *ptr) { + for (int i = 0; i <= 7; i++) + ptr[i] = i + 11; +} + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 1)]] +void ovl_free_func1(int *ptr) { + for (int i = 0; i <= 7; i++) + ptr[i] = i; +} + +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 1)]] +void ovl_free_func1(int *ptr, int val) { + for (int i = 0; i <= 7; i++) + ptr[i] = i + val; +} + +void func(int *ptr, int start, int end) {} + +void foo() { + // Check number of arguments. + // expected-error@+1 {{builtin takes one argument}} + bool b1 = __builtin_sycl_is_kernel(); + // expected-error@+1 {{builtin takes one argument}} + bool b2 = __builtin_sycl_is_kernel(sndrk_free_func1, 3); + + + // The following four are okay. + bool b3 = __builtin_sycl_is_kernel(sndrk_free_func1); // Okay + bool b4 = __builtin_sycl_is_kernel(*sndrk_free_func1); // Okay + bool b5 = __builtin_sycl_is_kernel(&sndrk_free_func1); // Okay + bool b6 = __builtin_sycl_is_kernel(func); // Okay + + // But the next two are not. + // expected-error@+1 {{use of undeclared identifier 'undef'}} + bool b7 = __builtin_sycl_is_kernel(undef); + // expected-error@+1 {{use of undeclared identifier 'laterdef'}} + bool b8 = __builtin_sycl_is_kernel(laterdef); + + // Constexpr forms of the valid cases. + constexpr bool b9 = __builtin_sycl_is_kernel(sndrk_free_func1); // Okay and true. + constexpr bool b10 = __builtin_sycl_is_kernel(func); // Okay, but false. + constexpr bool b11 = __builtin_sycl_is_kernel(sstk_free_func1); // Okay and true. + constexpr bool b12 = __builtin_sycl_is_kernel(sndrk_free_func1); // Okay and true. + + // expected-error@+1 {{constexpr variable 'b13' must be initialized by a constant expression}} + constexpr bool b13 = __builtin_sycl_is_kernel(*sndrk_free_func1); + // expected-error@+1 {{constexpr variable 'b14' must be initialized by a constant expression}} + constexpr bool b14 = __builtin_sycl_is_kernel(&sndrk_free_func1); + + // Test with function templates. + // expected-error@+1 {{1st argument must be a function pointer (was '')}} + constexpr bool b15 = __builtin_sycl_is_kernel(&sndrk_free_func_tmpl1); + // expected-error@+1 {{1st argument must be a function pointer (was '')}} + constexpr bool b16 = __builtin_sycl_is_kernel(sndrk_free_func_tmpl1); + constexpr bool b17 = __builtin_sycl_is_kernel((void(*)(int *))sndrk_free_func_tmpl1); // Okay + + + // Test with overloaded functions. + // expected-error@+1 {{1st argument must be a function pointer (was '')}} + constexpr bool b18 = __builtin_sycl_is_kernel(ovl_free_func1); + constexpr bool b19 = __builtin_sycl_is_kernel((void(*)(int *))ovl_free_func1); // Okay + constexpr bool b20 = __builtin_sycl_is_kernel((void(*)(int *, int))ovl_free_func1); // Okay +} + +void laterdef(); diff --git a/clang/test/SemaSYCL/builtin_sycl_nd_range_kernel.cpp b/clang/test/SemaSYCL/builtin_sycl_nd_range_kernel.cpp new file mode 100644 index 0000000000000..4af42377fb9d2 --- /dev/null +++ b/clang/test/SemaSYCL/builtin_sycl_nd_range_kernel.cpp @@ -0,0 +1,95 @@ +// RUN: %clang_cc1 -internal-isystem %S/Inputs -fsycl-is-device %s -verify + +// This test tests the builtin __builtin_sycl_is_nd_range_kernel + +#include "sycl.hpp" + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 4)]] +void sndrk_free_func1(int *ptr, int start, int end) { + for (int i = start; i <= end; i++) + ptr[i] = start; +} + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", "")]] +void sstk_free_func1(int *ptr, int start, int end) { + for (int i = start; i <= end; i++) + ptr[i] = start; +} + +template +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 4)]] +void sndrk_free_func_tmpl1(T *ptr) { + for (int i = 0; i <= 7; i++) + ptr[i] = i + 11; +} + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 1)]] +void ovl_free_func1(int *ptr) { + for (int i = 0; i <= 7; i++) + ptr[i] = i; +} + +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 1)]] +void ovl_free_func1(int *ptr, int val) { + for (int i = 0; i <= 7; i++) + ptr[i] = i + val; +} + +void func(int *ptr, int start, int end) {} + +void foo() { + // Check number of arguments. + // expected-error@+1 {{builtin requires exactly 2 arguments}} + bool b1 = __builtin_sycl_is_nd_range_kernel(); + // expected-error@+1 {{builtin requires exactly 2 arguments}} + bool b2 = __builtin_sycl_is_nd_range_kernel(sndrk_free_func1); + + // The following four are okay. + bool b3 = __builtin_sycl_is_nd_range_kernel(sndrk_free_func1, 4); // Okay + bool b4 = __builtin_sycl_is_nd_range_kernel(*sndrk_free_func1, 4); // Okay + bool b5 = __builtin_sycl_is_nd_range_kernel(&sndrk_free_func1, 4); // Okay + bool b6 = __builtin_sycl_is_nd_range_kernel(func, 8); // Okay + + // But the next two are not. + // expected-error@+1 {{use of undeclared identifier 'undef'}} + bool b7 = __builtin_sycl_is_nd_range_kernel(undef); + // expected-error@+1 {{use of undeclared identifier 'laterdef'}} + bool b8 = __builtin_sycl_is_nd_range_kernel(laterdef); + + // Constexpr forms of the valid cases. + constexpr bool b9 = __builtin_sycl_is_nd_range_kernel(sndrk_free_func1, 4); // Okay and true. + constexpr bool b10 = __builtin_sycl_is_nd_range_kernel(func, 4); // Okay, but false. + constexpr bool b11 = __builtin_sycl_is_nd_range_kernel(sstk_free_func1, 4); // Okay, but false. + constexpr bool b12 = __builtin_sycl_is_nd_range_kernel(sndrk_free_func1, 8); // Okay, but false. + + // expected-error@+1 {{constexpr variable 'b13' must be initialized by a constant expression}} + constexpr bool b13 = __builtin_sycl_is_nd_range_kernel(*sndrk_free_func1, 4); // Okay + // expected-error@+1 {{constexpr variable 'b14' must be initialized by a constant expression}} + constexpr bool b14 = __builtin_sycl_is_nd_range_kernel(&sndrk_free_func1, 4); // Okay + + // Test with function templates. + // expected-error@+1 {{1st argument must be a function pointer (was '')}} + constexpr bool b15 = __builtin_sycl_is_nd_range_kernel(&sndrk_free_func_tmpl1, 6); + // expected-error@+1 {{1st argument must be a function pointer (was '')}} + constexpr bool b16 = __builtin_sycl_is_nd_range_kernel(sndrk_free_func_tmpl1, 8); + constexpr bool b17 = __builtin_sycl_is_nd_range_kernel((void(*)(int *))sndrk_free_func_tmpl1, 12); // Okay + + + // Test with overloaded functions. + // expected-error@+1 {{1st argument must be a function pointer (was '')}} + constexpr bool b18 = __builtin_sycl_is_nd_range_kernel(ovl_free_func1, 4); + constexpr bool b19 = __builtin_sycl_is_nd_range_kernel((void(*)(int *))ovl_free_func1, 2); // Okay + constexpr bool b20 = __builtin_sycl_is_nd_range_kernel((void(*)(int *, int))ovl_free_func1, 2); // Okay + + // Test with invalid dimensions. + // expected-error@+1 {{2nd argument must be a strictly positive value (was -1)}} + bool b21 = __builtin_sycl_is_nd_range_kernel(sndrk_free_func1, -1); + // expected-error@+1 {{2nd argument must be a strictly positive value (was 0)}} + bool b22 = __builtin_sycl_is_nd_range_kernel(sndrk_free_func1, 0); +} + +void laterdef(); diff --git a/clang/test/SemaSYCL/builtin_sycl_single_task_kernel.cpp b/clang/test/SemaSYCL/builtin_sycl_single_task_kernel.cpp new file mode 100644 index 0000000000000..6a9111dd37b17 --- /dev/null +++ b/clang/test/SemaSYCL/builtin_sycl_single_task_kernel.cpp @@ -0,0 +1,90 @@ +// RUN: %clang_cc1 -internal-isystem %S/Inputs -fsycl-is-device %s -verify + +// This test tests the builtin __builtin_sycl_is_single_task_kernel + +#include "sycl.hpp" + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 0)]] +void sstk_free_func1(int *ptr, int start, int end) { + for (int i = start; i <= end; i++) + ptr[i] = start; +} + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", "")]] +void sndrk_free_func1(int *ptr, int start, int end) { + for (int i = start; i <= end; i++) + ptr[i] = start; +} + +template +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 4)]] +void sstk_free_func_tmpl1(T *ptr) { + for (int i = 0; i <= 7; i++) + ptr[i] = i + 11; +} + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 1)]] +void ovl_free_func1(int *ptr) { + for (int i = 0; i <= 7; i++) + ptr[i] = i; +} + +__attribute__((sycl_device)) +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 1)]] +void ovl_free_func1(int *ptr, int val) { + for (int i = 0; i <= 7; i++) + ptr[i] = i + val; +} + +void func(int *ptr, int start, int end) {} + +void foo() { + // Check number of arguments. + // expected-error@+1 {{builtin takes one argument}} + bool b1 = __builtin_sycl_is_single_task_kernel(); + // expected-error@+1 {{builtin takes one argument}} + bool b2 = __builtin_sycl_is_single_task_kernel(sstk_free_func1, 4); + + + // The following four are okay. + bool b3 = __builtin_sycl_is_single_task_kernel(sstk_free_func1); // Okay + bool b4 = __builtin_sycl_is_single_task_kernel(*sstk_free_func1); // Okay + bool b5 = __builtin_sycl_is_single_task_kernel(&sstk_free_func1); // Okay + bool b6 = __builtin_sycl_is_single_task_kernel(func); // Okay + + // But the next two are not. + // expected-error@+1 {{use of undeclared identifier 'undef'}} + bool b7 = __builtin_sycl_is_single_task_kernel(undef); + // expected-error@+1 {{use of undeclared identifier 'laterdef'}} + bool b8 = __builtin_sycl_is_single_task_kernel(laterdef); + + // Constexpr forms of the valid cases. + constexpr bool b9 = __builtin_sycl_is_single_task_kernel(sstk_free_func1); // Okay and true. + constexpr bool b10 = __builtin_sycl_is_single_task_kernel(func); // Okay, but false. + constexpr bool b11 = __builtin_sycl_is_single_task_kernel(sndrk_free_func1); // Okay, but false. + + // expected-error@+1 {{constexpr variable 'b12' must be initialized by a constant expression}} + constexpr bool b12 = __builtin_sycl_is_single_task_kernel(*sstk_free_func1); // Okay + // expected-error@+1 {{constexpr variable 'b13' must be initialized by a constant expression}} + constexpr bool b13 = __builtin_sycl_is_single_task_kernel(&sstk_free_func1); // Okay + + // Test with function templates. + // expected-error@+1 {{1st argument must be a function pointer (was '')}} + constexpr bool b14 = __builtin_sycl_is_single_task_kernel(&sstk_free_func_tmpl1); + // expected-error@+1 {{1st argument must be a function pointer (was '')}} + constexpr bool b15 = __builtin_sycl_is_single_task_kernel(sstk_free_func_tmpl1); + constexpr bool b16 = __builtin_sycl_is_single_task_kernel((void(*)(int *))sstk_free_func_tmpl1); // Okay + + + // Test with overloaded functions. + // expected-error@+1 {{1st argument must be a function pointer (was '')}} + constexpr bool b17 = __builtin_sycl_is_single_task_kernel(ovl_free_func1); + constexpr bool b18 = __builtin_sycl_is_single_task_kernel((void(*)(int *))ovl_free_func1); // Okay + constexpr bool b19 = __builtin_sycl_is_single_task_kernel((void(*)(int *, int))ovl_free_func1); // Okay +} + +void laterdef();