Skip to content

Commit 14fd363

Browse files
authored
[SYCL][ESIMD] Mark ESIMD kernel callgraph with sycl_explicit_simd. (#2096)
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 <[email protected]>. Signed-off-by: Konstantin S Bobrovsky <[email protected]>
1 parent 5155bf9 commit 14fd363

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
@@ -12742,6 +12742,7 @@ class Sema final {
1274212742
void checkSYCLDeviceVarDecl(VarDecl *Var);
1274312743
void ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc, MangleContext &MC);
1274412744
void MarkDevice();
12745+
void MarkSyclSimd();
1274512746

1274612747
/// Creates a DeviceDiagBuilder that emits the diagnostic if the current
1274712748
/// 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
@@ -1969,6 +1969,27 @@ void Sema::ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc,
19691969
ConstructingOpenCLKernel = false;
19701970
}
19711971

1972+
// This function marks all the callees of explicit SIMD kernel
1973+
// with !sycl_explicit_simd. We want to have different semantics
1974+
// for functions that are called from SYCL and E-SIMD contexts.
1975+
// Later, functions marked with !sycl_explicit_simd will be cloned
1976+
// to maintain two different semantics.
1977+
void Sema::MarkSyclSimd() {
1978+
for (Decl *D : syclDeviceDecls())
1979+
if (auto SYCLKernel = dyn_cast<FunctionDecl>(D))
1980+
if (SYCLKernel->hasAttr<SYCLSimdAttr>()) {
1981+
MarkDeviceFunction Marker(*this);
1982+
Marker.SYCLCG.addToCallGraph(getASTContext().getTranslationUnitDecl());
1983+
llvm::SmallPtrSet<FunctionDecl *, 10> VisitedSet;
1984+
Marker.CollectKernelSet(SYCLKernel, SYCLKernel, VisitedSet);
1985+
for (const auto &elt : Marker.KernelSet) {
1986+
if (FunctionDecl *Def = elt->getDefinition())
1987+
if (!Def->hasAttr<SYCLSimdAttr>())
1988+
Def->addAttr(SYCLSimdAttr::CreateImplicit(getASTContext()));
1989+
}
1990+
}
1991+
}
1992+
19721993
void Sema::MarkDevice(void) {
19731994
// Create the call graph so we can detect recursion and check the validity
19741995
// of new operator overrides. Add the kernel function itself in case
@@ -1979,7 +2000,8 @@ void Sema::MarkDevice(void) {
19792000
// Iterate through SYCL_EXTERNAL functions and add them to the device decls.
19802001
for (const auto &entry : *Marker.SYCLCG.getRoot()) {
19812002
if (auto *FD = dyn_cast<FunctionDecl>(entry.Callee->getDecl())) {
1982-
if (FD->hasAttr<SYCLDeviceAttr>() && !FD->hasAttr<SYCLKernelAttr>())
2003+
if (FD->hasAttr<SYCLDeviceAttr>() && !FD->hasAttr<SYCLKernelAttr>() &&
2004+
FD->hasBody())
19832005
addSyclDeviceDecl(FD);
19842006
}
19852007
}
@@ -2044,7 +2066,7 @@ void Sema::MarkDevice(void) {
20442066
case attr::Kind::SYCLIntelMaxWorkGroupSize:
20452067
case attr::Kind::SYCLIntelNoGlobalWorkOffset:
20462068
case attr::Kind::SYCLSimd: {
2047-
if ((A->getKind() == attr::Kind::SYCLSimd) &&
2069+
if ((A->getKind() == attr::Kind::SYCLSimd) && KernelBody &&
20482070
!KernelBody->getAttr<SYCLSimdAttr>()) {
20492071
// Usual kernel can't call ESIMD functions.
20502072
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)