Skip to content

Commit 0bc608d

Browse files
kbobrovsDenisBakhvalov
authored andcommitted
[SYCL][ESIMD] Mark ESIMD kernel callgraph with sycl_explicit_simd.
Traverse callgraph from ESIMD kernels and mark all functions with sycl_explicit_simd along the way. ESIMD code generation depends on presence of this attribute, which will be used to distinguish normal from ESIMD code. Author: Denis Bakhvalov <denis.bakhvalov@intel.com>. Signed-off-by: Konstantin S Bobrovsky <konstantin.s.bobrovsky@intel.com>
1 parent 1b762a8 commit 0bc608d

File tree

5 files changed

+73
-2
lines changed

5 files changed

+73
-2
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12696,6 +12696,7 @@ class Sema final {
1269612696
void checkSYCLDeviceVarDecl(VarDecl *Var);
1269712697
void ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc, MangleContext &MC);
1269812698
void MarkDevice();
12699+
void MarkSyclSimd();
1269912700

1270012701
/// Creates a DeviceDiagBuilder that emits the diagnostic if the current
1270112702
/// context is "used as device code".

clang/lib/Sema/Sema.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,8 @@ void Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) {
990990
SyclIntHeader->emit(getLangOpts().SYCLIntHeader);
991991
MarkDevice();
992992
}
993+
if (getLangOpts().SYCLExplicitSIMD)
994+
MarkSyclSimd();
993995

994996
emitDeferredDiags();
995997

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1900,6 +1900,27 @@ void Sema::ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc,
19001900
ConstructingOpenCLKernel = false;
19011901
}
19021902

1903+
// This function marks all the callees of explicit SIMD kernel
1904+
// with !sycl_explicit_simd. We want to have different semantics
1905+
// for functions that are called from SYCL and E-SIMD contexts.
1906+
// Later, functions marked with !sycl_explicit_simd will be cloned
1907+
// to maintain two different semantics.
1908+
void Sema::MarkSyclSimd() {
1909+
for (Decl *D : syclDeviceDecls())
1910+
if (auto SYCLKernel = dyn_cast<FunctionDecl>(D))
1911+
if (SYCLKernel->hasAttr<SYCLSimdAttr>()) {
1912+
MarkDeviceFunction Marker(*this);
1913+
Marker.SYCLCG.addToCallGraph(getASTContext().getTranslationUnitDecl());
1914+
llvm::SmallPtrSet<FunctionDecl *, 10> VisitedSet;
1915+
Marker.CollectKernelSet(SYCLKernel, SYCLKernel, VisitedSet);
1916+
for (const auto &elt : Marker.KernelSet) {
1917+
if (FunctionDecl *Def = elt->getDefinition())
1918+
if (!Def->hasAttr<SYCLSimdAttr>())
1919+
Def->addAttr(SYCLSimdAttr::CreateImplicit(getASTContext()));
1920+
}
1921+
}
1922+
}
1923+
19031924
void Sema::MarkDevice(void) {
19041925
// Create the call graph so we can detect recursion and check the validity
19051926
// of new operator overrides. Add the kernel function itself in case
@@ -1910,7 +1931,8 @@ void Sema::MarkDevice(void) {
19101931
// Iterate through SYCL_EXTERNAL functions and add them to the device decls.
19111932
for (const auto &entry : *Marker.SYCLCG.getRoot()) {
19121933
if (auto *FD = dyn_cast<FunctionDecl>(entry.Callee->getDecl())) {
1913-
if (FD->hasAttr<SYCLDeviceAttr>() && !FD->hasAttr<SYCLKernelAttr>())
1934+
if (FD->hasAttr<SYCLDeviceAttr>() && !FD->hasAttr<SYCLKernelAttr>() &&
1935+
FD->hasBody())
19141936
addSyclDeviceDecl(FD);
19151937
}
19161938
}
@@ -1975,7 +1997,7 @@ void Sema::MarkDevice(void) {
19751997
case attr::Kind::SYCLIntelMaxWorkGroupSize:
19761998
case attr::Kind::SYCLIntelNoGlobalWorkOffset:
19771999
case attr::Kind::SYCLSimd: {
1978-
if ((A->getKind() == attr::Kind::SYCLSimd) &&
2000+
if ((A->getKind() == attr::Kind::SYCLSimd) && KernelBody &&
19792001
!KernelBody->getAttr<SYCLSimdAttr>()) {
19802002
// Usual kernel can't call ESIMD functions.
19812003
Diag(KernelBody->getLocation(),
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %clang_cc1 -disable-llvm-passes -triple spir64-unknown-unknown-sycldevice -fsycl -fsycl-is-device -fsycl-explicit-simd -S -emit-llvm %s -o - | FileCheck %s --check-prefixes CHECK,CHECK-ESIMD
2+
3+
// In ESIMD mode:
4+
// 1. Attribute !intel_reqd_sub_group_size !1 is added
5+
// for kernels with !sycl_explicit_simd
6+
// 2. Attribute !sycl_explicit_simd is propagated to all the
7+
// callees of ESIMD kernel.
8+
9+
__attribute__((sycl_device)) void shared_func_decl();
10+
__attribute__((sycl_device)) void shared_func() { shared_func_decl(); }
11+
12+
__attribute__((sycl_device)) __attribute__((sycl_explicit_simd)) void esimd_func() { shared_func(); }
13+
14+
// CHECK-ESIMD-DAG: define spir_kernel void @{{.*}}kernel_cm() #{{[0-9]+}} !sycl_explicit_simd !{{[0-9]+}} {{.*}} !intel_reqd_sub_group_size ![[SGSIZE1:[0-9]+]] {{.*}}{
15+
// CHECK-ESIMD-DAG: define spir_func void @{{.*}}esimd_funcv() #{{[0-9]+}} !sycl_explicit_simd !{{[0-9]+}} {
16+
// CHECK-ESIMD-DAG: define spir_func void @{{.*}}shared_funcv() #{{[0-9]+}} !sycl_explicit_simd !{{[0-9]+}} {
17+
// CHECK-ESIMD-DAG: define linkonce_odr spir_func void @_ZN12ESIMDFunctorclEv({{.*}}) #{{[0-9]+}} {{.*}} !sycl_explicit_simd !{{[0-9]+}} {
18+
// CHECK-ESIMD-DAG: declare spir_func void @{{.*}}shared_func_declv() #{{[0-9]+}}
19+
20+
class ESIMDFunctor {
21+
public:
22+
void operator()() __attribute__((sycl_explicit_simd)) {
23+
esimd_func();
24+
}
25+
};
26+
27+
template <typename name, typename Func>
28+
__attribute__((sycl_kernel)) void kernel(Func kernelFunc) {
29+
kernelFunc();
30+
}
31+
32+
void bar() {
33+
ESIMDFunctor cmf;
34+
kernel<class kernel_cm>(cmf);
35+
}
36+
37+
// CHECK: !spirv.Source = !{[[LANG:![0-9]+]]}
38+
// CHECK: [[LANG]] = !{i32 6, i32 100000}
39+
// CHECK-ESIMD: ![[SGSIZE1]] = !{i32 1}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: %clang_cc1 -disable-llvm-passes -triple spir64-unknown-unknown-sycldevice -fsycl -fsycl-is-device -fsycl-explicit-simd -S -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK-ESIMD
2+
3+
__attribute__((sycl_device)) void funcWithSpirvIntrin() {}
4+
__attribute__((sycl_device)) __attribute__((sycl_explicit_simd)) void standaloneCmFunc() { funcWithSpirvIntrin(); }
5+
6+
// CHECK-ESIMD-DAG: define spir_func void @{{.*}}funcWithSpirvIntrinv() #{{[0-9]+}} !sycl_explicit_simd !{{[0-9]+}} {
7+
// CHECK-ESIMD-DAG: define spir_func void @{{.*}}standaloneCmFuncv() #{{[0-9]+}} !sycl_explicit_simd !{{[0-9]+}} {

0 commit comments

Comments
 (0)