Skip to content

Commit 2feb3e3

Browse files
authored
SPIRVReader: make image and sampler types match clang output (#3293)
For e.g. a `foo(image2d_t %img)` function type, clang produces @foo(target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0) %img) but after OpenCL -> SPIR-V translation, the SPIR-V reader would translate it into @foo(ptr addrspace(1) %img) Preserve image argument types as `TargetExtType`s when translating to an OpenCL target environment. `TargetExtType`s are already emitted for SPIR-V friendly IR. Make sure not to mangle the `TargetExtType` argument in the usual way, but continue using the special type mangling emitted by clang (e.g. `ocl_image1d_rw`). Contributes to #3287
1 parent b1114a9 commit 2feb3e3

21 files changed

+162
-115
lines changed

lib/SPIRV/OCLUtil.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,7 @@ class OCLBuiltinFuncMangleInfo : public SPIRV::BuiltinFuncMangleInfo {
523523
public:
524524
OCLBuiltinFuncMangleInfo(Function *F) : F(F) {}
525525
OCLBuiltinFuncMangleInfo() = default;
526+
bool isOpenCL() const override { return true; }
526527
void init(StringRef UniqName) override;
527528
// Auxiliary information, it is expected that it is relevant at the moment
528529
// the init method is called.

lib/SPIRV/SPIRVBuiltinHelper.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,11 +318,23 @@ Type *BuiltinCallHelper::getSPIRVType(
318318
UseRealType);
319319
}
320320

321+
/// Return true if we always need to emit a TargetExtType for the given type.
322+
static bool needsTargetExtTy(spv::Op TypeOpcode) {
323+
switch (TypeOpcode) {
324+
default:
325+
return false;
326+
case OpTypeImage:
327+
case OpTypeSampledImage:
328+
case OpTypeSampler:
329+
return true;
330+
}
331+
}
332+
321333
Type *BuiltinCallHelper::getSPIRVType(spv::Op TypeOpcode,
322334
StringRef InnerTypeName,
323335
ArrayRef<unsigned> Parameters,
324336
bool UseRealType) {
325-
if (UseTargetTypes) {
337+
if (UseTargetTypes || needsTargetExtTy(TypeOpcode)) {
326338
std::string BaseName = (Twine(kSPIRVTypeName::PrefixAndDelim) +
327339
SPIRVOpaqueTypeOpCodeMap::rmap(TypeOpcode))
328340
.str();

lib/SPIRV/SPIRVInternal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ class BuiltinFuncMangleInfo {
512512
virtual void init(StringRef UniqUnmangledName) {
513513
UnmangledName = UniqUnmangledName.str();
514514
}
515+
virtual bool isOpenCL() const { return false; }
515516

516517
protected:
517518
std::string UnmangledName;

lib/SPIRV/SPIRVToOCL.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ class SPIRVToOCLBase : public InstVisitor<SPIRVToOCLBase>,
262262
/// examples: __spirv_SDotKHR => dot, __spirv_SDotAccSatKHR => dot_acc_sat
263263
void visitCallSPIRVDot(CallInst *CI, Op OC, StringRef DemangledName);
264264

265+
static std::string translateOpaqueType(StringRef STName);
266+
265267
void translateOpaqueTypes();
266268

267269
private:
@@ -291,8 +293,6 @@ class SPIRVToOCLBase : public InstVisitor<SPIRVToOCLBase>,
291293
static std::string
292294
getOCLPipeOpaqueType(SmallVector<std::string, 8> &Postfixes);
293295

294-
static std::string translateOpaqueType(StringRef STName);
295-
296296
/// Mutate the call instruction based on (optional) image operands at position
297297
/// ImOpArgIndex. The new function name will be based on NewFuncName, and the
298298
/// type suffix based on Ty and whether the image operand was signed.

lib/SPIRV/SPIRVUtil.cpp

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include "ParameterType.h"
5050
#include "SPIRVInternal.h"
5151
#include "SPIRVMDWalker.h"
52+
#include "SPIRVToOCL.h"
5253
#include "libSPIRV/SPIRVDecorate.h"
5354
#include "libSPIRV/SPIRVValue.h"
5455

@@ -1288,11 +1289,33 @@ SPIR::TypePrimitiveEnum getOCLTypePrimitiveEnum(StringRef TyName) {
12881289
SPIR::PRIMITIVE_SUB_GROUP_AVC_IME_DUAL_REF_STREAMIN_T)
12891290
.Default(SPIR::PRIMITIVE_NONE);
12901291
}
1292+
1293+
/// Get TypePrimitiveEnum for special OpenCL type from TargetExtType.
1294+
static SPIR::TypePrimitiveEnum getOCLTypePrimitiveEnum(TargetExtType *Ty) {
1295+
if (Ty->getName() == "spirv.Image") {
1296+
std::string SPIRVName;
1297+
{
1298+
Type *InnerType = Ty->getTypeParameter(0);
1299+
raw_string_ostream OS(SPIRVName);
1300+
OS << kSPIRVTypeName::PrefixAndDelim
1301+
<< SPIRVOpaqueTypeOpCodeMap::rmap(OpTypeImage) << "._"
1302+
<< (InnerType ? convertTypeToPostfix(InnerType) : "void");
1303+
for (unsigned IntParam : Ty->int_params())
1304+
OS << kSPIRVTypeName::PostfixDelim << IntParam;
1305+
}
1306+
std::string OpenCLName = SPIRVToOCLBase::translateOpaqueType(SPIRVName);
1307+
return getOCLTypePrimitiveEnum(OpenCLName);
1308+
}
1309+
1310+
return SPIR::PRIMITIVE_NONE;
1311+
}
1312+
12911313
/// Translates LLVM type to descriptor for mangler.
12921314
/// \param Signed indicates integer type should be translated as signed.
12931315
/// \param VoidPtr indicates i8* should be translated as void*.
12941316
static SPIR::RefParamType transTypeDesc(Type *Ty,
12951317
const BuiltinArgTypeMangleInfo &Info,
1318+
bool IsOpenCL,
12961319
StringRef InstName = "") {
12971320
bool Signed = Info.IsSigned;
12981321
unsigned Attr = Info.Attr;
@@ -1308,7 +1331,8 @@ static SPIR::RefParamType transTypeDesc(Type *Ty,
13081331
if (Info.IsAtomic && !isa<TypedPointerType>(Ty)) {
13091332
BuiltinArgTypeMangleInfo DTInfo = Info;
13101333
DTInfo.IsAtomic = false;
1311-
return SPIR::RefParamType(new SPIR::AtomicType(transTypeDesc(Ty, DTInfo)));
1334+
return SPIR::RefParamType(
1335+
new SPIR::AtomicType(transTypeDesc(Ty, DTInfo, IsOpenCL)));
13121336
}
13131337
if (auto *IntTy = dyn_cast<IntegerType>(Ty)) {
13141338
switch (IntTy->getBitWidth()) {
@@ -1342,11 +1366,12 @@ static SPIR::RefParamType transTypeDesc(Type *Ty,
13421366
return SPIR::RefParamType(new SPIR::PrimitiveType(SPIR::PRIMITIVE_BFLOAT));
13431367
if (auto *VecTy = dyn_cast<FixedVectorType>(Ty)) {
13441368
return SPIR::RefParamType(new SPIR::VectorType(
1345-
transTypeDesc(VecTy->getElementType(), Info), VecTy->getNumElements()));
1369+
transTypeDesc(VecTy->getElementType(), Info, IsOpenCL),
1370+
VecTy->getNumElements()));
13461371
}
13471372
if (Ty->isArrayTy()) {
13481373
return transTypeDesc(TypedPointerType::get(Ty->getArrayElementType(), 0),
1349-
Info);
1374+
Info, IsOpenCL);
13501375
}
13511376
if (Ty->isStructTy()) {
13521377
auto Name = Ty->getStructName();
@@ -1373,6 +1398,13 @@ static SPIR::RefParamType transTypeDesc(Type *Ty,
13731398
return SPIR::RefParamType(new SPIR::UserDefinedType(Name.str()));
13741399
}
13751400
if (auto *TargetTy = dyn_cast<TargetExtType>(Ty)) {
1401+
if (IsOpenCL) {
1402+
SPIR::TypePrimitiveEnum TPE = getOCLTypePrimitiveEnum(TargetTy);
1403+
if (TPE != SPIR::PRIMITIVE_NONE) {
1404+
return SPIR::RefParamType(
1405+
new SPIR::PrimitiveType(getOCLTypePrimitiveEnum(TargetTy)));
1406+
}
1407+
}
13761408
std::string FullName;
13771409
unsigned AS = 0;
13781410
{
@@ -1407,7 +1439,8 @@ static SPIR::RefParamType transTypeDesc(Type *Ty,
14071439
FunctionType *FT = cast<FunctionType>(ET);
14081440
if (InstName.consume_front(kSPIRVName::Prefix) &&
14091441
InstName.starts_with("TaskSequence")) {
1410-
EPT = new SPIR::PointerType(transTypeDesc(FT->getReturnType(), Info));
1442+
EPT = new SPIR::PointerType(
1443+
transTypeDesc(FT->getReturnType(), Info, IsOpenCL));
14111444
} else {
14121445
assert((isVoidFuncTy(FT)) && "Not supported");
14131446
EPT = new SPIR::BlockType;
@@ -1461,7 +1494,7 @@ static SPIR::RefParamType transTypeDesc(Type *Ty,
14611494

14621495
if (VoidPtr && ET->isIntegerTy(8))
14631496
ET = Type::getVoidTy(ET->getContext());
1464-
auto *PT = new SPIR::PointerType(transTypeDesc(ET, Info));
1497+
auto *PT = new SPIR::PointerType(transTypeDesc(ET, Info, IsOpenCL));
14651498
PT->setAddressSpace(static_cast<SPIR::TypeAttributeEnum>(
14661499
TPT->getAddressSpace() + (unsigned)SPIR::ATTR_ADDR_SPACE_FIRST));
14671500
for (unsigned I = SPIR::ATTR_QUALIFIER_FIRST, E = SPIR::ATTR_QUALIFIER_LAST;
@@ -1743,8 +1776,8 @@ std::string mangleBuiltin(StringRef UniqName, ArrayRef<Type *> ArgTypes,
17431776
if (MangleInfo.PointerTy && T->isPointerTy()) {
17441777
T = MangleInfo.PointerTy;
17451778
}
1746-
FD.Parameters.emplace_back(
1747-
transTypeDesc(T, BtnInfo->getTypeMangleInfo(I), UniqName));
1779+
FD.Parameters.emplace_back(transTypeDesc(T, BtnInfo->getTypeMangleInfo(I),
1780+
BtnInfo->isOpenCL(), UniqName));
17481781
}
17491782
}
17501783
// Ellipsis must be the last argument of any function

test/GroupAndSubgroupInstructions.spvasm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@
104104
; CHECK-CL-DAG: declare spir_func i32 @_Z27intel_sub_group_shuffle_xorij(i32, i32) #[[#Attrs]]
105105
; CHECK-CL-DAG: declare spir_func i32 @_Z26intel_sub_group_block_readPU3AS1Kj(ptr addrspace(1)) #[[#Attrs]]
106106
; CHECK-CL-DAG: declare spir_func void @_Z27intel_sub_group_block_writePU3AS1jj(ptr addrspace(1), i32) #[[#Attrs]]
107-
; CHECK-CL-DAG: declare spir_func i32 @_Z26intel_sub_group_block_read14ocl_image2d_rwDv2_i(ptr addrspace(1), <2 x i32>) #[[#Attrs]]
108-
; CHECK-CL-DAG: declare spir_func void @_Z27intel_sub_group_block_write14ocl_image2d_rwDv2_ij(ptr addrspace(1), <2 x i32>, i32) #[[#Attrs]]
107+
; CHECK-CL-DAG: declare spir_func i32 @_Z26intel_sub_group_block_read14ocl_image2d_rwDv2_i(target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 2), <2 x i32>) #[[#Attrs]]
108+
; CHECK-CL-DAG: declare spir_func void @_Z27intel_sub_group_block_write14ocl_image2d_rwDv2_ij(target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 2), <2 x i32>, i32) #[[#Attrs]]
109109
; CHECK-CL-DAG: declare spir_func i32 @_Z15sub_group_electv() #[[#Attrs]]
110110
; CHECK-CL-DAG: declare spir_func i32 @_Z25sub_group_non_uniform_alli(i32) #[[#Attrs]]
111111
; CHECK-CL-DAG: declare spir_func i32 @_Z25sub_group_non_uniform_anyi(i32) #[[#Attrs]]

0 commit comments

Comments
 (0)