diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 8cbd33b279e8f..710afe5f543f2 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -514,52 +514,25 @@ class MarkDeviceFunction : public RecursiveASTVisitor { if (auto *A = FD->getAttr()) Attrs.insert(A); + if (auto *A = FD->getAttr()) Attrs.insert(A); - // Allow the following kernel attributes only on lambda functions and - // function objects that are called directly from a kernel (i.e. the one - // passed to the parallel_for function). For all other cases, - // emit a warning and ignore. - if (auto *A = FD->getAttr()) { - if (ParentFD == SYCLKernel) { - Attrs.insert(A); - } else { - SemaRef.Diag(A->getLocation(), diag::warn_attribute_ignored) << A; - FD->dropAttr(); - } - } - if (auto *A = FD->getAttr()) { - if (ParentFD == SYCLKernel) { - Attrs.insert(A); - } else { - SemaRef.Diag(A->getLocation(), diag::warn_attribute_ignored) << A; - FD->dropAttr(); - } - } - if (auto *A = FD->getAttr()) { - if (ParentFD == SYCLKernel) { - Attrs.insert(A); - } else { - SemaRef.Diag(A->getLocation(), diag::warn_attribute_ignored) << A; - FD->dropAttr(); - } - } - if (auto *A = FD->getAttr()) { - if (ParentFD == SYCLKernel) { - Attrs.insert(A); - } else { - SemaRef.Diag(A->getLocation(), diag::warn_attribute_ignored) << A; - FD->dropAttr(); - } - } - if (auto *A = FD->getAttr()) { - if (ParentFD == SYCLKernel) { - Attrs.insert(A); - } else { - SemaRef.Diag(A->getLocation(), diag::warn_attribute_ignored) << A; - FD->dropAttr(); - } - } + + if (auto *A = FD->getAttr()) + Attrs.insert(A); + + if (auto *A = FD->getAttr()) + Attrs.insert(A); + + if (auto *A = FD->getAttr()) + Attrs.insert(A); + + if (auto *A = FD->getAttr()) + Attrs.insert(A); + + if (auto *A = FD->getAttr()) + Attrs.insert(A); + if (auto *A = FD->getAttr()) Attrs.insert(A); // Propagate the explicit SIMD attribute through call graph - it is used @@ -2054,6 +2027,38 @@ void Sema::MarkDevice(void) { Diag(Attr->getLocation(), diag::note_conflicting_attribute); SYCLKernel->setInvalidDecl(); } + } else if (auto *Existing = + SYCLKernel->getAttr()) { + if (Existing->getXDim() < Attr->getXDim() || + Existing->getYDim() < Attr->getYDim() || + Existing->getZDim() < Attr->getZDim()) { + Diag(SYCLKernel->getLocation(), + diag::err_conflicting_sycl_kernel_attributes); + Diag(Existing->getLocation(), diag::note_conflicting_attribute); + Diag(Attr->getLocation(), diag::note_conflicting_attribute); + SYCLKernel->setInvalidDecl(); + } else { + SYCLKernel->addAttr(A); + } + } else { + SYCLKernel->addAttr(A); + } + break; + } + case attr::Kind::SYCLIntelMaxWorkGroupSize: { + auto *Attr = cast(A); + if (auto *Existing = SYCLKernel->getAttr()) { + if (Existing->getXDim() > Attr->getXDim() || + Existing->getYDim() > Attr->getYDim() || + Existing->getZDim() > Attr->getZDim()) { + Diag(SYCLKernel->getLocation(), + diag::err_conflicting_sycl_kernel_attributes); + Diag(Existing->getLocation(), diag::note_conflicting_attribute); + Diag(Attr->getLocation(), diag::note_conflicting_attribute); + SYCLKernel->setInvalidDecl(); + } else { + SYCLKernel->addAttr(A); + } } else { SYCLKernel->addAttr(A); } @@ -2062,7 +2067,6 @@ void Sema::MarkDevice(void) { case attr::Kind::SYCLIntelKernelArgsRestrict: case attr::Kind::SYCLIntelNumSimdWorkItems: case attr::Kind::SYCLIntelMaxGlobalWorkDim: - case attr::Kind::SYCLIntelMaxWorkGroupSize: case attr::Kind::SYCLIntelNoGlobalWorkOffset: case attr::Kind::SYCLSimd: { if ((A->getKind() == attr::Kind::SYCLSimd) && KernelBody && diff --git a/clang/test/SemaSYCL/check-notdirect-attribute-propagation.cpp b/clang/test/SemaSYCL/check-notdirect-attribute-propagation.cpp new file mode 100644 index 0000000000000..3dd98f12b0120 --- /dev/null +++ b/clang/test/SemaSYCL/check-notdirect-attribute-propagation.cpp @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 %s -fsyntax-only -fsycl -fsycl-is-device -triple spir64 -verify +// RUN: %clang_cc1 %s -fsyntax-only -fsycl -fsycl-is-device -triple spir64 -DTRIGGER_ERROR -verify +// RUN: %clang_cc1 %s -fsyntax-only -ast-dump -fsycl -fsycl-is-device -triple spir64 | FileCheck %s + +#ifndef TRIGGER_ERROR +[[intelfpga::no_global_work_offset]] void not_direct_one() {} // expected-no-diagnostics + +[[intel::reqd_sub_group_size(1)]] void func_one() { + not_direct_one(); +} + +#else +[[cl::reqd_work_group_size(2, 2, 2)]] void not_direct_two() {} // expected-note {{conflicting attribute is here}} + +[[intelfpga::max_work_group_size(1, 1, 1)]] // expected-note {{conflicting attribute is here}} +void +func_two() { + not_direct_two(); +} + +[[cl::reqd_work_group_size(4, 4, 4)]] // expected-note 2 {{conflicting attribute is here}} +void +func_three() { + not_direct_two(); +} +#endif + +template +[[clang::sycl_kernel]] void __my_kernel__(Type bar) { + bar(); +#ifndef TRIGGER_ERROR + func_one(); +#else + func_two(); + func_three(); +#endif +} + +template +void parallel_for(Type lambda) { + __my_kernel__(lambda); +} + +void invoke_foo2() { +#ifndef TRIGGER_ERROR + // CHECK-LABEL: FunctionDecl {{.*}} invoke_foo2 'void ()' + // CHECK: `-FunctionDecl {{.*}}KernelName 'void ()' + // CHECK: -IntelReqdSubGroupSizeAttr {{.*}} + // CHECK: `-SYCLIntelNoGlobalWorkOffsetAttr {{.*}} Enabled + parallel_for([]() {}); +#else + parallel_for([]() {}); // expected-error 2 {{conflicting attributes applied to a SYCL kernel or SYCL_EXTERNAL function}} +#endif +} diff --git a/clang/test/SemaSYCL/intel-max-global-work-dim.cpp b/clang/test/SemaSYCL/intel-max-global-work-dim.cpp index 85db992f46cca..d391924773f1e 100644 --- a/clang/test/SemaSYCL/intel-max-global-work-dim.cpp +++ b/clang/test/SemaSYCL/intel-max-global-work-dim.cpp @@ -20,8 +20,7 @@ void foo() { #else // __SYCL_DEVICE_ONLY__ -[[intelfpga::max_global_work_dim(2)]] // expected-warning{{'max_global_work_dim' attribute ignored}} -void func_ignore() {} +[[intelfpga::max_global_work_dim(2)]] void func_do_not_ignore() {} struct FuncObj { [[intelfpga::max_global_work_dim(1)]] @@ -68,9 +67,9 @@ int main() { []() [[intelfpga::max_global_work_dim(2)]] {}); // CHECK-LABEL: FunctionDecl {{.*}}test_kernel3 - // CHECK-NOT: SYCLIntelMaxGlobalWorkDimAttr {{.*}} + // CHECK: SYCLIntelMaxGlobalWorkDimAttr {{.*}} kernel( - []() {func_ignore();}); + []() { func_do_not_ignore(); }); kernel( TRIFuncObjGood1()); diff --git a/clang/test/SemaSYCL/intel-max-work-group-size.cpp b/clang/test/SemaSYCL/intel-max-work-group-size.cpp index 441c1fea7df7e..f5b2a67599e8b 100644 --- a/clang/test/SemaSYCL/intel-max-work-group-size.cpp +++ b/clang/test/SemaSYCL/intel-max-work-group-size.cpp @@ -20,8 +20,7 @@ void foo() { #else // __SYCL_DEVICE_ONLY__ -[[intelfpga::max_work_group_size(2, 2, 2)]] // expected-warning{{'max_work_group_size' attribute ignored}} -void func_ignore() {} +[[intelfpga::max_work_group_size(2, 2, 2)]] void func_do_not_ignore() {} struct FuncObj { [[intelfpga::max_work_group_size(4, 4, 4)]] @@ -53,9 +52,9 @@ int main() { []() [[intelfpga::max_work_group_size(8, 8, 8)]] {}); // CHECK-LABEL: FunctionDecl {{.*}}test_kernel3 - // CHECK-NOT: SYCLIntelMaxWorkGroupSizeAttr {{.*}} + // CHECK: SYCLIntelMaxWorkGroupSizeAttr {{.*}} kernel( - []() {func_ignore();}); + []() { func_do_not_ignore(); }); #ifdef TRIGGER_ERROR [[intelfpga::max_work_group_size(1, 1, 1)]] int Var = 0; // expected-error{{'max_work_group_size' attribute only applies to functions}} diff --git a/clang/test/SemaSYCL/intel-restrict.cpp b/clang/test/SemaSYCL/intel-restrict.cpp index 810e7b0b3a5d3..b998b261f4320 100644 --- a/clang/test/SemaSYCL/intel-restrict.cpp +++ b/clang/test/SemaSYCL/intel-restrict.cpp @@ -1,8 +1,7 @@ // RUN: %clang_cc1 %s -fsyntax-only -fsycl -fsycl-is-device -triple spir64 -DCHECKDIAG -verify // RUN: %clang_cc1 %s -fsyntax-only -ast-dump -fsycl -fsycl-is-device -triple spir64 | FileCheck %s -[[intel::kernel_args_restrict]] // expected-warning{{'kernel_args_restrict' attribute ignored}} -void func_ignore() {} +[[intel::kernel_args_restrict]] void func_do_not_ignore() {} struct FuncObj { [[intel::kernel_args_restrict]] @@ -29,7 +28,7 @@ int main() { []() [[intel::kernel_args_restrict]] {}); // CHECK-LABEL: FunctionDecl {{.*}}test_kernel3 - // CHECK-NOT: SYCLIntelKernelArgsRestrictAttr + // CHECK: SYCLIntelKernelArgsRestrictAttr kernel( - []() {func_ignore();}); + []() { func_do_not_ignore(); }); } diff --git a/clang/test/SemaSYCL/num_simd_work_items.cpp b/clang/test/SemaSYCL/num_simd_work_items.cpp index 4eaf95080e275..638539917a283 100644 --- a/clang/test/SemaSYCL/num_simd_work_items.cpp +++ b/clang/test/SemaSYCL/num_simd_work_items.cpp @@ -20,8 +20,7 @@ void foo() { #else // __SYCL_DEVICE_ONLY__ -[[intelfpga::num_simd_work_items(2)]] // expected-warning{{'num_simd_work_items' attribute ignored}} -void func_ignore() {} +[[intelfpga::num_simd_work_items(2)]] void func_do_not_ignore() {} struct FuncObj { [[intelfpga::num_simd_work_items(42)]] @@ -45,9 +44,9 @@ int main() { []() [[intelfpga::num_simd_work_items(8)]] {}); // CHECK-LABEL: FunctionDecl {{.*}}test_kernel3 - // CHECK-NOT: SYCLIntelNumSimdWorkItemsAttr {{.*}} 2 + // CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}} 2 kernel( - []() {func_ignore();}); + []() { func_do_not_ignore(); }); #ifdef TRIGGER_ERROR [[intelfpga::num_simd_work_items(0)]] int Var = 0; // expected-error{{'num_simd_work_items' attribute only applies to functions}}