Skip to content

Commit 67d3e27

Browse files
aratajewAlexeySotkin
authored andcommitted
Move OCL-IR translation logic related to EIS instructions to SPIRVToOCL pass
This change also fixes vstore translation for SPV-IR generation path and adds test for vstore and printf.
1 parent ebaacc0 commit 67d3e27

File tree

13 files changed

+1612
-78
lines changed

13 files changed

+1612
-78
lines changed

lib/SPIRV/OCLUtil.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,9 @@ class OCLBuiltinFuncMangleInfo : public SPIRV::BuiltinFuncMangleInfo {
987987
if (NameRef.startswith("async_work_group")) {
988988
addUnsignedArg(-1);
989989
setArgAttr(1, SPIR::ATTR_CONST);
990-
} else if (NameRef.startswith("write_imageui"))
990+
} else if (NameRef.startswith("printf"))
991+
setVarArg(1);
992+
else if (NameRef.startswith("write_imageui"))
991993
addUnsignedArg(2);
992994
else if (NameRef.equals("prefetch")) {
993995
addUnsignedArg(1);

lib/SPIRV/SPIRVInternal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,10 @@ template <> inline void SPIRVMap<std::string, Op, SPIRVOpaqueType>::init() {
982982
// Check if the module contains llvm.loop.* metadata
983983
bool hasLoopMetadata(const Module *M);
984984

985+
// Check if CI is a call to instruction from OpenCL Extended Instruction Set.
986+
// If so, return it's extended opcode in ExtOp.
987+
bool isSPIRVOCLExtInst(const CallInst *CI, OCLExtOpKind *ExtOp);
988+
985989
// check LLVM Intrinsics type(s) for validity
986990
bool checkTypeForSPIRVExtendedInstLowering(IntrinsicInst *II, SPIRVModule *BM);
987991
} // namespace SPIRV

lib/SPIRV/SPIRVReader.cpp

Lines changed: 12 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -4224,88 +4224,25 @@ bool SPIRVToLLVM::transAlign(SPIRVValue *BV, Value *V) {
42244224
return true;
42254225
}
42264226

4227-
void SPIRVToLLVM::transOCLVectorLoadStore(std::string &UnmangledName,
4228-
std::vector<SPIRVWord> &BArgs) {
4229-
if (UnmangledName.find("vload") == 0 &&
4230-
UnmangledName.find("n") != std::string::npos) {
4231-
if (BArgs.back() != 1) {
4232-
std::stringstream SS;
4233-
SS << BArgs.back();
4234-
UnmangledName.replace(UnmangledName.find("n"), 1, SS.str());
4235-
} else {
4236-
UnmangledName.erase(UnmangledName.find("n"), 1);
4237-
}
4238-
BArgs.pop_back();
4239-
} else if (UnmangledName.find("vstore") == 0) {
4240-
if (UnmangledName.find("n") != std::string::npos) {
4241-
auto T = BM->getValueType(BArgs[0]);
4242-
if (T->isTypeVector()) {
4243-
auto W = T->getVectorComponentCount();
4244-
std::stringstream SS;
4245-
SS << W;
4246-
UnmangledName.replace(UnmangledName.find("n"), 1, SS.str());
4247-
} else {
4248-
UnmangledName.erase(UnmangledName.find("n"), 1);
4249-
}
4250-
}
4251-
if (UnmangledName.find("_r") != std::string::npos) {
4252-
UnmangledName.replace(
4253-
UnmangledName.find("_r"), 2,
4254-
std::string("_") +
4255-
SPIRSPIRVFPRoundingModeMap::rmap(
4256-
static_cast<SPIRVFPRoundingModeKind>(BArgs.back())));
4257-
BArgs.pop_back();
4258-
}
4259-
}
4260-
}
4261-
4262-
// printf is not mangled. The function type should have just one argument.
4263-
// read_image*: the second argument should be mangled as sampler.
42644227
Instruction *SPIRVToLLVM::transOCLBuiltinFromExtInst(SPIRVExtInst *BC,
42654228
BasicBlock *BB) {
42664229
assert(BB && "Invalid BB");
4267-
std::string MangledName;
4268-
SPIRVWord EntryPoint = BC->getExtOp();
4269-
std::string UnmangledName;
4270-
std::vector<SPIRVWord> BArgs = BC->getArguments();
4230+
auto ExtOp = static_cast<OCLExtOpKind>(BC->getExtOp());
4231+
std::string UnmangledName = OCLExtOpMap::map(ExtOp);
42714232

42724233
assert(BM->getBuiltinSet(BC->getExtSetId()) == SPIRVEIS_OpenCL &&
42734234
"Not OpenCL extended instruction");
42744235

4275-
bool IsPrintf = (EntryPoint == OpenCLLIB::Printf);
4276-
UnmangledName = OCLExtOpMap::map(static_cast<OCLExtOpKind>(EntryPoint));
4277-
4278-
SPIRVDBG(spvdbgs() << "[transOCLBuiltinFromExtInst] OrigUnmangledName: "
4279-
<< UnmangledName << '\n');
4280-
transOCLVectorLoadStore(UnmangledName, BArgs);
4281-
4282-
std::vector<Type *> ArgTypes = transTypeVector(BC->getValueTypes(BArgs));
4283-
4284-
// TODO: we should always produce SPIR-V friendly IR and apply lowering
4285-
// later if needed
4286-
if (IsPrintf) {
4287-
ArgTypes.resize(1);
4288-
}
4289-
4236+
std::vector<Type *> ArgTypes = transTypeVector(BC->getArgTypes());
42904237
Type *RetTy = transType(BC->getType());
4291-
if (BM->getDesiredBIsRepresentation() != BIsRepresentation::SPIRVFriendlyIR) {
4292-
// Convert extended instruction into an OpenCL built-in
4293-
if (IsPrintf) {
4294-
MangledName = "printf";
4295-
} else {
4296-
mangleOpenClBuiltin(UnmangledName, ArgTypes, MangledName);
4297-
}
4298-
} else {
4299-
MangledName = getSPIRVFriendlyIRFunctionName(
4300-
static_cast<OCLExtOpKind>(EntryPoint), ArgTypes, RetTy);
4301-
}
4238+
std::string MangledName =
4239+
getSPIRVFriendlyIRFunctionName(ExtOp, ArgTypes, RetTy);
43024240

4303-
SPIRVDBG(spvdbgs() << "[transOCLBuiltinFromExtInst] ModifiedUnmangledName: "
4241+
SPIRVDBG(spvdbgs() << "[transOCLBuiltinFromExtInst] UnmangledName: "
43044242
<< UnmangledName << " MangledName: " << MangledName
43054243
<< '\n');
43064244

4307-
FunctionType *FT = FunctionType::get(RetTy, ArgTypes,
4308-
/* IsVarArg */ IsPrintf);
4245+
FunctionType *FT = FunctionType::get(RetTy, ArgTypes, false);
43094246
Function *F = M->getFunction(MangledName);
43104247
if (!F) {
43114248
F = Function::Create(FT, GlobalValue::ExternalLinkage, MangledName, M);
@@ -4315,17 +4252,17 @@ Instruction *SPIRVToLLVM::transOCLBuiltinFromExtInst(SPIRVExtInst *BC,
43154252
if (isFuncReadNone(UnmangledName))
43164253
F->addFnAttr(Attribute::ReadNone);
43174254
}
4318-
auto Args = transValue(BC->getValues(BArgs), F, BB);
4255+
auto Args = transValue(BC->getArgValues(), F, BB);
43194256
SPIRVDBG(dbgs() << "[transOCLBuiltinFromExtInst] Function: " << *F
43204257
<< ", Args: ";
43214258
for (auto &I
43224259
: Args) dbgs()
43234260
<< *I << ", ";
43244261
dbgs() << '\n');
4325-
CallInst *Call = CallInst::Create(F, Args, BC->getName(), BB);
4326-
setCallingConv(Call);
4327-
addFnAttr(Call, Attribute::NoUnwind);
4328-
return transOCLBuiltinPostproc(BC, Call, BB, UnmangledName);
4262+
CallInst *CI = CallInst::Create(F, Args, BC->getName(), BB);
4263+
setCallingConv(CI);
4264+
addFnAttr(CI, Attribute::NoUnwind);
4265+
return CI;
43294266
}
43304267

43314268
// SPIR-V only contains language version. Use OpenCL language version as

lib/SPIRV/SPIRVReader.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,6 @@ class SPIRVToLLVM {
123123
SPIRVInstruction *BI, BasicBlock *BB);
124124
Instruction *transOCLBuiltinFromInst(SPIRVInstruction *BI, BasicBlock *BB);
125125
Instruction *transSPIRVBuiltinFromInst(SPIRVInstruction *BI, BasicBlock *BB);
126-
void transOCLVectorLoadStore(std::string &UnmangledName,
127-
std::vector<SPIRVWord> &BArgs);
128126

129127
/// Post-process translated LLVM module for OpenCL.
130128
bool postProcessOCL();

lib/SPIRV/SPIRVToOCL.cpp

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,32 @@ void SPIRVToOCL::visitCallInst(CallInst &CI) {
5353
if (!F)
5454
return;
5555

56+
OCLExtOpKind ExtOp;
57+
if (isSPIRVOCLExtInst(&CI, &ExtOp)) {
58+
switch (ExtOp) {
59+
case OpenCLLIB::Vloadn:
60+
case OpenCLLIB::Vloada_halfn:
61+
case OpenCLLIB::Vload_halfn:
62+
visitCallSPIRVVLoadn(&CI, ExtOp);
63+
break;
64+
case OpenCLLIB::Vstoren:
65+
case OpenCLLIB::Vstore_halfn:
66+
case OpenCLLIB::Vstorea_halfn:
67+
case OpenCLLIB::Vstore_half_r:
68+
case OpenCLLIB::Vstore_halfn_r:
69+
case OpenCLLIB::Vstorea_halfn_r:
70+
visitCallSPIRVVStore(&CI, ExtOp);
71+
break;
72+
case OpenCLLIB::Printf:
73+
visitCallSPIRVPrintf(&CI, ExtOp);
74+
break;
75+
default:
76+
visitCallSPIRVOCLExt(&CI, ExtOp);
77+
break;
78+
}
79+
return;
80+
}
81+
5682
auto MangledName = F->getName();
5783
StringRef DemangledName;
5884
Op OC = OpNop;
@@ -648,6 +674,89 @@ void SPIRVToOCL::visitCallSPIRVBuiltin(CallInst *CI, Op OC) {
648674
&Attrs);
649675
}
650676

677+
void SPIRVToOCL::visitCallSPIRVOCLExt(CallInst *CI, OCLExtOpKind Kind) {
678+
AttributeList Attrs = CI->getCalledFunction()->getAttributes();
679+
mutateCallInstOCL(
680+
M, CI,
681+
[=](CallInst *, std::vector<Value *> &Args) {
682+
return OCLExtOpMap::map(Kind);
683+
},
684+
&Attrs);
685+
}
686+
687+
void SPIRVToOCL::visitCallSPIRVVLoadn(CallInst *CI, OCLExtOpKind Kind) {
688+
AttributeList Attrs = CI->getCalledFunction()->getAttributes();
689+
mutateCallInstOCL(
690+
M, CI,
691+
[=](CallInst *, std::vector<Value *> &Args) {
692+
std::string Name = OCLExtOpMap::map(Kind);
693+
if (ConstantInt *C = dyn_cast<ConstantInt>(Args.back())) {
694+
uint64_t NumComponents = C->getZExtValue();
695+
std::stringstream SS;
696+
SS << NumComponents;
697+
Name.replace(Name.find("n"), 1, SS.str());
698+
}
699+
Args.pop_back();
700+
return Name;
701+
},
702+
&Attrs);
703+
}
704+
705+
void SPIRVToOCL::visitCallSPIRVVStore(CallInst *CI, OCLExtOpKind Kind) {
706+
AttributeList Attrs = CI->getCalledFunction()->getAttributes();
707+
mutateCallInstOCL(
708+
M, CI,
709+
[=](CallInst *, std::vector<Value *> &Args) {
710+
std::string Name = OCLExtOpMap::map(Kind);
711+
if (Kind == OpenCLLIB::Vstore_half_r ||
712+
Kind == OpenCLLIB::Vstore_halfn_r ||
713+
Kind == OpenCLLIB::Vstorea_halfn_r) {
714+
auto C = cast<ConstantInt>(Args.back());
715+
auto RoundingMode =
716+
static_cast<SPIRVFPRoundingModeKind>(C->getZExtValue());
717+
Name.replace(Name.find("_r"), 2,
718+
std::string("_") +
719+
SPIRSPIRVFPRoundingModeMap::rmap(RoundingMode));
720+
Args.pop_back();
721+
}
722+
723+
if (Kind == OpenCLLIB::Vstore_halfn ||
724+
Kind == OpenCLLIB::Vstore_halfn_r ||
725+
Kind == OpenCLLIB::Vstorea_halfn ||
726+
Kind == OpenCLLIB::Vstorea_halfn_r || Kind == OpenCLLIB::Vstoren) {
727+
if (auto DataType = dyn_cast<VectorType>(Args[0]->getType())) {
728+
uint64_t NumElements = DataType->getElementCount().getValue();
729+
assert((NumElements == 2 || NumElements == 3 || NumElements == 4 ||
730+
NumElements == 8 || NumElements == 16) &&
731+
"Unsupported vector size for vstore instruction!");
732+
std::stringstream SS;
733+
SS << NumElements;
734+
Name.replace(Name.find("n"), 1, SS.str());
735+
}
736+
}
737+
738+
return Name;
739+
},
740+
&Attrs);
741+
}
742+
743+
void SPIRVToOCL::visitCallSPIRVPrintf(CallInst *CI, OCLExtOpKind Kind) {
744+
AttributeList Attrs = CI->getCalledFunction()->getAttributes();
745+
CallInst *NewCI = mutateCallInstOCL(
746+
M, CI,
747+
[=](CallInst *, std::vector<Value *> &Args) {
748+
return OCLExtOpMap::map(OpenCLLIB::Printf);
749+
},
750+
&Attrs);
751+
752+
// Clang represents printf function without mangling
753+
std::string TargetName = "printf";
754+
if (Function *F = M->getFunction(TargetName))
755+
NewCI->setCalledFunction(F);
756+
else
757+
NewCI->getCalledFunction()->setName(TargetName);
758+
}
759+
651760
std::string SPIRVToOCL::getGroupBuiltinPrefix(CallInst *CI) {
652761
std::string Prefix;
653762
auto ES = getArgAsScope(CI, 0);

lib/SPIRV/SPIRVToOCL.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,19 @@ class SPIRVToOCL : public ModulePass, public InstVisitor<SPIRVToOCL> {
120120
/// No change with arguments.
121121
void visitCallSPIRVBuiltin(CallInst *CI, Op OC);
122122

123+
/// Transform __spirv_ocl* instructions (OpenCL Extended Instruction Set)
124+
/// to OpenCL builtins.
125+
void visitCallSPIRVOCLExt(CallInst *CI, OCLExtOpKind Kind);
126+
127+
/// Transform __spirv_ocl_vstore* to corresponding vstore OpenCL instruction
128+
void visitCallSPIRVVStore(CallInst *CI, OCLExtOpKind Kind);
129+
130+
/// Transform __spirv_ocl_vloadn to OpenCL vload[2|4|8|16]
131+
void visitCallSPIRVVLoadn(CallInst *CI, OCLExtOpKind Kind);
132+
133+
/// Transform __spirv_ocl_printf to (i8 addrspace(2)*, ...) @printf
134+
void visitCallSPIRVPrintf(CallInst *CI, OCLExtOpKind Kind);
135+
123136
/// Get prefix work_/sub_ for OCL group builtin functions.
124137
/// Assuming the first argument of \param CI is a constant integer for
125138
/// workgroup/subgroup scope enums.

lib/SPIRV/SPIRVUtil.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,6 +1524,35 @@ bool hasLoopMetadata(const Module *M) {
15241524
return false;
15251525
}
15261526

1527+
bool isSPIRVOCLExtInst(const CallInst *CI, OCLExtOpKind *ExtOp) {
1528+
StringRef DemangledName;
1529+
if (!oclIsBuiltin(CI->getCalledFunction()->getName(), DemangledName))
1530+
return false;
1531+
StringRef S = DemangledName;
1532+
if (!S.startswith(kSPIRVName::Prefix))
1533+
return false;
1534+
S = S.drop_front(strlen(kSPIRVName::Prefix));
1535+
auto Loc = S.find(kSPIRVPostfix::Divider);
1536+
auto ExtSetName = S.substr(0, Loc);
1537+
SPIRVExtInstSetKind Set = SPIRVEIS_Count;
1538+
if (!SPIRVExtSetShortNameMap::rfind(ExtSetName.str(), &Set))
1539+
return false;
1540+
1541+
if (Set != SPIRVEIS_OpenCL)
1542+
return false;
1543+
1544+
auto ExtOpName = S.substr(Loc + 1);
1545+
auto PostFixPos = ExtOpName.find("_R");
1546+
ExtOpName = ExtOpName.substr(0, PostFixPos);
1547+
1548+
OCLExtOpKind EOC;
1549+
if (!OCLExtOpMap::rfind(ExtOpName.str(), &EOC))
1550+
return false;
1551+
1552+
*ExtOp = EOC;
1553+
return true;
1554+
}
1555+
15271556
// Returns true if type(s) and number of elements (if vector) is valid
15281557
bool checkTypeForSPIRVExtendedInstLowering(IntrinsicInst *II, SPIRVModule *BM) {
15291558
switch (II->getIntrinsicID()) {

lib/SPIRV/libSPIRV/SPIRVInstruction.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1865,6 +1865,23 @@ class SPIRVExtInst : public SPIRVFunctionCallGeneric<OpExtInst, 5> {
18651865
return Index == 3;
18661866
}
18671867
}
1868+
std::vector<SPIRVValue *> getArgValues() {
1869+
std::vector<SPIRVValue *> VArgs;
1870+
for (size_t I = 0; I < Args.size(); ++I) {
1871+
if (isOperandLiteral(I))
1872+
VArgs.push_back(Module->getLiteralAsConstant(Args[I]));
1873+
else
1874+
VArgs.push_back(getValue(Args[I]));
1875+
}
1876+
return VArgs;
1877+
}
1878+
std::vector<SPIRVType *> getArgTypes() {
1879+
std::vector<SPIRVType *> ArgTypes;
1880+
auto VArgs = getArgValues();
1881+
for (auto VArg : VArgs)
1882+
ArgTypes.push_back(VArg->getType());
1883+
return ArgTypes;
1884+
}
18681885

18691886
protected:
18701887
SPIRVExtInstSetKind ExtSetKind;

0 commit comments

Comments
 (0)