Skip to content

Commit e440fbd

Browse files
jcranmer-inteldwoodwor-intel
authored andcommitted
Pass pointer type information into mangleBuiltin. (#1549)
This includes a rejigging of the BuiltinFuncMangleInfo to actually act as the source of information to pass this information into. Only some of the call sites of mangleBuiltin have been properly updated to pass in the pointer type element information. The various mutateCallInst* callers have yet to be updated, so those methods are temporarily relying on querying getPointerElementType() to generate this information. Original commit: KhronosGroup/SPIRV-LLVM-Translator@0eb9a7d
1 parent 75b547f commit e440fbd

File tree

9 files changed

+256
-99
lines changed

9 files changed

+256
-99
lines changed

llvm-spirv/include/LLVMSPIRVLib.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ std::unique_ptr<SPIRVModule> readSpirvModule(std::istream &IS,
106106
const SPIRV::TranslatorOpts &Opts,
107107
std::string &ErrMsg);
108108

109+
/// This contains a pair of the pointer element type and an indirection
110+
/// parameter (to capture cases where an array of OpenCL types is used).
111+
typedef llvm::PointerIntPair<llvm::Type *, 1, bool> PointerIndirectPair;
112+
109113
} // End namespace SPIRV
110114

111115
namespace llvm {
@@ -156,8 +160,13 @@ bool regularizeLlvmForSpirv(Module *M, std::string &ErrMsg,
156160
const SPIRV::TranslatorOpts &Opts);
157161

158162
/// \brief Mangle OpenCL builtin function function name.
163+
/// If any type in ArgTypes is a pointer type, the corresponding entry in
164+
/// ArgPointerTypes should contain the type should point to. If there are no
165+
/// pointer-typed arguments in ArgTypes, then ArgPointerTypes may be empty.
159166
void mangleOpenClBuiltin(const std::string &UnmangledName,
160-
ArrayRef<Type *> ArgTypes, std::string &MangledName);
167+
ArrayRef<Type *> ArgTypes,
168+
ArrayRef<SPIRV::PointerIndirectPair> ArgPointerTypes,
169+
std::string &MangledName);
161170

162171
/// Create a pass for translating LLVM to SPIR-V.
163172
ModulePass *createLLVMToSPIRVLegacy(SPIRV::SPIRVModule *);

llvm-spirv/lib/SPIRV/OCLToSPIRV.cpp

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,7 +1009,8 @@ void OCLToSPIRVBase::visitCallReadImageWithSampler(CallInst *CI,
10091009
Value *SampledImgArgs[] = {Args[0], Args[1]};
10101010
auto SampledImg = addCallInstSPIRV(
10111011
M, getSPIRVFuncName(OpSampledImage), SampledImgTy, SampledImgArgs,
1012-
nullptr, CI, kSPIRVName::TempSampledImage);
1012+
nullptr, {ArgStructTys[0], ArgStructTys[1]}, CI,
1013+
kSPIRVName::TempSampledImage);
10131014

10141015
Args[0] = SampledImg;
10151016
Args.erase(Args.begin() + 1, Args.begin() + 2);
@@ -1645,13 +1646,16 @@ void OCLToSPIRVBase::visitSubgroupAVCWrapperBuiltinCall(
16451646
getSubgroupAVCIntelTyKind(CI->getCalledFunction()->getName());
16461647
std::string MCETName =
16471648
std::string(kOCLSubgroupsAVCIntel::TypePrefix) + "mce_" + TyKind + "_t";
1648-
auto *MCETy =
1649-
PointerType::get(getSubgroupAVCIntelMCEType(M, MCETName), SPIRAS_Private);
1649+
auto *MCESTy = getSubgroupAVCIntelMCEType(M, MCETName);
1650+
auto *MCETy = PointerType::get(MCESTy, SPIRAS_Private);
16501651
std::string ToMCEFName = Prefix + OpKind + "_convert_to_mce_" + TyKind;
16511652
Op ToMCEOC = OpNop;
16521653
OCLSPIRVSubgroupAVCIntelBuiltinMap::find(ToMCEFName, &ToMCEOC);
16531654
assert(ToMCEOC != OpNop && "Invalid Subgroup AVC Intel built-in call");
16541655

1656+
SmallVector<StructType *, 2> ParamTys;
1657+
getParameterTypes(CI, ParamTys);
1658+
16551659
if (std::strcmp(TyKind, "payload") == 0) {
16561660
// Wrapper built-ins which take the 'payload_t' argument return it as
16571661
// the result: two conversion calls required.
@@ -1666,16 +1670,16 @@ void OCLToSPIRVBase::visitSubgroupAVCWrapperBuiltinCall(
16661670
[=](CallInst *, std::vector<Value *> &Args, Type *&Ret) {
16671671
Ret = MCETy;
16681672
// Create conversion function call for the last operand
1669-
Args[Args.size() - 1] =
1670-
addCallInstSPIRV(M, getSPIRVFuncName(ToMCEOC), MCETy,
1671-
Args[Args.size() - 1], nullptr, CI, "");
1673+
Args[Args.size() - 1] = addCallInstSPIRV(
1674+
M, getSPIRVFuncName(ToMCEOC), MCETy, Args[Args.size() - 1],
1675+
nullptr, {ParamTys[Args.size() - 1]}, CI, "");
16721676

16731677
return getSPIRVFuncName(WrappedOC);
16741678
},
16751679
[=](CallInst *NewCI) -> Instruction * {
16761680
// Create conversion function call for the return result
16771681
return addCallInstSPIRV(M, getSPIRVFuncName(FromMCEOC), CI->getType(),
1678-
NewCI, nullptr, CI, "");
1682+
NewCI, nullptr, {MCESTy}, CI, "");
16791683
},
16801684
&Attrs);
16811685
} else {
@@ -1686,9 +1690,9 @@ void OCLToSPIRVBase::visitSubgroupAVCWrapperBuiltinCall(
16861690
[=](CallInst *, std::vector<Value *> &Args) {
16871691
// Create conversion function call for the last
16881692
// operand
1689-
Args[Args.size() - 1] =
1690-
addCallInstSPIRV(M, getSPIRVFuncName(ToMCEOC), MCETy,
1691-
Args[Args.size() - 1], nullptr, CI, "");
1693+
Args[Args.size() - 1] = addCallInstSPIRV(
1694+
M, getSPIRVFuncName(ToMCEOC), MCETy, Args[Args.size() - 1],
1695+
nullptr, {ParamTys[Args.size() - 1]}, CI, "");
16921696

16931697
return getSPIRVFuncName(WrappedOC);
16941698
},
@@ -1726,6 +1730,7 @@ void OCLToSPIRVBase::visitSubgroupAVCBuiltinCallWithSampler(
17261730
"Invalid Subgroup AVC Intel built-in call");
17271731
auto SamplerIt = Args.begin() + (TyIt - ParamTys.begin());
17281732
auto *SamplerVal = *SamplerIt;
1733+
auto *SamplerTy = *TyIt;
17291734
Args.erase(SamplerIt);
17301735
ParamTys.erase(TyIt);
17311736

@@ -1745,7 +1750,8 @@ void OCLToSPIRVBase::visitSubgroupAVCBuiltinCallWithSampler(
17451750

17461751
Value *SampledImgArgs[] = {Args[I], SamplerVal};
17471752
Args[I] = addCallInstSPIRV(M, getSPIRVFuncName(OpVmeImageINTEL),
1748-
SampledImgTy, SampledImgArgs, nullptr, CI,
1753+
SampledImgTy, SampledImgArgs, nullptr,
1754+
{ParamTys[I], SamplerTy}, CI,
17491755
kSPIRVName::TempSampledImage);
17501756
}
17511757
return getSPIRVFuncName(OC);

llvm-spirv/lib/SPIRV/OCLUtil.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,9 +1146,11 @@ class OCLBuiltinFuncMangleInfo : public SPIRV::BuiltinFuncMangleInfo {
11461146
} else if (NameRef.startswith("vstore")) {
11471147
addUnsignedArg(1);
11481148
} else if (NameRef.startswith("ndrange_")) {
1149-
addUnsignedArg(-1);
1149+
addUnsignedArgs(0, 2);
11501150
if (NameRef[8] == '2' || NameRef[8] == '3') {
1151-
setArgAttr(-1, SPIR::ATTR_CONST);
1151+
setArgAttr(0, SPIR::ATTR_CONST);
1152+
setArgAttr(1, SPIR::ATTR_CONST);
1153+
setArgAttr(2, SPIR::ATTR_CONST);
11521154
}
11531155
} else if (NameRef.contains("umax")) {
11541156
addUnsignedArg(-1);
@@ -1594,7 +1596,9 @@ Value *SPIRV::transSPIRVMemorySemanticsIntoOCLMemFenceFlags(
15941596

15951597
void llvm::mangleOpenClBuiltin(const std::string &UniqName,
15961598
ArrayRef<Type *> ArgTypes,
1599+
ArrayRef<PointerIndirectPair> PointerElementTys,
15971600
std::string &MangledName) {
15981601
OCLUtil::OCLBuiltinFuncMangleInfo BtnInfo(ArgTypes);
1602+
BtnInfo.fillPointerElementTypes(PointerElementTys);
15991603
MangledName = SPIRV::mangleBuiltin(UniqName, ArgTypes, &BtnInfo);
16001604
}

llvm-spirv/lib/SPIRV/SPIRVInternal.h

Lines changed: 38 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -456,10 +456,11 @@ struct BuiltinArgTypeMangleInfo {
456456
bool IsLocalArgBlock;
457457
SPIR::TypePrimitiveEnum Enum;
458458
unsigned Attr;
459+
PointerIndirectPair PointerElementType;
459460
BuiltinArgTypeMangleInfo()
460461
: IsSigned(true), IsVoidPtr(false), IsEnum(false), IsSampler(false),
461462
IsAtomic(false), IsLocalArgBlock(false), Enum(SPIR::PRIMITIVE_NONE),
462-
Attr(0) {}
463+
Attr(0), PointerElementType(nullptr, false) {}
463464
};
464465

465466
/// Information for mangling builtin function.
@@ -468,92 +469,61 @@ class BuiltinFuncMangleInfo {
468469
/// Translate builtin function name and set
469470
/// argument attributes and unsigned args.
470471
BuiltinFuncMangleInfo(const std::string &UniqName = "")
471-
: LocalArgBlockIdx(-1), VarArgIdx(-1), DontMangle(false) {
472+
: VarArgIdx(-1), DontMangle(false) {
472473
if (!UniqName.empty())
473474
init(UniqName);
474475
}
475476
virtual ~BuiltinFuncMangleInfo() {}
476477
const std::string &getUnmangledName() const { return UnmangledName; }
477-
void addUnsignedArg(int Ndx) { UnsignedArgs.insert(Ndx); }
478+
void addUnsignedArg(int Ndx) {
479+
if (Ndx == -1)
480+
return addUnsignedArgs(0, 10); // 10 is enough for everybody, right?
481+
getTypeMangleInfo(Ndx).IsSigned = false;
482+
}
478483
void addUnsignedArgs(int StartNdx, int StopNdx) {
479484
assert(StartNdx < StopNdx && "wrong parameters");
480485
for (int I = StartNdx; I <= StopNdx; ++I)
481486
addUnsignedArg(I);
482487
}
483-
void addVoidPtrArg(int Ndx) { VoidPtrArgs.insert(Ndx); }
484-
void addSamplerArg(int Ndx) { SamplerArgs.insert(Ndx); }
485-
void addAtomicArg(int Ndx) { AtomicArgs.insert(Ndx); }
486-
void setLocalArgBlock(int Ndx) {
487-
assert(0 <= Ndx && "it is not allowed to set less than zero index");
488-
LocalArgBlockIdx = Ndx;
488+
void addVoidPtrArg(unsigned Ndx) { getTypeMangleInfo(Ndx).IsVoidPtr = true; }
489+
void addSamplerArg(unsigned Ndx) { getTypeMangleInfo(Ndx).IsSampler = true; }
490+
void addAtomicArg(unsigned Ndx) { getTypeMangleInfo(Ndx).IsAtomic = true; }
491+
void setLocalArgBlock(unsigned Ndx) {
492+
getTypeMangleInfo(Ndx).IsLocalArgBlock = true;
489493
}
490-
void setEnumArg(int Ndx, SPIR::TypePrimitiveEnum Enum) {
491-
EnumArgs[Ndx] = Enum;
494+
void setEnumArg(unsigned Ndx, SPIR::TypePrimitiveEnum Enum) {
495+
auto &Info = getTypeMangleInfo(Ndx);
496+
Info.IsEnum = true;
497+
Info.Enum = Enum;
498+
}
499+
void setArgAttr(unsigned Ndx, unsigned Attr) {
500+
getTypeMangleInfo(Ndx).Attr = Attr;
492501
}
493-
void setArgAttr(int Ndx, unsigned Attr) { Attrs[Ndx] = Attr; }
494502
void setVarArg(int Ndx) {
495503
assert(0 <= Ndx && "it is not allowed to set less than zero index");
496504
VarArgIdx = Ndx;
497505
}
498506
void setAsDontMangle() { DontMangle = true; }
499-
bool isArgUnsigned(int Ndx) {
500-
return UnsignedArgs.count(-1) || UnsignedArgs.count(Ndx);
501-
}
502-
bool isArgVoidPtr(int Ndx) {
503-
return VoidPtrArgs.count(-1) || VoidPtrArgs.count(Ndx);
504-
}
505-
bool isArgSampler(int Ndx) { return SamplerArgs.count(Ndx); }
506-
bool isArgAtomic(int Ndx) { return AtomicArgs.count(Ndx); }
507-
bool isLocalArgBlock(int Ndx) { return LocalArgBlockIdx == Ndx; }
508-
bool isArgEnum(int Ndx, SPIR::TypePrimitiveEnum *Enum = nullptr) {
509-
auto Loc = EnumArgs.find(Ndx);
510-
if (Loc == EnumArgs.end())
511-
Loc = EnumArgs.find(-1);
512-
if (Loc == EnumArgs.end())
513-
return false;
514-
if (Enum)
515-
*Enum = Loc->second;
516-
return true;
517-
}
518507
bool avoidMangling() { return DontMangle; }
519-
unsigned getArgAttr(int Ndx) {
520-
auto Loc = Attrs.find(Ndx);
521-
if (Loc == Attrs.end())
522-
Loc = Attrs.find(-1);
523-
if (Loc == Attrs.end())
524-
return 0;
525-
return Loc->second;
526-
}
527508
// get ellipsis index, single ellipsis at the end of the function is possible
528509
// only return value < 0 if none
529510
int getVarArg() const { return VarArgIdx; }
530-
BuiltinArgTypeMangleInfo getTypeMangleInfo(int Ndx) {
531-
BuiltinArgTypeMangleInfo Info;
532-
Info.IsSigned = !isArgUnsigned(Ndx);
533-
Info.IsVoidPtr = isArgVoidPtr(Ndx);
534-
Info.IsEnum = isArgEnum(Ndx, &Info.Enum);
535-
Info.IsSampler = isArgSampler(Ndx);
536-
Info.IsAtomic = isArgAtomic(Ndx);
537-
Info.IsLocalArgBlock = isLocalArgBlock(Ndx);
538-
Info.Attr = getArgAttr(Ndx);
511+
BuiltinArgTypeMangleInfo &getTypeMangleInfo(unsigned Ndx) {
512+
while (Ndx >= ArgInfo.size())
513+
ArgInfo.emplace_back();
514+
BuiltinArgTypeMangleInfo &Info = ArgInfo[Ndx];
539515
return Info;
540516
}
541517
virtual void init(StringRef UniqUnmangledName) {
542518
UnmangledName = UniqUnmangledName.str();
543519
}
544520

521+
void fillPointerElementTypes(ArrayRef<PointerIndirectPair>);
522+
545523
protected:
546524
std::string UnmangledName;
547-
std::set<int> UnsignedArgs; // unsigned arguments, or -1 if all are unsigned
548-
std::set<int> VoidPtrArgs; // void pointer arguments, or -1 if all are void
549-
// pointer
550-
std::set<int> SamplerArgs; // sampler arguments
551-
std::set<int> AtomicArgs; // atomic arguments
552-
std::map<int, SPIR::TypePrimitiveEnum> EnumArgs; // enum arguments
553-
std::map<int, unsigned> Attrs; // argument attributes
554-
int LocalArgBlockIdx; // index of a block with local arguments, idx < 0 if
555-
// none
556-
int VarArgIdx; // index of ellipsis argument, idx < 0 if none
525+
std::vector<BuiltinArgTypeMangleInfo> ArgInfo;
526+
int VarArgIdx; // index of ellipsis argument, idx < 0 if none
557527
private:
558528
bool DontMangle; // clang doesn't apply mangling for some builtin functions
559529
// (i.e. enqueue_kernel)
@@ -597,7 +567,8 @@ void removeFnAttr(CallInst *Call, Attribute::AttrKind Attr);
597567
void addFnAttr(CallInst *Call, Attribute::AttrKind Attr);
598568
void saveLLVMModule(Module *M, const std::string &OutputFile);
599569
std::string mapSPIRVTypeToOCLType(SPIRVType *Ty, bool Signed);
600-
std::string mapLLVMTypeToOCLType(const Type *Ty, bool Signed);
570+
std::string mapLLVMTypeToOCLType(const Type *Ty, bool Signed,
571+
Type *PointerElementType = nullptr);
601572
SPIRVDecorate *mapPostfixToDecorate(StringRef Postfix, SPIRVEntry *Target);
602573

603574
/// Add decorations to a SPIR-V entry.
@@ -681,7 +652,8 @@ StringRef dePrefixSPIRVName(StringRef R, SmallVectorImpl<StringRef> &Postfix);
681652
/// Get a canonical function name for a SPIR-V op code.
682653
std::string getSPIRVFuncName(Op OC, StringRef PostFix = "");
683654

684-
std::string getSPIRVFuncName(Op OC, const Type *PRetTy, bool IsSigned = false);
655+
std::string getSPIRVFuncName(Op OC, const Type *PRetTy, bool IsSigned = false,
656+
Type *PointerElementType = nullptr);
685657

686658
std::string getSPIRVFuncName(SPIRVBuiltinVariableKind BVKind);
687659

@@ -784,6 +756,7 @@ CallInst *addCallInst(Module *M, StringRef FuncName, Type *RetTy,
784756
/// Add a call instruction for SPIR-V builtin function.
785757
CallInst *addCallInstSPIRV(Module *M, StringRef FuncName, Type *RetTy,
786758
ArrayRef<Value *> Args, AttributeList *Attrs,
759+
ArrayRef<Type *> PointerElementTypes,
787760
Instruction *Pos, StringRef InstName);
788761

789762
/// Add a call of spir_block_bind function.
@@ -888,7 +861,8 @@ std::string getPostfix(Decoration Dec, unsigned Value = 0);
888861
/// Get postfix _R{ReturnType} for return type
889862
/// The returned postfix does not includ "_" at the beginning
890863
std::string getPostfixForReturnType(CallInst *CI, bool IsSigned = false);
891-
std::string getPostfixForReturnType(const Type *PRetTy, bool IsSigned = false);
864+
std::string getPostfixForReturnType(const Type *PRetTy, bool IsSigned = false,
865+
Type *PointerElementType = nullptr);
892866

893867
Constant *getScalarOrVectorConstantInt(Type *T, uint64_t V,
894868
bool IsSigned = false);
@@ -1012,6 +986,7 @@ inline void getParameterTypes(CallInst *CI,
1012986
/// manner
1013987
std::string getSPIRVFriendlyIRFunctionName(OCLExtOpKind ExtOpId,
1014988
ArrayRef<Type *> ArgTys,
989+
ArrayRef<PointerIndirectPair> PETs,
1015990
Type *RetTy = nullptr);
1016991

1017992
/// Mangle a function in SPIR-V friendly IR manner
@@ -1023,7 +998,8 @@ std::string getSPIRVFriendlyIRFunctionName(OCLExtOpKind ExtOpId,
1023998
/// \param Types of arguments of SPIR-V built-in function
1024999
/// \return IA64 mangled name.
10251000
std::string getSPIRVFriendlyIRFunctionName(const std::string &UniqName,
1026-
spv::Op OC, ArrayRef<Type *> ArgTys);
1001+
spv::Op OC, ArrayRef<Type *> ArgTys,
1002+
ArrayRef<PointerIndirectPair> PETs);
10271003

10281004
/// Cast a function to a void(void) funtion pointer.
10291005
Constant *castToVoidFuncPtr(Function *F);

0 commit comments

Comments
 (0)