Skip to content

Commit f33b946

Browse files
Fix emission of SPIR-V friendly IR for OpenCL EIS (#746)
Added possibility to emit SPIR-V friendly IR instead of OpenCL-C-like mangled function names for instructions from OpenCL extended instruction set.
1 parent 24599a8 commit f33b946

File tree

7 files changed

+243
-35
lines changed

7 files changed

+243
-35
lines changed

lib/SPIRV/SPIRVInternal.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,11 @@ bool containsUnsignedAtomicType(StringRef Name);
935935
std::string mangleBuiltin(StringRef UniqName, ArrayRef<Type *> ArgTypes,
936936
BuiltinFuncMangleInfo *BtnInfo);
937937

938+
/// Mangle a function from OpenCL extended instruction set in SPIR-V friendly IR
939+
/// manner
940+
std::string getSPIRVFriendlyIRFunctionName(OCLExtOpKind ExtOpId,
941+
ArrayRef<Type *> ArgTys);
942+
938943
/// Remove cast from a value.
939944
Value *removeCast(Value *V);
940945

lib/SPIRV/SPIRVReader.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4182,12 +4182,24 @@ Instruction *SPIRVToLLVM::transOCLBuiltinFromExtInst(SPIRVExtInst *BC,
41824182

41834183
std::vector<Type *> ArgTypes = transTypeVector(BC->getValueTypes(BArgs));
41844184

4185+
// TODO: we should always produce SPIR-V friendly IR and apply lowering
4186+
// later if needed
41854187
if (IsPrintf) {
4186-
MangledName = "printf";
41874188
ArgTypes.resize(1);
4189+
}
4190+
4191+
if (BM->getDesiredBIsRepresentation() != BIsRepresentation::SPIRVFriendlyIR) {
4192+
// Convert extended instruction into an OpenCL built-in
4193+
if (IsPrintf) {
4194+
MangledName = "printf";
4195+
} else {
4196+
mangleOpenClBuiltin(UnmangledName, ArgTypes, MangledName);
4197+
}
41884198
} else {
4189-
mangleOpenClBuiltin(UnmangledName, ArgTypes, MangledName);
4199+
MangledName = getSPIRVFriendlyIRFunctionName(
4200+
static_cast<OCLExtOpKind>(EntryPoint), ArgTypes);
41904201
}
4202+
41914203
SPIRVDBG(spvdbgs() << "[transOCLBuiltinFromExtInst] ModifiedUnmangledName: "
41924204
<< UnmangledName << " MangledName: " << MangledName
41934205
<< '\n');

lib/SPIRV/SPIRVUtil.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1554,5 +1554,70 @@ bool checkTypeForSPIRVExtendedInstLowering(IntrinsicInst *II, SPIRVModule *BM) {
15541554
}
15551555
return true;
15561556
}
1557+
} // namespace SPIRV
1558+
1559+
namespace {
1560+
class OpenCLStdToSPIRVFriendlyIRMangleInfo : public BuiltinFuncMangleInfo {
1561+
public:
1562+
OpenCLStdToSPIRVFriendlyIRMangleInfo(OCLExtOpKind ExtOpId,
1563+
ArrayRef<Type *> ArgTys)
1564+
: ExtOpId(ExtOpId), ArgTys(ArgTys) {
1565+
UnmangledName = getSPIRVExtFuncName(SPIRVEIS_OpenCL, ExtOpId);
1566+
}
1567+
1568+
void init(StringRef) override {
1569+
switch (ExtOpId) {
1570+
case OpenCLLIB::UAbs:
1571+
LLVM_FALLTHROUGH;
1572+
case OpenCLLIB::UAbs_diff:
1573+
LLVM_FALLTHROUGH;
1574+
case OpenCLLIB::UAdd_sat:
1575+
LLVM_FALLTHROUGH;
1576+
case OpenCLLIB::UHadd:
1577+
LLVM_FALLTHROUGH;
1578+
case OpenCLLIB::URhadd:
1579+
LLVM_FALLTHROUGH;
1580+
case OpenCLLIB::UClamp:
1581+
LLVM_FALLTHROUGH;
1582+
case OpenCLLIB::UMad_hi:
1583+
LLVM_FALLTHROUGH;
1584+
case OpenCLLIB::UMad_sat:
1585+
LLVM_FALLTHROUGH;
1586+
case OpenCLLIB::UMax:
1587+
LLVM_FALLTHROUGH;
1588+
case OpenCLLIB::UMin:
1589+
LLVM_FALLTHROUGH;
1590+
case OpenCLLIB::UMul_hi:
1591+
LLVM_FALLTHROUGH;
1592+
case OpenCLLIB::USub_sat:
1593+
LLVM_FALLTHROUGH;
1594+
case OpenCLLIB::U_Upsample:
1595+
LLVM_FALLTHROUGH;
1596+
case OpenCLLIB::UMad24:
1597+
LLVM_FALLTHROUGH;
1598+
case OpenCLLIB::UMul24:
1599+
// Treat all arguments as unsigned
1600+
addUnsignedArg(-1);
1601+
break;
1602+
case OpenCLLIB::S_Upsample:
1603+
addUnsignedArg(1);
1604+
break;
1605+
default:;
1606+
// No special handling is needed
1607+
}
1608+
}
1609+
1610+
private:
1611+
OCLExtOpKind ExtOpId;
1612+
ArrayRef<Type *> ArgTys;
1613+
};
1614+
} // namespace
1615+
1616+
namespace SPIRV {
1617+
std::string getSPIRVFriendlyIRFunctionName(OCLExtOpKind ExtOpId,
1618+
ArrayRef<Type *> ArgTys) {
1619+
OpenCLStdToSPIRVFriendlyIRMangleInfo MangleInfo(ExtOpId, ArgTys);
1620+
return mangleBuiltin(MangleInfo.getUnmangledName(), ArgTys, &MangleInfo);
1621+
}
15571622

15581623
} // namespace SPIRV

lib/SPIRV/libSPIRV/SPIRVModule.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,10 @@ class SPIRVModule {
498498
}
499499
}
500500

501+
BIsRepresentation getDesiredBIsRepresentation() const {
502+
return TranslationOpts.getDesiredBIsRepresentation();
503+
}
504+
501505
// I/O functions
502506
friend spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M);
503507
friend std::istream &operator>>(std::istream &I, SPIRVModule &M);

test/OpenCL.std/acos.spvasm

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
; REQUIRES: spirv-as
2+
; RUN: spirv-as --target-env spv1.0 -o %t.spv %s
3+
; RUN: llvm-spirv %t.spv -r --spirv-target-env=SPV-IR -o - | llvm-dis | FileCheck %s --check-prefixes=CHECK,CHECK-SPV-IR
4+
; RUN: llvm-spirv %t.spv -r --spirv-target-env=CL2.0 -o - | llvm-dis | FileCheck %s --check-prefixes=CHECK,CHECK-CL20
5+
;
6+
; CHECK-LABEL: spir_kernel void @test
7+
; CHECK-SPV-IR: call spir_func float @_Z16__spirv_ocl_acosf(float
8+
; CHECK-SPV-IR: call spir_func double @_Z16__spirv_ocl_acosd(double
9+
; CHECK-CL20: call spir_func float @_Z4acosf(float
10+
; CHECK-CL20: call spir_func double @_Z4acosd(double
11+
; CHECK-LABEL: spir_kernel void @test2
12+
; CHECK-SPV-IR: call spir_func <4 x float> @_Z16__spirv_ocl_acosDv4_f(<4 x float>
13+
; CHECK-SPV-IR: call spir_func <4 x double> @_Z16__spirv_ocl_acosDv4_d(<4 x double>
14+
; CHECK-CL20: call spir_func <4 x float> @_Z4acosDv4_f(<4 x float>
15+
; CHECK-CL20: call spir_func <4 x double> @_Z4acosDv4_d(<4 x double>
16+
17+
OpCapability Addresses
18+
OpCapability Kernel
19+
OpCapability Float64
20+
%1 = OpExtInstImport "OpenCL.std"
21+
OpMemoryModel Physical32 OpenCL
22+
OpEntryPoint Kernel %8 "test"
23+
OpEntryPoint Kernel %21 "test2"
24+
%29 = OpString "kernel_arg_type.test.float,double,float*,double*,"
25+
%30 = OpString "kernel_arg_type.test2.float4,double4,float4*,double4*,"
26+
OpSource OpenCL_C 200000
27+
OpName %arg1 "arg1"
28+
OpName %arg2 "arg2"
29+
OpName %output1 "output1"
30+
OpName %output2 "output2"
31+
OpName %entry "entry"
32+
OpName %call "call"
33+
OpName %call1 "call1"
34+
OpName %arg1_0 "arg1"
35+
OpName %arg2_0 "arg2"
36+
OpName %output1_0 "output1"
37+
OpName %output2_0 "output2"
38+
OpName %entry_0 "entry"
39+
OpName %call_0 "call"
40+
OpName %call1_0 "call1"
41+
OpDecorate %output1 FuncParamAttr NoCapture
42+
OpDecorate %output2 FuncParamAttr NoCapture
43+
OpDecorate %output1_0 FuncParamAttr NoCapture
44+
OpDecorate %output2_0 FuncParamAttr NoCapture
45+
%void = OpTypeVoid
46+
%float = OpTypeFloat 32
47+
%double = OpTypeFloat 64
48+
%_ptr_CrossWorkgroup_float = OpTypePointer CrossWorkgroup %float
49+
%_ptr_CrossWorkgroup_double = OpTypePointer CrossWorkgroup %double
50+
%7 = OpTypeFunction %void %float %double %_ptr_CrossWorkgroup_float %_ptr_CrossWorkgroup_double
51+
%v4float = OpTypeVector %float 4
52+
%v4double = OpTypeVector %double 4
53+
%_ptr_CrossWorkgroup_v4float = OpTypePointer CrossWorkgroup %v4float
54+
%_ptr_CrossWorkgroup_v4double = OpTypePointer CrossWorkgroup %v4double
55+
%20 = OpTypeFunction %void %v4float %v4double %_ptr_CrossWorkgroup_v4float %_ptr_CrossWorkgroup_v4double
56+
%8 = OpFunction %void None %7
57+
%arg1 = OpFunctionParameter %float
58+
%arg2 = OpFunctionParameter %double
59+
%output1 = OpFunctionParameter %_ptr_CrossWorkgroup_float
60+
%output2 = OpFunctionParameter %_ptr_CrossWorkgroup_double
61+
%entry = OpLabel
62+
%call = OpExtInst %float %1 acos %arg1
63+
OpStore %output1 %call Aligned 4
64+
%call1 = OpExtInst %double %1 acos %arg2
65+
OpStore %output2 %call1 Aligned 8
66+
OpReturn
67+
OpFunctionEnd
68+
%21 = OpFunction %void None %20
69+
%arg1_0 = OpFunctionParameter %v4float
70+
%arg2_0 = OpFunctionParameter %v4double
71+
%output1_0 = OpFunctionParameter %_ptr_CrossWorkgroup_v4float
72+
%output2_0 = OpFunctionParameter %_ptr_CrossWorkgroup_v4double
73+
%entry_0 = OpLabel
74+
%call_0 = OpExtInst %v4float %1 acos %arg1_0
75+
OpStore %output1_0 %call_0 Aligned 16
76+
%call1_0 = OpExtInst %v4double %1 acos %arg2_0
77+
OpStore %output2_0 %call1_0 Aligned 32
78+
OpReturn
79+
OpFunctionEnd

test/OpenCL.std/upsample.spvasm

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
; REQUIRES: spirv-as
2+
; RUN: spirv-as --target-env spv1.0 -o %t.spv %s
3+
; RUN: llvm-spirv %t.spv -r --spirv-target-env=SPV-IR -o - | llvm-dis | FileCheck %s --check-prefixes=CHECK,CHECK-SPV-IR
4+
; RUN: llvm-spirv %t.spv -r --spirv-target-env=CL2.0 -o - | llvm-dis | FileCheck %s --check-prefixes=CHECK,CHECK-CL20
5+
;
6+
; CHECK-LABEL: spir_kernel void @test
7+
; CHECK-SPV-IR: call spir_func i64 @_Z22__spirv_ocl_s_upsampleij(i32 %{{[0-9a-z]+}}, i32
8+
; CHECK-SPV-IR: call spir_func i64 @_Z22__spirv_ocl_u_upsamplejj(i32 %{{[0-9a-z]+}}, i32
9+
; CHECK-CL20: call spir_func i64 @_Z8upsampleij(i32 %{{[0-9a-z]+}}, i32
10+
; CHECK-CL20: call spir_func i64 @_Z8upsamplejj(i32 %{{[0-9a-z]+}}, i32
11+
; CHECK-LABEL: spir_kernel void @test2
12+
; CHECK-SPV-IR: call spir_func <4 x i64> @_Z22__spirv_ocl_s_upsampleDv4_iDv4_j(<4 x i32> %{{[0-9a-z]+}}, <4 x i32>
13+
; CHECK-SPV-IR: call spir_func <4 x i64> @_Z22__spirv_ocl_u_upsampleDv4_jS_(<4 x i32> %{{[0-9a-z]+}}, <4 x i32>
14+
; CHECK-CL20: call spir_func <4 x i64> @_Z8upsampleDv4_iDv4_j(<4 x i32> %{{[0-9a-z]+}}, <4 x i32>
15+
; CHECK-CL20: call spir_func <4 x i64> @_Z8upsampleDv4_jS_(<4 x i32> %{{[0-9a-z]+}}, <4 x i32>
16+
17+
OpCapability Addresses
18+
OpCapability Kernel
19+
OpCapability Int64
20+
%1 = OpExtInstImport "OpenCL.std"
21+
OpMemoryModel Physical32 OpenCL
22+
OpEntryPoint Kernel %7 "test"
23+
OpEntryPoint Kernel %20 "test2"
24+
%28 = OpString "kernel_arg_type.test.int,uint,long*,"
25+
%29 = OpString "kernel_arg_type.test2.int4,uint4,ulong4*,"
26+
OpSource OpenCL_C 200000
27+
OpName %a "a"
28+
OpName %b "b"
29+
OpName %c "c"
30+
OpName %entry "entry"
31+
OpName %call "call"
32+
OpName %call1 "call1"
33+
OpName %arrayidx2 "arrayidx2"
34+
OpName %call2 "call2"
35+
OpName %b_0 "b"
36+
OpName %c_0 "c"
37+
OpName %entry_0 "entry"
38+
OpName %call1_0 "call1"
39+
OpName %call3 "call3"
40+
OpName %arrayidx4 "arrayidx4"
41+
OpDecorate %c FuncParamAttr NoCapture
42+
OpDecorate %c_0 FuncParamAttr NoCapture
43+
%uint = OpTypeInt 32 0
44+
%ulong = OpTypeInt 64 0
45+
%uint_1 = OpConstant %uint 1
46+
%void = OpTypeVoid
47+
%_ptr_CrossWorkgroup_ulong = OpTypePointer CrossWorkgroup %ulong
48+
%6 = OpTypeFunction %void %uint %uint %_ptr_CrossWorkgroup_ulong
49+
%v4uint = OpTypeVector %uint 4
50+
%v4ulong = OpTypeVector %ulong 4
51+
%_ptr_CrossWorkgroup_v4ulong = OpTypePointer CrossWorkgroup %v4ulong
52+
%19 = OpTypeFunction %void %v4uint %v4uint %_ptr_CrossWorkgroup_v4ulong
53+
%7 = OpFunction %void None %6
54+
%a = OpFunctionParameter %uint
55+
%b = OpFunctionParameter %uint
56+
%c = OpFunctionParameter %_ptr_CrossWorkgroup_ulong
57+
%entry = OpLabel
58+
%call = OpExtInst %ulong %1 s_upsample %a %b
59+
OpStore %c %call Aligned 8
60+
%call1 = OpExtInst %ulong %1 u_upsample %a %b
61+
%arrayidx2 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_ulong %c %uint_1
62+
OpStore %arrayidx2 %call1 Aligned 8
63+
OpReturn
64+
OpFunctionEnd
65+
%20 = OpFunction %void None %19
66+
%call2 = OpFunctionParameter %v4uint
67+
%b_0 = OpFunctionParameter %v4uint
68+
%c_0 = OpFunctionParameter %_ptr_CrossWorkgroup_v4ulong
69+
%entry_0 = OpLabel
70+
%call1_0 = OpExtInst %v4ulong %1 s_upsample %call2 %b_0
71+
OpStore %c_0 %call1_0 Aligned 32
72+
%call3 = OpExtInst %v4ulong %1 u_upsample %call2 %b_0
73+
%arrayidx4 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_v4ulong %c_0 %uint_1
74+
OpStore %arrayidx4 %call3 Aligned 32
75+
OpReturn
76+
OpFunctionEnd

test/mangling_upsample.spt

Lines changed: 0 additions & 33 deletions
This file was deleted.

0 commit comments

Comments
 (0)