Skip to content

Commit 36d4d36

Browse files
committed
[SYCL] Propagate SPIRV kernel parameter opt info to runtime.
The post-link tool - uses a new analysis pass (SPIRKernelParamOptInfo) to extract kernel parameter optimization info from IR produced by the DeadArgumentElimination pass - uses the PropertySetIO mechanism to encode this information into the ourput property file Then the clang offload wrapper picks up the property file and injects it into the device binary descriptor accessed by the SYCL runtime when the app runs. Signed-off-by: Konstantin S Bobrovsky <[email protected]>
1 parent 25efdd3 commit 36d4d36

File tree

6 files changed

+184
-2
lines changed

6 files changed

+184
-2
lines changed

llvm/include/llvm/Support/PropertySetIO.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ class PropertySetRegistry {
180180
static constexpr char SYCL_SPECIALIZATION_CONSTANTS[] =
181181
"SYCL/specialization constants";
182182
static constexpr char SYCL_DEVICELIB_REQ_MASK[] = "SYCL/devicelib req mask";
183+
static constexpr char SYCL_KERNEL_PARAM_OPT_INFO[] = "SYCL/kernel param opt";
183184

184185
// Function for bulk addition of an entire property set under given category
185186
// (property set name).
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
; This test checks that the post-link tool generates correct kernel parameter
2+
; optimization info into a property file if the source IR contained
3+
; corresponding metadata.
4+
;
5+
; RUN: sycl-post-link -emit-param-info -S %s -o %t.files.table
6+
; RUN: FileCheck %s -input-file=%t.files.table --check-prefixes CHECK-TABLE
7+
; RUN: FileCheck %s -input-file=%t.files_0.prop --match-full-lines --check-prefixes CHECK-PROP
8+
9+
target triple = "spir64-unknown-unknown-sycldevice"
10+
11+
define weak_odr spir_kernel void @SpirKernel1(float %arg1) !spir_kernel_omit_args !0 {
12+
call void @foo(float %arg1)
13+
ret void
14+
}
15+
16+
define weak_odr spir_kernel void @SpirKernel2(i8 %arg1, i8 %arg2, i8 %arg3) !spir_kernel_omit_args !1 {
17+
call void @bar(i8 %arg1)
18+
call void @bar(i8 %arg2)
19+
call void @bar(i8 %arg3)
20+
ret void
21+
}
22+
23+
declare void @foo(float)
24+
declare void @bar(i8)
25+
26+
; // HEX: 0x01 (1 byte)
27+
; // BIN: 01 - 2 arguments total, 1 remains
28+
; // NOTE: In the metadata string below, unlike bitmask above, least significant
29+
; // element goes first
30+
!0 = !{i1 true, i1 false}
31+
32+
; // HEX: 0x7E 0x06 (2 bytes)
33+
; // BIN: 110 01111110 - 11 arguments total, 3 remain
34+
!1 = !{i1 false, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 false, i1 false, i1 true, i1 true}
35+
36+
; CHECK-PROP: [SYCL/kernel param opt]
37+
; // Base64 encoding in the prop file (including 8 bytes length):
38+
; CHECK-PROP-NEXT: SpirKernel1=2|CAAAAAAAAAQA
39+
; // Base64 encoding in the prop file (including 8 bytes length):
40+
; CHECK-PROP-NEXT: SpirKernel2=2|LAAAAAAAAAgfGA
41+
42+
; CHECK-TABLE: [Code|Properties]
43+
; CHECK-TABLE-NEXT: {{.*}}files_0.prop
44+
; CHECK-TABLE-EMPTY:

llvm/tools/sycl-post-link/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ set(LLVM_LINK_COMPONENTS
99

1010
add_llvm_tool(sycl-post-link
1111
sycl-post-link.cpp
12+
SPIRKernelParamOptInfo.cpp
1213
SpecConstants.cpp
1314

1415
DEPENDS
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//==-- SPIRKernelParamOptInfo.cpp -- get kernel param optimization info ----==//
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+
9+
#include "SPIRKernelParamOptInfo.h"
10+
11+
#include "llvm/IR/Constants.h"
12+
#include "llvm/Support/Casting.h"
13+
14+
namespace {
15+
16+
// Must match the one produced by DeadArgumentElimination
17+
static constexpr char MetaDataID[] = "spir_kernel_omit_args";
18+
19+
} // anonymous namespace
20+
21+
namespace llvm {
22+
23+
void SPIRKernelParamOptInfo::releaseMemory() { clear(); }
24+
25+
SPIRKernelParamOptInfo
26+
SPIRKernelParamOptInfoAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
27+
SPIRKernelParamOptInfo Res;
28+
29+
for (const Function &F : M) {
30+
MDNode *MD = F.getMetadata(MetaDataID);
31+
if (!MD)
32+
continue;
33+
using BaseTy = SPIRKernelParamOptInfoBaseTy;
34+
auto Ins =
35+
Res.insert(BaseTy::value_type{F.getName(), BaseTy::mapped_type{}});
36+
assert(Ins.second && "duplicate kernel?");
37+
BitVector &ParamDropped = Ins.first->second;
38+
39+
for (unsigned int I = 0; I < MD->getNumOperands(); ++I) {
40+
const auto *MDInt1 = cast<ConstantAsMetadata>(MD->getOperand(I));
41+
unsigned ID = static_cast<unsigned>(
42+
cast<ConstantInt>(MDInt1->getValue())->getValue().getZExtValue());
43+
ParamDropped.push_back(ID != 0);
44+
}
45+
}
46+
return Res;
47+
}
48+
49+
AnalysisKey SPIRKernelParamOptInfoAnalysis::Key;
50+
51+
} // namespace llvm
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//==-- SPIRKernelParamOptInfo.h -- get kernel param optimization info ------==//
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+
// Analysis pass which collects parameter optimization info for SPIR kernels.
9+
// Currently the info is whether i'th kernel parameter as emitted by the FE has
10+
// been optimized away by the LLVM optimizer. The information is produced by
11+
// DeadArgumentElimination transformation and stored into a specific metadata
12+
// attached to kernel functions in a module.
13+
//===----------------------------------------------------------------------===//
14+
15+
#include "llvm/ADT/BitVector.h"
16+
#include "llvm/ADT/StringRef.h"
17+
#include "llvm/IR/Module.h"
18+
#include "llvm/IR/PassManager.h"
19+
20+
#include <map>
21+
#include <string>
22+
23+
namespace llvm {
24+
25+
// the StringRef key refers to a function name
26+
using SPIRKernelParamOptInfoBaseTy = std::map<StringRef, BitVector>;
27+
28+
class SPIRKernelParamOptInfo : public SPIRKernelParamOptInfoBaseTy {
29+
public:
30+
void releaseMemory();
31+
};
32+
33+
class SPIRKernelParamOptInfoAnalysis
34+
: public AnalysisInfoMixin<SPIRKernelParamOptInfoAnalysis> {
35+
friend AnalysisInfoMixin<SPIRKernelParamOptInfoAnalysis>;
36+
37+
static AnalysisKey Key;
38+
39+
public:
40+
/// Provide the result type for this analysis pass.
41+
using Result = SPIRKernelParamOptInfo;
42+
43+
/// Run the analysis pass over a function and produce BPI.
44+
SPIRKernelParamOptInfo run(Module &M, ModuleAnalysisManager &AM);
45+
};
46+
47+
} // namespace llvm

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

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
// - specialization constant intrinsic transformation
1414
//===----------------------------------------------------------------------===//
1515

16+
#include "SPIRKernelParamOptInfo.h"
1617
#include "SpecConstants.h"
18+
1719
#include "llvm/ADT/SetVector.h"
1820
#include "llvm/ADT/Triple.h"
1921
#include "llvm/Bitcode/BitcodeWriterPass.h"
@@ -34,6 +36,7 @@
3436
#include "llvm/Transforms/IPO.h"
3537
#include "llvm/Transforms/IPO/GlobalDCE.h"
3638
#include "llvm/Transforms/Utils/Cloning.h"
39+
3740
#include <memory>
3841

3942
using namespace llvm;
@@ -117,11 +120,16 @@ static cl::opt<SpecConstMode> SpecConstLower{
117120
"set spec constants to C++ defaults")),
118121
cl::cat(PostLinkCat)};
119122

123+
static cl::opt<bool> EmitKernelParamInfo{
124+
"emit-param-info", cl::desc("emit kernel parameter optimization info"),
125+
cl::cat(PostLinkCat)};
126+
120127
struct ImagePropSaveInfo {
121128
bool NeedDeviceLibReqMask;
122129
bool DoSpecConst;
123130
bool SetSpecConstAtRT;
124131
bool SpecConstsMet;
132+
bool EmitKernelParamInfo;
125133
};
126134
// Please update DeviceLibFuncMap if any item is added to or removed from
127135
// fallback device libraries in libdevice.
@@ -508,6 +516,30 @@ static string_vector saveDeviceImageProperty(
508516
llvm::util::PropertySetRegistry::SYCL_SPECIALIZATION_CONSTANTS,
509517
TmpSpecIDMap);
510518
}
519+
if (ImgPSInfo.EmitKernelParamInfo) {
520+
// extract kernel parameter optimization info per module
521+
ModuleAnalysisManager MAM;
522+
// Register required analysis
523+
MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
524+
// Register the payload analysis
525+
MAM.registerPass([&] { return SPIRKernelParamOptInfoAnalysis(); });
526+
SPIRKernelParamOptInfo PInfo =
527+
MAM.getResult<SPIRKernelParamOptInfoAnalysis>(*ResultModules[I]);
528+
529+
// convert analysis results into properties and record them
530+
llvm::util::PropertySet &Props =
531+
PropSet[llvm::util::PropertySetRegistry::SYCL_KERNEL_PARAM_OPT_INFO];
532+
533+
for (const auto &NameInfoPair : PInfo) {
534+
const llvm::BitVector &Bits = NameInfoPair.second;
535+
const llvm::ArrayRef<uintptr_t> Arr = NameInfoPair.second.getData();
536+
const unsigned char *Data =
537+
reinterpret_cast<const unsigned char *>(Arr.begin());
538+
llvm::util::PropertyValue::SizeTy DataBitSize = Bits.size();
539+
Props.insert(std::make_pair(
540+
NameInfoPair.first, llvm::util::PropertyValue(Data, DataBitSize)));
541+
}
542+
}
511543
std::error_code EC;
512544
std::string SCFile = makeResultFileName(".prop", I);
513545
raw_fd_ostream SCOut(SCFile, EC);
@@ -580,8 +612,9 @@ int main(int argc, char **argv) {
580612

581613
bool DoSplit = SplitMode.getNumOccurrences() > 0;
582614
bool DoSpecConst = SpecConstLower.getNumOccurrences() > 0;
615+
bool DoParamInfo = EmitKernelParamInfo.getNumOccurrences() > 0;
583616

584-
if (!DoSplit && !DoSpecConst && !DoSymGen) {
617+
if (!DoSplit && !DoSpecConst && !DoSymGen && !DoParamInfo) {
585618
errs() << "no actions specified; try --help for usage info\n";
586619
return 1;
587620
}
@@ -595,6 +628,11 @@ int main(int argc, char **argv) {
595628
<< IROutputOnly.ArgStr << "\n";
596629
return 1;
597630
}
631+
if (IROutputOnly && DoParamInfo) {
632+
errs() << "error: -" << EmitKernelParamInfo.ArgStr << " can't be used with"
633+
<< " -" << IROutputOnly.ArgStr << "\n";
634+
return 1;
635+
}
598636
SMDiagnostic Err;
599637
std::unique_ptr<Module> M = parseIRFile(InputFilename, Err, Context);
600638
// It is OK to use raw pointer here as we control that it does not outlive M
@@ -664,7 +702,7 @@ int main(int argc, char **argv) {
664702

665703
{
666704
ImagePropSaveInfo ImgPSInfo = {true, DoSpecConst, SetSpecConstAtRT,
667-
SpecConstsMet};
705+
SpecConstsMet, EmitKernelParamInfo};
668706
string_vector Files = saveDeviceImageProperty(ResultModules, ImgPSInfo);
669707
Error Err = Table.addColumn(COL_PROPS, Files);
670708
CHECK_AND_EXIT(Err);

0 commit comments

Comments
 (0)