Skip to content

Commit cf94188

Browse files
Artem Gindinsonromanovvlad
Artem Gindinson
authored andcommitted
Sync with SPIRV-LLVM-Translator 55f2041f2c
Synced with: 55f2041f2c Open SPIR-V output file as a binary file As in sync 11e6695, this excludes following syncs with LLVM: 2cdb947d4 Update LLVM to r358377 72bcddd08 Sync with LLVM 6183f7c486 Sync with LLVM Signed-off-by: Artem Gindinson <[email protected]>
1 parent 3378926 commit cf94188

30 files changed

+321
-59
lines changed

llvm-spirv/include/LLVMSPIRVLib.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ bool isSpirvBinary(std::string &Img);
7979
bool convertSpirv(std::istream &IS, std::ostream &OS, std::string &ErrMsg,
8080
bool FromText, bool ToText);
8181

82-
/// \brief Convert SPIR-V between binary and internel text formats.
82+
/// \brief Convert SPIR-V between binary and internal text formats.
8383
/// This function is not thread safe and should not be used in multi-thread
8484
/// applications unless guarded by a critical section.
8585
bool convertSpirv(std::string &Input, std::string &Out, std::string &ErrMsg,
@@ -93,11 +93,11 @@ bool isSpirvText(std::string &Img);
9393

9494
namespace llvm {
9595

96-
/// \brief Translate LLVM module to SPIRV and write to ostream.
96+
/// \brief Translate LLVM module to SPIR-V and write to ostream.
9797
/// \returns true if succeeds.
9898
bool writeSpirv(Module *M, std::ostream &OS, std::string &ErrMsg);
9999

100-
/// \brief Load SPIRV from istream and translate to LLVM module.
100+
/// \brief Load SPIR-V from istream and translate to LLVM module.
101101
/// \returns true if succeeds.
102102
bool readSpirv(LLVMContext &C, std::istream &IS, Module *&M,
103103
std::string &ErrMsg);

llvm-spirv/lib/SPIRV/OCL20ToSPIRV.cpp

+9-8
Original file line numberDiff line numberDiff line change
@@ -1111,7 +1111,7 @@ void OCL20ToSPIRV::visitCallReadImageWithSampler(
11111111
assert(0 && "read_image* with unhandled number of args!");
11121112
}
11131113

1114-
// SPIR-V intruction always returns 4-element vector
1114+
// SPIR-V instruction always returns 4-element vector
11151115
if (IsRetScalar)
11161116
Ret = VectorType::get(Ret, 4);
11171117
return getSPIRVFuncName(OpImageSampleExplicitLod,
@@ -1687,13 +1687,14 @@ void OCL20ToSPIRV::visitSubgroupImageMediaBlockINTEL(
16871687
spv::Op OpCode = DemangledName.rfind("read") != std::string::npos
16881688
? spv::OpSubgroupImageMediaBlockReadINTEL
16891689
: spv::OpSubgroupImageMediaBlockWriteINTEL;
1690-
mutateCallInstSPIRV(M, CI,
1691-
[=](CallInst *, std::vector<Value *> &Args) {
1692-
// Moving the last argument to the begining.
1693-
std::rotate(Args.begin(), Args.end() - 1, Args.end());
1694-
return getSPIRVFuncName(OpCode, CI->getType());
1695-
},
1696-
&Attrs);
1690+
mutateCallInstSPIRV(
1691+
M, CI,
1692+
[=](CallInst *, std::vector<Value *> &Args) {
1693+
// Moving the last argument to the beginning.
1694+
std::rotate(Args.begin(), Args.end() - 1, Args.end());
1695+
return getSPIRVFuncName(OpCode, CI->getType());
1696+
},
1697+
&Attrs);
16971698
}
16981699

16991700
static const char *getSubgroupAVCIntelOpKind(const std::string &Name) {

llvm-spirv/lib/SPIRV/SPIRVInternal.h

+1
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ enum SPIRAddressSpace {
184184
SPIRAS_Local,
185185
SPIRAS_Generic,
186186
SPIRAS_Input,
187+
SPIRAS_Output,
187188
SPIRAS_Count,
188189
};
189190

llvm-spirv/lib/SPIRV/SPIRVReader.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -2202,6 +2202,10 @@ void generateIntelFPGAAnnotation(const SPIRVEntry *E,
22022202
Out << "{numbanks:" << Result << '}';
22032203
if (E->hasDecorate(DecorationMaxconcurrencyINTEL, 0, &Result))
22042204
Out << "{max_concurrency:" << Result << '}';
2205+
if (E->hasDecorate(DecorationSinglepumpINTEL))
2206+
Out << "{pump:1}";
2207+
if (E->hasDecorate(DecorationDoublepumpINTEL))
2208+
Out << "{pump:2}";
22052209
}
22062210

22072211
void generateIntelFPGAAnnotationForStructMember(
@@ -2224,6 +2228,10 @@ void generateIntelFPGAAnnotationForStructMember(
22242228
if (E->hasMemberDecorate(DecorationMaxconcurrencyINTEL, 0, MemberNumber,
22252229
&Result))
22262230
Out << "{max_concurrency:" << Result << '}';
2231+
if (E->hasMemberDecorate(DecorationSinglepumpINTEL, 0, MemberNumber))
2232+
Out << "{pump:1}";
2233+
if (E->hasMemberDecorate(DecorationDoublepumpINTEL, 0, MemberNumber))
2234+
Out << "{pump:2}";
22272235
}
22282236

22292237
void SPIRVToLLVM::transIntelFPGADecorations(SPIRVValue *BV, Value *V) {
@@ -2904,6 +2912,7 @@ bool llvm::readSpirv(LLVMContext &C, std::istream &IS, Module *&M,
29042912

29052913
IS >> *BM;
29062914
if (!BM->isModuleValid()) {
2915+
BM->getError(ErrMsg);
29072916
M = nullptr;
29082917
return false;
29092918
}

llvm-spirv/lib/SPIRV/SPIRVToOCL20.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class SPIRVToOCL20 : public ModulePass, public InstVisitor<SPIRVToOCL20> {
7777
// appropriate calls to conversion built-ins defined by the standards.
7878
void visitCastInst(CastInst &CI);
7979

80-
/// Transform __spirv_ImageQuerySize[Lod] into vector of the same lenght
80+
/// Transform __spirv_ImageQuerySize[Lod] into vector of the same length
8181
/// containing {[get_image_width | get_image_dim], get_image_array_size}
8282
/// for all images except image1d_t which is always converted into
8383
/// get_image_width returning scalar result.

llvm-spirv/lib/SPIRV/SPIRVUtil.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1210,7 +1210,7 @@ Type *getSPIRVTypeByChangeBaseTypeName(Module *M, Type *T, StringRef OldName,
12101210
if (isSPIRVType(T, OldName, &Postfixes))
12111211
return getOrCreateOpaquePtrType(M, getSPIRVTypeName(NewName, Postfixes));
12121212
LLVM_DEBUG(dbgs() << " Invalid SPIR-V type " << *T << '\n');
1213-
llvm_unreachable("Invalid SPIRV-V type");
1213+
llvm_unreachable("Invalid SPIR-V type");
12141214
return nullptr;
12151215
}
12161216

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

+113-16
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ LLVMToSPIRV::LLVMToSPIRV(SPIRVModule *SMod)
128128

129129
bool LLVMToSPIRV::runOnModule(Module &Mod) {
130130
M = &Mod;
131+
CG = make_unique<CallGraph>(Mod);
131132
Ctx = &M->getContext();
132133
DbgTran->setModule(M);
133134
assert(BM && "SPIR-V module not initialized");
@@ -1127,16 +1128,25 @@ parseAnnotations(StringRef AnnotatedCode) {
11271128
StringRef AnnotatedDecoration = AnnotatedCode.substr(From + 1, To - 1);
11281129
std::pair<StringRef, StringRef> D = AnnotatedDecoration.split(':');
11291130

1130-
StringRef F = D.first;
1131-
Decoration Dec =
1132-
llvm::StringSwitch<Decoration>(F)
1133-
.Case("memory", DecorationMemoryINTEL)
1134-
.Case("register", DecorationRegisterINTEL)
1135-
.Case("numbanks", DecorationNumbanksINTEL)
1136-
.Case("bankwidth", DecorationBankwidthINTEL)
1137-
.Case("max_concurrency", DecorationMaxconcurrencyINTEL);
1131+
StringRef F = D.first, S = D.second;
1132+
StringRef Value;
1133+
Decoration Dec;
1134+
if (F == "pump") {
1135+
Dec = llvm::StringSwitch<Decoration>(S)
1136+
.Case("1", DecorationSinglepumpINTEL)
1137+
.Case("2", DecorationDoublepumpINTEL);
1138+
} else if (F == "register") {
1139+
Dec = DecorationRegisterINTEL;
1140+
} else {
1141+
Dec = llvm::StringSwitch<Decoration>(F)
1142+
.Case("memory", DecorationMemoryINTEL)
1143+
.Case("numbanks", DecorationNumbanksINTEL)
1144+
.Case("bankwidth", DecorationBankwidthINTEL)
1145+
.Case("max_concurrency", DecorationMaxconcurrencyINTEL);
1146+
Value = S;
1147+
}
11381148

1139-
Decorates.push_back({Dec, D.second});
1149+
Decorates.push_back({Dec, Value});
11401150
AnnotatedCode = AnnotatedCode.drop_front(To + 1);
11411151
}
11421152
return Decorates;
@@ -1146,12 +1156,25 @@ void addIntelFPGADecorations(
11461156
SPIRVEntry *E,
11471157
std::vector<std::pair<Decoration, std::string>> &Decorations) {
11481158
for (const auto &I : Decorations) {
1149-
if (I.first == DecorationMemoryINTEL)
1159+
switch (I.first) {
1160+
case DecorationMemoryINTEL:
11501161
E->addDecorate(new SPIRVDecorateMemoryINTELAttr(E, I.second));
1151-
else {
1162+
break;
1163+
case DecorationRegisterINTEL:
1164+
case DecorationSinglepumpINTEL:
1165+
case DecorationDoublepumpINTEL:
1166+
assert(I.second.empty());
1167+
E->addDecorate(I.first);
1168+
break;
1169+
// The rest of IntelFPGA decorations:
1170+
// DecorationNumbanksINTEL
1171+
// DecorationBankwidthINTEL
1172+
// DecorationMaxconcurrencyINTEL
1173+
default:
11521174
SPIRVWord Result = 0;
11531175
StringRef(I.second).getAsInteger(10, Result);
11541176
E->addDecorate(I.first, Result);
1177+
break;
11551178
}
11561179
}
11571180
}
@@ -1160,13 +1183,26 @@ void addIntelFPGADecorationsForStructMember(
11601183
SPIRVEntry *E, SPIRVWord MemberNumber,
11611184
std::vector<std::pair<Decoration, std::string>> &Decorations) {
11621185
for (const auto &I : Decorations) {
1163-
if (I.first == DecorationMemoryINTEL)
1186+
switch (I.first) {
1187+
case DecorationMemoryINTEL:
11641188
E->addMemberDecorate(
11651189
new SPIRVMemberDecorateMemoryINTELAttr(E, MemberNumber, I.second));
1166-
else {
1190+
break;
1191+
case DecorationRegisterINTEL:
1192+
case DecorationSinglepumpINTEL:
1193+
case DecorationDoublepumpINTEL:
1194+
assert(I.second.empty());
1195+
E->addMemberDecorate(MemberNumber, I.first);
1196+
break;
1197+
// The rest of IntelFPGA decorations:
1198+
// DecorationNumbanksINTEL
1199+
// DecorationBankwidthINTEL
1200+
// DecorationMaxconcurrencyINTEL
1201+
default:
11671202
SPIRVWord Result = 0;
11681203
StringRef(I.second).getAsInteger(10, Result);
11691204
E->addMemberDecorate(MemberNumber, I.first, Result);
1205+
break;
11701206
}
11711207
}
11721208
}
@@ -1177,6 +1213,14 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
11771213
std::vector<SPIRVWord> MemoryAccess(1, MemoryAccessMaskNone);
11781214
if (SPIRVWord AlignVal = MI->getDestAlignment()) {
11791215
MemoryAccess[0] |= MemoryAccessAlignedMask;
1216+
if (auto MTI = dyn_cast<MemTransferInst>(MI)) {
1217+
SPIRVWord SourceAlignVal = MTI->getSourceAlignment();
1218+
assert(SourceAlignVal && "Missed Source alignment!");
1219+
1220+
// In a case when alignment of source differs from dest one
1221+
// least value is guaranteed anyway.
1222+
AlignVal = std::min(AlignVal, SourceAlignVal);
1223+
}
11801224
MemoryAccess.push_back(AlignVal);
11811225
}
11821226
if (MI->isVolatile())
@@ -1233,9 +1277,6 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
12331277
GetMemoryAccess(MSI), BB);
12341278
} break;
12351279
case Intrinsic::memcpy:
1236-
assert(cast<MemCpyInst>(II)->getSourceAlignment() ==
1237-
cast<MemCpyInst>(II)->getDestAlignment() &&
1238-
"Alignment mismatch!");
12391280
return BM->addCopyMemorySizedInst(
12401281
transValue(II->getOperand(0), BB), transValue(II->getOperand(1), BB),
12411282
transValue(II->getOperand(2), BB),
@@ -1417,6 +1458,59 @@ bool LLVMToSPIRV::transGlobalVariables() {
14171458
return true;
14181459
}
14191460

1461+
bool LLVMToSPIRV::isAnyFunctionReachableFromFunction(
1462+
const Function *FS,
1463+
const std::unordered_set<const Function *> Funcs) const {
1464+
std::unordered_set<const Function *> Done;
1465+
std::unordered_set<const Function *> ToDo;
1466+
ToDo.insert(FS);
1467+
1468+
while (!ToDo.empty()) {
1469+
auto It = ToDo.begin();
1470+
const Function *F = *It;
1471+
1472+
if (Funcs.find(F) != Funcs.end())
1473+
return true;
1474+
1475+
ToDo.erase(It);
1476+
Done.insert(F);
1477+
1478+
const CallGraphNode *FN = (*CG)[F];
1479+
for (unsigned I = 0; I < FN->size(); ++I) {
1480+
const CallGraphNode *NN = (*FN)[I];
1481+
const Function *NNF = NN->getFunction();
1482+
if (!NNF)
1483+
continue;
1484+
if (Done.find(NNF) == Done.end()) {
1485+
ToDo.insert(NNF);
1486+
}
1487+
}
1488+
}
1489+
1490+
return false;
1491+
}
1492+
1493+
void LLVMToSPIRV::collectInputOutputVariables(SPIRVFunction *SF, Function *F) {
1494+
for (auto &GV : M->globals()) {
1495+
const auto AS = GV.getAddressSpace();
1496+
if (AS != SPIRAS_Input && AS != SPIRAS_Output)
1497+
continue;
1498+
1499+
std::unordered_set<const Function *> Funcs;
1500+
1501+
for (const auto &U : GV.uses()) {
1502+
const Instruction *Inst = dyn_cast<Instruction>(U.getUser());
1503+
if (!Inst)
1504+
continue;
1505+
Funcs.insert(Inst->getFunction());
1506+
}
1507+
1508+
if (isAnyFunctionReachableFromFunction(F, Funcs)) {
1509+
SF->addVariable(ValueMap[&GV]);
1510+
}
1511+
}
1512+
}
1513+
14201514
void LLVMToSPIRV::mutateFuncArgType(
14211515
const std::map<unsigned, Type *> &ChangedType, Function *F) {
14221516
for (auto &I : ChangedType) {
@@ -1458,6 +1552,9 @@ void LLVMToSPIRV::transFunction(Function *I) {
14581552
BF->addExecutionMode(BF->getModule()->add(
14591553
new SPIRVExecutionMode(BF, spv::ExecutionModeContractionOff)));
14601554
}
1555+
if (BF->getModule()->isEntryPoint(spv::ExecutionModelKernel, BF->getId())) {
1556+
collectInputOutputVariables(BF, I);
1557+
}
14611558
}
14621559

14631560
bool LLVMToSPIRV::translate() {

llvm-spirv/lib/SPIRV/SPIRVWriter.h

+7
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include "SPIRVUtil.h"
5858
#include "SPIRVValue.h"
5959

60+
#include "llvm/Analysis/CallGraph.h"
6061
#include "llvm/IR/IntrinsicInst.h"
6162

6263
#include <memory>
@@ -128,6 +129,7 @@ class LLVMToSPIRV : public ModulePass {
128129
SPIRVWord SrcLang;
129130
SPIRVWord SrcLangVer;
130131
std::unique_ptr<LLVMToSPIRVDbgTran> DbgTran;
132+
std::unique_ptr<CallGraph> CG;
131133

132134
SPIRVType *mapType(Type *T, SPIRVType *BT);
133135
SPIRVValue *mapValue(Value *V, SPIRVValue *BV);
@@ -178,6 +180,11 @@ class LLVMToSPIRV : public ModulePass {
178180
SPIRVId addInt32(int);
179181
void transFunction(Function *I);
180182
SPIRV::SPIRVLinkageTypeKind transLinkageType(const GlobalValue *GV);
183+
184+
bool isAnyFunctionReachableFromFunction(
185+
const Function *FS,
186+
const std::unordered_set<const Function *> Funcs) const;
187+
void collectInputOutputVariables(SPIRVFunction *SF, Function *F);
181188
};
182189

183190
} // namespace SPIRV

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVDecorate.h

+10
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,16 @@ class SPIRVDecorate : public SPIRVDecorateGeneric {
136136
// Incomplete constructor
137137
SPIRVDecorate() : SPIRVDecorateGeneric(OC) {}
138138

139+
SPIRVExtSet getRequiredExtensions() const override {
140+
switch (Dec) {
141+
case DecorationNoSignedWrap:
142+
case DecorationNoUnsignedWrap:
143+
return getSet(SPV_KHR_no_integer_wrap_decoration);
144+
default:
145+
return SPIRVExtSet();
146+
}
147+
}
148+
139149
_SPIRV_DCL_ENCDEC
140150
void setWordCount(SPIRVWord) override;
141151
void validate() const override {

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.cpp

+6-5
Original file line numberDiff line numberDiff line change
@@ -438,17 +438,18 @@ std::istream &operator>>(std::istream &I, SPIRVEntry &E) {
438438

439439
SPIRVEntryPoint::SPIRVEntryPoint(SPIRVModule *TheModule,
440440
SPIRVExecutionModelKind TheExecModel,
441-
SPIRVId TheId, const std::string &TheName)
441+
SPIRVId TheId, const std::string &TheName,
442+
std::vector<SPIRVId> Variables)
442443
: SPIRVAnnotation(TheModule->get<SPIRVFunction>(TheId),
443-
getSizeInWords(TheName) + 3),
444-
ExecModel(TheExecModel), Name(TheName) {}
444+
getSizeInWords(TheName) + Variables.size() + 3),
445+
ExecModel(TheExecModel), Name(TheName), Variables(Variables) {}
445446

446447
void SPIRVEntryPoint::encode(spv_ostream &O) const {
447-
getEncoder(O) << ExecModel << Target << Name;
448+
getEncoder(O) << ExecModel << Target << Name << Variables;
448449
}
449450

450451
void SPIRVEntryPoint::decode(std::istream &I) {
451-
getDecoder(I) >> ExecModel >> Target >> Name;
452+
getDecoder(I) >> ExecModel >> Target >> Name >> Variables;
452453
Module->setName(getOrCreateTarget(), Name);
453454
Module->addEntryPoint(ExecModel, Target);
454455
}

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ class SPIRVEntry {
288288
Op getOpCode() const { return OpCode; }
289289
SPIRVModule *getModule() const { return Module; }
290290
virtual SPIRVCapVec getRequiredCapability() const { return SPIRVCapVec(); }
291+
virtual SPIRVExtSet getRequiredExtensions() const { return SPIRVExtSet(); }
291292
const std::string &getName() const { return Name; }
292293
bool hasDecorate(Decoration Kind, size_t Index = 0,
293294
SPIRVWord *Result = 0) const;
@@ -478,12 +479,16 @@ template <Op OC> class SPIRVAnnotation : public SPIRVAnnotationGeneric {
478479
class SPIRVEntryPoint : public SPIRVAnnotation<OpEntryPoint> {
479480
public:
480481
SPIRVEntryPoint(SPIRVModule *TheModule, SPIRVExecutionModelKind,
481-
SPIRVId TheId, const std::string &TheName);
482+
SPIRVId TheId, const std::string &TheName,
483+
std::vector<SPIRVId> Variables);
482484
SPIRVEntryPoint() : ExecModel(ExecutionModelKernel) {}
483485
_SPIRV_DCL_ENCDEC
484486
protected:
485487
SPIRVExecutionModelKind ExecModel;
486488
std::string Name;
489+
490+
private:
491+
std::vector<SPIRVId> Variables;
487492
};
488493

489494
class SPIRVName : public SPIRVAnnotation<OpName> {

0 commit comments

Comments
 (0)