Skip to content

Commit c2c443a

Browse files
github-actions[bot]bashbaugsvenvh
authored
[Backport to llvm_release_140] Support for cl_khr_kernel_clock (#3655)
Backport of PR #2582 into `llvm_release_140`. All commits applied cleanly. Co-authored-by: Ben Ashbaugh <ben.ashbaugh@intel.com> Co-authored-by: Sven van Haastregt <sven.vanhaastregt@arm.com>
1 parent 4ecde1b commit c2c443a

File tree

9 files changed

+131
-0
lines changed

9 files changed

+131
-0
lines changed

lib/SPIRV/OCLToSPIRV.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,10 @@ void OCLToSPIRVBase::visitCallInst(CallInst &CI) {
320320
visitCallDot(&CI, MangledName, DemangledName);
321321
return;
322322
}
323+
if (DemangledName.startswith(kOCLBuiltinName::ClockReadPrefix)) {
324+
visitCallClockRead(&CI, MangledName, DemangledName);
325+
return;
326+
}
323327
if (DemangledName == kOCLBuiltinName::FMin ||
324328
DemangledName == kOCLBuiltinName::FMax ||
325329
DemangledName == kOCLBuiltinName::Min ||
@@ -1423,6 +1427,25 @@ void OCLToSPIRVBase::visitCallDot(CallInst *CI, StringRef MangledName,
14231427
&Attrs);
14241428
}
14251429

1430+
void OCLToSPIRVBase::visitCallClockRead(CallInst *CI, StringRef MangledName,
1431+
StringRef DemangledName) {
1432+
// The builtin returns i64 or <2 x i32>, but both variants are mapped to the
1433+
// same instruction; hence include the return type.
1434+
const std::string OpName = getSPIRVFuncName(OpReadClockKHR, CI->getType());
1435+
1436+
// Scope is part of the OpenCL builtin name.
1437+
const Scope ScopeArg = StringSwitch<Scope>(DemangledName)
1438+
.EndsWith("device", ScopeDevice)
1439+
.EndsWith("work_group", ScopeWorkgroup)
1440+
.EndsWith("sub_group", ScopeSubgroup)
1441+
.Default(ScopeMax);
1442+
1443+
mutateCallInstSPIRV(M, CI, [=](CallInst *, std::vector<Value *> &Args) {
1444+
Args.push_back(getInt32(M, ScopeArg));
1445+
return OpName;
1446+
});
1447+
}
1448+
14261449
void OCLToSPIRVBase::visitCallScalToVec(CallInst *CI, StringRef MangledName,
14271450
StringRef DemangledName) {
14281451
// Check if all arguments have the same type - it's simple case.

lib/SPIRV/OCLToSPIRV.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,10 @@ class OCLToSPIRVBase : public InstVisitor<OCLToSPIRVBase> {
215215
void visitCallDot(CallInst *CI, StringRef MangledName,
216216
StringRef DemangledName);
217217

218+
/// Transform clock_read_* calls to OpReadClockKHR instructions.
219+
void visitCallClockRead(CallInst *CI, StringRef MangledName,
220+
StringRef DemangledName);
221+
218222
/// Fixes for built-in functions with vector+scalar arguments that are
219223
/// translated to the SPIR-V instructions where all arguments must have the
220224
/// same type.

lib/SPIRV/OCLUtil.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ const static char AtomicInit[] = "atomic_init";
239239
const static char AtomicWorkItemFence[] = "atomic_work_item_fence";
240240
const static char Barrier[] = "barrier";
241241
const static char Clamp[] = "clamp";
242+
const static char ClockReadPrefix[] = "clock_read_";
242243
const static char ConvertPrefix[] = "convert_";
243244
const static char Dot[] = "dot";
244245
const static char DotAccSat[] = "dot_acc_sat";

lib/SPIRV/SPIRVToOCL.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,10 @@ void SPIRVToOCLBase::visitCallInst(CallInst &CI) {
209209
visitCallSPIRVRelational(&CI, OC);
210210
return;
211211
}
212+
if (OC == OpReadClockKHR) {
213+
visitCallSPIRVReadClockKHR(&CI);
214+
return;
215+
}
212216
if (OC == internal::OpConvertFToBF16INTEL ||
213217
OC == internal::OpConvertBF16ToFINTEL) {
214218
visitCallSPIRVBFloat16Conversions(&CI, OC);
@@ -1242,6 +1246,34 @@ void SPIRVToOCLBase::visitCallSPIRVRelational(CallInst *CI, Op OC) {
12421246
&Attrs);
12431247
}
12441248

1249+
void SPIRVToOCLBase::visitCallSPIRVReadClockKHR(CallInst *CI) {
1250+
std::string Name("clock_read_");
1251+
1252+
if (CI->getType()->isVectorTy())
1253+
Name += "hilo_";
1254+
1255+
// Encode the scope (taken from the argument) in the function name.
1256+
ConstantInt *ScopeOp = cast<ConstantInt>(CI->getArgOperand(0));
1257+
switch (static_cast<Scope>(ScopeOp->getZExtValue())) {
1258+
case ScopeDevice:
1259+
Name += "device";
1260+
break;
1261+
case ScopeWorkgroup:
1262+
Name += "work_group";
1263+
break;
1264+
case ScopeSubgroup:
1265+
Name += "sub_group";
1266+
break;
1267+
default:
1268+
break;
1269+
}
1270+
1271+
mutateCallInstOCL(M, CI, [=](CallInst *Call, std::vector<Value *> &Args) {
1272+
Args.pop_back();
1273+
return Name;
1274+
});
1275+
}
1276+
12451277
std::string SPIRVToOCLBase::getGroupBuiltinPrefix(CallInst *CI) {
12461278
std::string Prefix;
12471279
auto ES = getArgAsScope(CI, 0);

lib/SPIRV/SPIRVToOCL.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,9 @@ class SPIRVToOCLBase : public InstVisitor<SPIRVToOCLBase> {
237237
/// Transform relational builtin, e.g. __spirv_IsNan, to OpenCL builtin.
238238
void visitCallSPIRVRelational(CallInst *CI, Op OC);
239239

240+
/// Transform __spirv_ReadClockKHR to OpenCL builtin.
241+
void visitCallSPIRVReadClockKHR(CallInst *CI);
242+
240243
/// Conduct generic mutations for all atomic builtins
241244
virtual CallInst *mutateCommonAtomicArguments(CallInst *CI, Op OC) = 0;
242245

test/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ if(SPIRV_TOOLS_FOUND)
1111
set(SPIRV_TOOLS_SPIRV_AS_FOUND True)
1212
endif()
1313

14+
find_program(SPIRV_TOOLS_SPIRV_DIS NAMES spirv-dis PATHS ${SPIRV_TOOLS_PREFIX}/bin)
15+
if(SPIRV_TOOLS_SPIRV_DIS)
16+
set(SPIRV_TOOLS_SPIRV_DIS_FOUND True)
17+
endif()
18+
1419
find_program(SPIRV_TOOLS_SPIRV_LINK NAMES spirv-link PATHS ${SPIRV_TOOLS_PREFIX}/bin)
1520
if(SPIRV_TOOLS_SPIRV_LINK)
1621
set(SPIRV_TOOLS_SPIRV_LINK_FOUND True)
@@ -29,6 +34,11 @@ if(NOT SPIRV_TOOLS_SPIRV_AS)
2934
set(SPIRV_TOOLS_SPIRV_AS_FOUND False)
3035
endif()
3136

37+
if(NOT SPIRV_TOOLS_SPIRV_DIS)
38+
message(WARNING "spirv-dis not found! SPIR-V disassembly tests will not be run.")
39+
set(SPIRV_TOOLS_SPIRV_DIS_FOUND False)
40+
endif()
41+
3242
if(NOT SPIRV_TOOLS_SPIRV_LINK)
3343
message(WARNING "spirv-link not found! SPIR-V test involving the linker will not be run.")
3444
set(SPIRV_TOOLS_SPIRV_LINK_FOUND False)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// This test will fail if Clang does not support the cl_khr_shader_clock extension:
2+
// XFAIL: *
3+
// REQUIRES: spirv-dis
4+
// RUN: %clang_cc1 -triple spir-unknown-unknown -O1 -cl-std=CL2.0 -fdeclare-opencl-builtins -finclude-default-header -emit-llvm-bc %s -o %t.bc
5+
// RUN: llvm-spirv %t.bc --spirv-ext=+SPV_KHR_shader_clock -o %t.spv
6+
// RUN: spirv-dis %t.spv -o - | FileCheck %s --check-prefix=CHECK-SPIRV
7+
// TODO: spirv-val %t.spv
8+
// RUN: llvm-spirv -r %t.spv -o %t.rev.bc
9+
// RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM
10+
// RUN: llvm-spirv -r --spirv-target-env=SPV-IR %t.spv -o %t.rev.bc
11+
// RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-SPV-IR
12+
13+
// CHECK-SPIRV: OpCapability ShaderClockKHR
14+
// CHECK-SPIRV: OpExtension "SPV_KHR_shader_clock"
15+
// CHECK-SPIRV-DAG: [[uint:%[a-z0-9_]+]] = OpTypeInt 32
16+
// CHECK-SPIRV-DAG: [[ulong:%[a-z0-9_]+]] = OpTypeInt 64
17+
// CHECK-SPIRV-DAG: [[v2uint:%[a-z0-9_]+]] = OpTypeVector [[uint]] 2
18+
// CHECK-SPIRV-DAG: [[uint_1:%[a-z0-9_]+]] = OpConstant [[uint]] 1
19+
// CHECK-SPIRV-DAG: [[uint_2:%[a-z0-9_]+]] = OpConstant [[uint]] 2
20+
// CHECK-SPIRV-DAG: [[uint_3:%[a-z0-9_]+]] = OpConstant [[uint]] 3
21+
// CHECK-SPIRV: OpReadClockKHR [[ulong]] [[uint_1]]
22+
// CHECK-SPIRV: OpReadClockKHR [[ulong]] [[uint_2]]
23+
// CHECK-SPIRV: OpReadClockKHR [[ulong]] [[uint_3]]
24+
// CHECK-SPIRV: OpReadClockKHR [[v2uint]] [[uint_1]]
25+
// CHECK-SPIRV: OpReadClockKHR [[v2uint]] [[uint_2]]
26+
// CHECK-SPIRV: OpReadClockKHR [[v2uint]] [[uint_3]]
27+
28+
// CHECK-LLVM-LABEL: test_clocks
29+
// CHECK-LLVM: call spir_func i64 @_Z17clock_read_devicev()
30+
// CHECK-LLVM: call spir_func i64 @_Z21clock_read_work_groupv()
31+
// CHECK-LLVM: call spir_func i64 @_Z20clock_read_sub_groupv()
32+
// CHECK-LLVM: call spir_func <2 x i32> @_Z22clock_read_hilo_devicev()
33+
// CHECK-LLVM: call spir_func <2 x i32> @_Z26clock_read_hilo_work_groupv()
34+
// CHECK-LLVM: call spir_func <2 x i32> @_Z25clock_read_hilo_sub_groupv()
35+
36+
// CHECK-SPV-IR-LABEL: test_clocks
37+
// CHECK-SPV-IR: call spir_func i64 @_Z27__spirv_ReadClockKHR_Rulongi(i32 1)
38+
// CHECK-SPV-IR: call spir_func i64 @_Z27__spirv_ReadClockKHR_Rulongi(i32 2)
39+
// CHECK-SPV-IR: call spir_func i64 @_Z27__spirv_ReadClockKHR_Rulongi(i32 3)
40+
// CHECK-SPV-IR: call spir_func <2 x i32> @_Z27__spirv_ReadClockKHR_Ruint2i(i32 1)
41+
// CHECK-SPV-IR: call spir_func <2 x i32> @_Z27__spirv_ReadClockKHR_Ruint2i(i32 2)
42+
// CHECK-SPV-IR: call spir_func <2 x i32> @_Z27__spirv_ReadClockKHR_Ruint2i(i32 3)
43+
44+
kernel void test_clocks(global ulong *out64, global uint2 *outv2) {
45+
out64[0] = clock_read_device();
46+
out64[1] = clock_read_work_group();
47+
out64[2] = clock_read_sub_group();
48+
49+
outv2[0] = clock_read_hilo_device();
50+
outv2[1] = clock_read_hilo_work_group();
51+
outv2[2] = clock_read_hilo_sub_group();
52+
}

test/lit.cfg.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@
6565
config.available_features.add('spirv-as')
6666
using_spirv_tools = True
6767

68+
if config.spirv_tools_have_spirv_dis:
69+
llvm_config.add_tool_substitutions(['spirv-dis'], [config.spirv_tools_bin_dir])
70+
config.available_features.add('spirv-dis')
71+
using_spirv_tools = True
72+
6873
if config.spirv_tools_have_spirv_link:
6974
llvm_config.add_tool_substitutions(['spirv-link'], [config.spirv_tools_bin_dir])
7075
config.available_features.add('spirv-link')

test/lit.site.cfg.py.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ config.python_executable = "@PYTHON_EXECUTABLE@"
1717
config.test_run_dir = "@CMAKE_CURRENT_BINARY_DIR@"
1818
config.spirv_tools_found = "@SPIRV_TOOLS_FOUND@"
1919
config.spirv_tools_have_spirv_as = @SPIRV_TOOLS_SPIRV_AS_FOUND@
20+
config.spirv_tools_have_spirv_dis = @SPIRV_TOOLS_SPIRV_DIS_FOUND@
2021
config.spirv_tools_have_spirv_link = @SPIRV_TOOLS_SPIRV_LINK_FOUND@
2122
config.spirv_tools_have_spirv_val = @SPIRV_TOOLS_SPIRV_VAL_FOUND@
2223
config.spirv_tools_bin_dir = "@SPIRV_TOOLS_BINDIR@"

0 commit comments

Comments
 (0)