Skip to content

Commit 385d0e0

Browse files
committed
Reimplement the fix as a compiler pass
1 parent 00a1f80 commit 385d0e0

File tree

8 files changed

+231
-227
lines changed

8 files changed

+231
-227
lines changed

llvm/include/llvm/SYCLLowerIR/ESIMD/ESIMDUtils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ namespace llvm {
1616
namespace esimd {
1717

1818
constexpr char ATTR_DOUBLE_GRF[] = "esimd-double-grf";
19+
constexpr char ATTR_ESIMD_KERNEL[] = "sycl_explicit_simd";
1920

2021
using CallGraphNodeAction = std::function<void(Function *)>;
2122
void traverseCallgraphUp(llvm::Function *F, CallGraphNodeAction NodeF,
@@ -34,6 +35,8 @@ void traverseCallgraphUp(Function *F, CallGraphNodeActionF ActionF,
3435

3536
// Tells whether given function is a ESIMD kernel.
3637
bool isESIMDKernel(const Function &F);
38+
// Tells whether given function is a ESIMD function.
39+
bool isESIMD(const Function &F);
3740

3841
/// Reports and error with the message \p Msg concatenated with the optional
3942
/// \p OptMsg if \p Condition is false.

llvm/include/llvm/SYCLLowerIR/ESIMD/LowerESIMD.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ class SYCLLowerESIMDKernelPropsPass
7676
PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
7777
};
7878

79+
// Fixes ESIMD Kernel attributes for wrapper functions for ESIMD kernels
80+
class SYCLLowerESIMDKernelAttrPass
81+
: public PassInfoMixin<SYCLLowerESIMDKernelPropsPass> {
82+
public:
83+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
84+
};
7985
} // namespace llvm
8086

8187
#endif // LLVM_SYCLLOWERIR_LOWERESIMD_H

llvm/lib/Passes/PassRegistry.def

Lines changed: 123 additions & 159 deletions
Large diffs are not rendered by default.

llvm/lib/SYCLLowerIR/CMakeLists.txt

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
if(${CMAKE_VERSION} VERSION_LESS 3.14)
1+
if (${CMAKE_VERSION} VERSION_LESS 3.14)
22
macro(FetchContent_MakeAvailable NAME)
33
FetchContent_GetProperties(${NAME})
44
if(NOT ${NAME}_POPULATED)
@@ -8,14 +8,14 @@ if(${CMAKE_VERSION} VERSION_LESS 3.14)
88
endmacro()
99
endif()
1010

11-
# Lowering of SYCL ESIMD kernels depends on vc-intrinsics
12-
# NOTE: could have been added earlier from llvm/projects
11+
#Lowering of SYCL ESIMD kernels depends on vc - intrinsics
12+
#NOTE : could have been added earlier from llvm / projects
1313
if (NOT TARGET LLVMGenXIntrinsics)
1414
if (NOT DEFINED LLVMGenXIntrinsics_SOURCE_DIR)
1515
set(LLVMGenXIntrinsics_GIT_REPO https://github.com/intel/vc-intrinsics.git)
16-
# Author: Haohai Wen <[email protected]>
17-
# Date: Fri Jun 10 03:46:22 2022 +0000
18-
# Format InstructionSimplify names
16+
#Author : Haohai Wen < haohai.wen @intel.com>
17+
#Date : Fri Jun 10 03 : 46 : 22 2022 + 0000
18+
#Format InstructionSimplify names
1919
set(LLVMGenXIntrinsics_GIT_TAG abce9184b7a3a7fe1b02289b9285610d9dc45465)
2020

2121
message(STATUS "vc-intrinsics repo is missing. Will try to download it from ${LLVMGenXIntrinsics_GIT_REPO}")
@@ -30,7 +30,7 @@ if (NOT TARGET LLVMGenXIntrinsics)
3030
set(LLVMGenXIntrinsics_SOURCE_DIR ${vc-intrinsics_SOURCE_DIR})
3131
set(LLVMGenXIntrinsics_BINARY_DIR ${vc-intrinsics_BINARY_DIR})
3232
else (NOT DEFINED LLVMGenXIntrinsics_SOURCE_DIR)
33-
# -DLLVMGenXIntrinsics_SOURCE_DIR is provided
33+
#- DLLVMGenXIntrinsics_SOURCE_DIR is provided
3434
message(STATUS "vc-intrinsics are added manually ${LLVMGenXIntrinsics_SOURCE_DIR}")
3535

3636
set(LLVMGenXIntrinsics_BINARY_DIR ${CMAKE_BINARY_DIR}/vc-intrinsics-build)
@@ -53,6 +53,7 @@ add_llvm_component_library(LLVMSYCLLowerIR
5353
ESIMD/LowerESIMDVecArg.cpp
5454
ESIMD/ESIMDUtils.cpp
5555
ESIMD/ESIMDVerifier.cpp
56+
ESIMD/LowerESIMDKernelAttrs.cpp
5657
LowerInvokeSimd.cpp
5758
LowerWGScope.cpp
5859
LowerWGLocalMemory.cpp
@@ -77,7 +78,7 @@ add_llvm_component_library(LLVMSYCLLowerIR
7778
LLVMGenXIntrinsics
7879
LLVMDemangle
7980
LLVMTransformUtils
80-
81+
8182
LINK_COMPONENTS
8283
Analysis
8384
Core

llvm/lib/SYCLLowerIR/ESIMD/ESIMDUtils.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,12 @@ void traverseCallgraphUp(llvm::Function *F, CallGraphNodeAction ActionF,
6969
}
7070
}
7171

72+
bool isESIMD(const Function &F) {
73+
return F.getMetadata(ATTR_ESIMD_KERNEL) != nullptr;
74+
}
75+
7276
bool isESIMDKernel(const Function &F) {
73-
return (F.getCallingConv() == CallingConv::SPIR_KERNEL) &&
74-
(F.getMetadata("sycl_explicit_simd") != nullptr);
77+
return (F.getCallingConv() == CallingConv::SPIR_KERNEL) && isESIMD(F);
7578
}
7679

7780
} // namespace esimd
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//===---- LowerESIMDKernelAttrs - lower __esimd_set_kernel_attributes ---===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
// Finds and adds sycl_explicit_simd attributes to wrapper functions that wrap
9+
// ESIMD kernel functions
10+
11+
#include "llvm/SYCLLowerIR/ESIMD/ESIMDUtils.h"
12+
#include "llvm/SYCLLowerIR/ESIMD/LowerESIMD.h"
13+
14+
#include "llvm/IR/Module.h"
15+
#include "llvm/Pass.h"
16+
17+
#define DEBUG_TYPE "LowerESIMDKernelAttrs"
18+
19+
using namespace llvm;
20+
21+
namespace llvm {
22+
PreservedAnalyses
23+
SYCLLowerESIMDKernelAttrPass::run(Module &M, ModuleAnalysisManager &MAM) {
24+
bool Modified = false;
25+
for (Function &F : M) {
26+
if (llvm::esimd::isESIMD(F)) {
27+
llvm::esimd::traverseCallgraphUp(&F, [&](Function *GraphNode) {
28+
if (!llvm::esimd::isESIMD(*GraphNode)) {
29+
GraphNode->setMetadata(
30+
llvm::esimd::ATTR_ESIMD_KERNEL,
31+
llvm::MDNode::get(GraphNode->getContext(), {}));
32+
Modified = true;
33+
}
34+
});
35+
}
36+
}
37+
return Modified ? PreservedAnalyses::none() : PreservedAnalyses::all();
38+
}
39+
} // namespace llvm

llvm/tools/sycl-post-link/ModuleSplitter.cpp

Lines changed: 42 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -136,63 +136,6 @@ bool isEntryPoint(const Function &F, bool EmitOnlyKernelsAsEntryPoints) {
136136
bool isESIMDFunction(const Function &F) {
137137
return F.getMetadata(ESIMD_MARKER_MD) != nullptr;
138138
}
139-
// Represents a call graph between functions in a module. Nodes are functions,
140-
// edges are "calls" relation.
141-
class CallGraph {
142-
public:
143-
using FunctionSet = SmallPtrSet<const Function *, 16>;
144-
145-
private:
146-
std::unordered_map<const Function *, FunctionSet> Graph;
147-
SmallPtrSet<const Function *, 1> EmptySet;
148-
FunctionSet AddrTakenFunctions;
149-
150-
public:
151-
CallGraph(const Module &M) {
152-
for (const auto &F : M) {
153-
for (const Value *U : F.users()) {
154-
if (const auto *I = dyn_cast<CallInst>(U)) {
155-
if (I->getCalledFunction() == &F) {
156-
const Function *F1 = I->getFunction();
157-
Graph[F1].insert(&F);
158-
}
159-
}
160-
}
161-
if (F.hasAddressTaken()) {
162-
AddrTakenFunctions.insert(&F);
163-
}
164-
}
165-
}
166-
167-
iterator_range<FunctionSet::const_iterator>
168-
successors(const Function *F) const {
169-
auto It = Graph.find(F);
170-
return (It == Graph.end())
171-
? make_range(EmptySet.begin(), EmptySet.end())
172-
: make_range(It->second.begin(), It->second.end());
173-
}
174-
175-
iterator_range<FunctionSet::const_iterator> addrTakenFunctions() const {
176-
return make_range(AddrTakenFunctions.begin(), AddrTakenFunctions.end());
177-
}
178-
};
179-
180-
bool isESIMDFunctionInCallChain(const Function *F, const CallGraph &Deps) {
181-
if (isESIMDFunction(*F)) {
182-
return true;
183-
}
184-
for (const Function *F1 : Deps.successors(F)) {
185-
if (isESIMDFunctionInCallChain(F1, Deps)) {
186-
return true;
187-
}
188-
// Optimization to reduce recursion depth.
189-
// No need to check function calls beyond kernel function.
190-
if (isEntryPoint(*F1, true)) {
191-
return false;
192-
}
193-
}
194-
return false;
195-
}
196139

197140
// This function makes one or two groups depending on kernel types (SYCL, ESIMD)
198141
EntryPointGroupVec
@@ -208,7 +151,7 @@ groupEntryPointsByKernelType(const ModuleDesc &MD,
208151
!MD.isEntryPointCandidate(F))
209152
continue;
210153

211-
if (isESIMDFunctionInCallChain(&F, CallGraph{M}))
154+
if (isESIMDFunction(F))
212155
EntryPointMap[ESIMD_SCOPE_NAME].insert(&F);
213156
else
214157
EntryPointMap[SYCL_SCOPE_NAME].insert(&F);
@@ -337,6 +280,47 @@ groupEntryPointsByAttribute(const ModuleDesc &MD, StringRef AttrName,
337280
return EntryPointGroups;
338281
}
339282

283+
// Represents a call graph between functions in a module. Nodes are functions,
284+
// edges are "calls" relation.
285+
class CallGraph {
286+
public:
287+
using FunctionSet = SmallPtrSet<const Function *, 16>;
288+
289+
private:
290+
std::unordered_map<const Function *, FunctionSet> Graph;
291+
SmallPtrSet<const Function *, 1> EmptySet;
292+
FunctionSet AddrTakenFunctions;
293+
294+
public:
295+
CallGraph(const Module &M) {
296+
for (const auto &F : M) {
297+
for (const Value *U : F.users()) {
298+
if (const auto *I = dyn_cast<CallInst>(U)) {
299+
if (I->getCalledFunction() == &F) {
300+
const Function *F1 = I->getFunction();
301+
Graph[F1].insert(&F);
302+
}
303+
}
304+
}
305+
if (F.hasAddressTaken()) {
306+
AddrTakenFunctions.insert(&F);
307+
}
308+
}
309+
}
310+
311+
iterator_range<FunctionSet::const_iterator>
312+
successors(const Function *F) const {
313+
auto It = Graph.find(F);
314+
return (It == Graph.end())
315+
? make_range(EmptySet.begin(), EmptySet.end())
316+
: make_range(It->second.begin(), It->second.end());
317+
}
318+
319+
iterator_range<FunctionSet::const_iterator> addrTakenFunctions() const {
320+
return make_range(AddrTakenFunctions.begin(), AddrTakenFunctions.end());
321+
}
322+
};
323+
340324
void collectFunctionsToExtract(SetVector<const GlobalValue *> &GVs,
341325
const EntryPointGroup &ModuleEntryPoints,
342326
const CallGraph &Deps) {

llvm/tools/sycl-post-link/sycl-post-link.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,10 @@ processInputModule(std::unique_ptr<Module> M) {
665665
// if none were made.
666666
bool Modified = false;
667667

668+
// Propagate ESIMD attribute to wrapper functions to prevent
669+
// spurious splits and kernel link errors.
670+
Modified |= runModulePass<SYCLLowerESIMDKernelAttrPass>(*M);
671+
668672
// After linking device bitcode "llvm.used" holds references to the kernels
669673
// that are defined in the device image. But after splitting device image into
670674
// separate kernels we may end up with having references to kernel declaration

0 commit comments

Comments
 (0)