From a61241037477331ec004ebea1664eb92a75711f3 Mon Sep 17 00:00:00 2001 From: Artem Gindinson Date: Wed, 8 May 2019 10:03:29 +0300 Subject: [PATCH] Sync with SPIRV-LLVM-Translator 55f2041f2c Synced with: 55f2041f2c Open SPIR-V output file as a binary file As in sync 11e66953d1, this excludes following syncs with LLVM: 2cdb947d4 Update LLVM to r358377 72bcddd08 Sync with LLVM 6183f7c486 Sync with LLVM Signed-off-by: Artem Gindinson --- llvm-spirv/include/LLVMSPIRVLib.h | 6 +- llvm-spirv/lib/SPIRV/OCL20ToSPIRV.cpp | 17 +-- llvm-spirv/lib/SPIRV/SPIRVInternal.h | 1 + llvm-spirv/lib/SPIRV/SPIRVReader.cpp | 9 ++ llvm-spirv/lib/SPIRV/SPIRVToOCL20.cpp | 2 +- llvm-spirv/lib/SPIRV/SPIRVUtil.cpp | 2 +- llvm-spirv/lib/SPIRV/SPIRVWriter.cpp | 129 +++++++++++++++--- llvm-spirv/lib/SPIRV/SPIRVWriter.h | 7 + llvm-spirv/lib/SPIRV/libSPIRV/SPIRVDecorate.h | 10 ++ llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.cpp | 11 +- llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h | 7 +- llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEnum.h | 17 +++ llvm-spirv/lib/SPIRV/libSPIRV/SPIRVFunction.h | 10 ++ .../lib/SPIRV/libSPIRV/SPIRVInstruction.h | 4 + .../lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h | 2 + llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.cpp | 22 ++- llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h | 3 + .../lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h | 2 + llvm-spirv/lib/SPIRV/libSPIRV/SPIRVType.h | 8 ++ llvm-spirv/lib/SPIRV/libSPIRV/SPIRVUtil.h | 6 + llvm-spirv/lib/SPIRV/libSPIRV/SPIRVValue.h | 7 + llvm-spirv/lib/SPIRV/libSPIRV/spirv.hpp | 2 + llvm-spirv/test/IntelFPGAMemoryAttributes.ll | 38 ++++-- .../IntelFPGAMemoryAttributesForStruct.ll | 36 ++++- llvm-spirv/test/NoSignedUnsignedWrap.ll | 2 + .../transcoding/subgroup_avc_intel_generic.ll | 1 + .../transcoding/subgroup_avc_intel_types.ll | 1 + .../subgroup_avc_intel_vme_image.ll | 2 + .../subgroup_avc_intel_wrappers.ll | 2 + llvm-spirv/tools/llvm-spirv/llvm-spirv.cpp | 14 +- 30 files changed, 321 insertions(+), 59 deletions(-) diff --git a/llvm-spirv/include/LLVMSPIRVLib.h b/llvm-spirv/include/LLVMSPIRVLib.h index aacf8eec389cd..02ca142153ced 100644 --- a/llvm-spirv/include/LLVMSPIRVLib.h +++ b/llvm-spirv/include/LLVMSPIRVLib.h @@ -79,7 +79,7 @@ bool isSpirvBinary(std::string &Img); bool convertSpirv(std::istream &IS, std::ostream &OS, std::string &ErrMsg, bool FromText, bool ToText); -/// \brief Convert SPIR-V between binary and internel text formats. +/// \brief Convert SPIR-V between binary and internal text formats. /// This function is not thread safe and should not be used in multi-thread /// applications unless guarded by a critical section. bool convertSpirv(std::string &Input, std::string &Out, std::string &ErrMsg, @@ -93,11 +93,11 @@ bool isSpirvText(std::string &Img); namespace llvm { -/// \brief Translate LLVM module to SPIRV and write to ostream. +/// \brief Translate LLVM module to SPIR-V and write to ostream. /// \returns true if succeeds. bool writeSpirv(Module *M, std::ostream &OS, std::string &ErrMsg); -/// \brief Load SPIRV from istream and translate to LLVM module. +/// \brief Load SPIR-V from istream and translate to LLVM module. /// \returns true if succeeds. bool readSpirv(LLVMContext &C, std::istream &IS, Module *&M, std::string &ErrMsg); diff --git a/llvm-spirv/lib/SPIRV/OCL20ToSPIRV.cpp b/llvm-spirv/lib/SPIRV/OCL20ToSPIRV.cpp index 96d4119eabdca..f58ed6bcf578b 100644 --- a/llvm-spirv/lib/SPIRV/OCL20ToSPIRV.cpp +++ b/llvm-spirv/lib/SPIRV/OCL20ToSPIRV.cpp @@ -1111,7 +1111,7 @@ void OCL20ToSPIRV::visitCallReadImageWithSampler( assert(0 && "read_image* with unhandled number of args!"); } - // SPIR-V intruction always returns 4-element vector + // SPIR-V instruction always returns 4-element vector if (IsRetScalar) Ret = VectorType::get(Ret, 4); return getSPIRVFuncName(OpImageSampleExplicitLod, @@ -1687,13 +1687,14 @@ void OCL20ToSPIRV::visitSubgroupImageMediaBlockINTEL( spv::Op OpCode = DemangledName.rfind("read") != std::string::npos ? spv::OpSubgroupImageMediaBlockReadINTEL : spv::OpSubgroupImageMediaBlockWriteINTEL; - mutateCallInstSPIRV(M, CI, - [=](CallInst *, std::vector &Args) { - // Moving the last argument to the begining. - std::rotate(Args.begin(), Args.end() - 1, Args.end()); - return getSPIRVFuncName(OpCode, CI->getType()); - }, - &Attrs); + mutateCallInstSPIRV( + M, CI, + [=](CallInst *, std::vector &Args) { + // Moving the last argument to the beginning. + std::rotate(Args.begin(), Args.end() - 1, Args.end()); + return getSPIRVFuncName(OpCode, CI->getType()); + }, + &Attrs); } static const char *getSubgroupAVCIntelOpKind(const std::string &Name) { diff --git a/llvm-spirv/lib/SPIRV/SPIRVInternal.h b/llvm-spirv/lib/SPIRV/SPIRVInternal.h index 61a5761a9a3f9..394ad4d8423ab 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVInternal.h +++ b/llvm-spirv/lib/SPIRV/SPIRVInternal.h @@ -184,6 +184,7 @@ enum SPIRAddressSpace { SPIRAS_Local, SPIRAS_Generic, SPIRAS_Input, + SPIRAS_Output, SPIRAS_Count, }; diff --git a/llvm-spirv/lib/SPIRV/SPIRVReader.cpp b/llvm-spirv/lib/SPIRV/SPIRVReader.cpp index df09e8c51f971..935cf67ce1f5d 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVReader.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVReader.cpp @@ -2202,6 +2202,10 @@ void generateIntelFPGAAnnotation(const SPIRVEntry *E, Out << "{numbanks:" << Result << '}'; if (E->hasDecorate(DecorationMaxconcurrencyINTEL, 0, &Result)) Out << "{max_concurrency:" << Result << '}'; + if (E->hasDecorate(DecorationSinglepumpINTEL)) + Out << "{pump:1}"; + if (E->hasDecorate(DecorationDoublepumpINTEL)) + Out << "{pump:2}"; } void generateIntelFPGAAnnotationForStructMember( @@ -2224,6 +2228,10 @@ void generateIntelFPGAAnnotationForStructMember( if (E->hasMemberDecorate(DecorationMaxconcurrencyINTEL, 0, MemberNumber, &Result)) Out << "{max_concurrency:" << Result << '}'; + if (E->hasMemberDecorate(DecorationSinglepumpINTEL, 0, MemberNumber)) + Out << "{pump:1}"; + if (E->hasMemberDecorate(DecorationDoublepumpINTEL, 0, MemberNumber)) + Out << "{pump:2}"; } void SPIRVToLLVM::transIntelFPGADecorations(SPIRVValue *BV, Value *V) { @@ -2904,6 +2912,7 @@ bool llvm::readSpirv(LLVMContext &C, std::istream &IS, Module *&M, IS >> *BM; if (!BM->isModuleValid()) { + BM->getError(ErrMsg); M = nullptr; return false; } diff --git a/llvm-spirv/lib/SPIRV/SPIRVToOCL20.cpp b/llvm-spirv/lib/SPIRV/SPIRVToOCL20.cpp index ccce0b075b8f9..298850ced49ed 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVToOCL20.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVToOCL20.cpp @@ -77,7 +77,7 @@ class SPIRVToOCL20 : public ModulePass, public InstVisitor { // appropriate calls to conversion built-ins defined by the standards. void visitCastInst(CastInst &CI); - /// Transform __spirv_ImageQuerySize[Lod] into vector of the same lenght + /// Transform __spirv_ImageQuerySize[Lod] into vector of the same length /// containing {[get_image_width | get_image_dim], get_image_array_size} /// for all images except image1d_t which is always converted into /// get_image_width returning scalar result. diff --git a/llvm-spirv/lib/SPIRV/SPIRVUtil.cpp b/llvm-spirv/lib/SPIRV/SPIRVUtil.cpp index 97279cb6efbcc..1d8aa1cbb0659 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVUtil.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVUtil.cpp @@ -1210,7 +1210,7 @@ Type *getSPIRVTypeByChangeBaseTypeName(Module *M, Type *T, StringRef OldName, if (isSPIRVType(T, OldName, &Postfixes)) return getOrCreateOpaquePtrType(M, getSPIRVTypeName(NewName, Postfixes)); LLVM_DEBUG(dbgs() << " Invalid SPIR-V type " << *T << '\n'); - llvm_unreachable("Invalid SPIRV-V type"); + llvm_unreachable("Invalid SPIR-V type"); return nullptr; } diff --git a/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp b/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp index 38f74763497ad..04762dd75a7e6 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp @@ -128,6 +128,7 @@ LLVMToSPIRV::LLVMToSPIRV(SPIRVModule *SMod) bool LLVMToSPIRV::runOnModule(Module &Mod) { M = &Mod; + CG = make_unique(Mod); Ctx = &M->getContext(); DbgTran->setModule(M); assert(BM && "SPIR-V module not initialized"); @@ -1127,16 +1128,25 @@ parseAnnotations(StringRef AnnotatedCode) { StringRef AnnotatedDecoration = AnnotatedCode.substr(From + 1, To - 1); std::pair D = AnnotatedDecoration.split(':'); - StringRef F = D.first; - Decoration Dec = - llvm::StringSwitch(F) - .Case("memory", DecorationMemoryINTEL) - .Case("register", DecorationRegisterINTEL) - .Case("numbanks", DecorationNumbanksINTEL) - .Case("bankwidth", DecorationBankwidthINTEL) - .Case("max_concurrency", DecorationMaxconcurrencyINTEL); + StringRef F = D.first, S = D.second; + StringRef Value; + Decoration Dec; + if (F == "pump") { + Dec = llvm::StringSwitch(S) + .Case("1", DecorationSinglepumpINTEL) + .Case("2", DecorationDoublepumpINTEL); + } else if (F == "register") { + Dec = DecorationRegisterINTEL; + } else { + Dec = llvm::StringSwitch(F) + .Case("memory", DecorationMemoryINTEL) + .Case("numbanks", DecorationNumbanksINTEL) + .Case("bankwidth", DecorationBankwidthINTEL) + .Case("max_concurrency", DecorationMaxconcurrencyINTEL); + Value = S; + } - Decorates.push_back({Dec, D.second}); + Decorates.push_back({Dec, Value}); AnnotatedCode = AnnotatedCode.drop_front(To + 1); } return Decorates; @@ -1146,12 +1156,25 @@ void addIntelFPGADecorations( SPIRVEntry *E, std::vector> &Decorations) { for (const auto &I : Decorations) { - if (I.first == DecorationMemoryINTEL) + switch (I.first) { + case DecorationMemoryINTEL: E->addDecorate(new SPIRVDecorateMemoryINTELAttr(E, I.second)); - else { + break; + case DecorationRegisterINTEL: + case DecorationSinglepumpINTEL: + case DecorationDoublepumpINTEL: + assert(I.second.empty()); + E->addDecorate(I.first); + break; + // The rest of IntelFPGA decorations: + // DecorationNumbanksINTEL + // DecorationBankwidthINTEL + // DecorationMaxconcurrencyINTEL + default: SPIRVWord Result = 0; StringRef(I.second).getAsInteger(10, Result); E->addDecorate(I.first, Result); + break; } } } @@ -1160,13 +1183,26 @@ void addIntelFPGADecorationsForStructMember( SPIRVEntry *E, SPIRVWord MemberNumber, std::vector> &Decorations) { for (const auto &I : Decorations) { - if (I.first == DecorationMemoryINTEL) + switch (I.first) { + case DecorationMemoryINTEL: E->addMemberDecorate( new SPIRVMemberDecorateMemoryINTELAttr(E, MemberNumber, I.second)); - else { + break; + case DecorationRegisterINTEL: + case DecorationSinglepumpINTEL: + case DecorationDoublepumpINTEL: + assert(I.second.empty()); + E->addMemberDecorate(MemberNumber, I.first); + break; + // The rest of IntelFPGA decorations: + // DecorationNumbanksINTEL + // DecorationBankwidthINTEL + // DecorationMaxconcurrencyINTEL + default: SPIRVWord Result = 0; StringRef(I.second).getAsInteger(10, Result); E->addMemberDecorate(MemberNumber, I.first, Result); + break; } } } @@ -1177,6 +1213,14 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II, std::vector MemoryAccess(1, MemoryAccessMaskNone); if (SPIRVWord AlignVal = MI->getDestAlignment()) { MemoryAccess[0] |= MemoryAccessAlignedMask; + if (auto MTI = dyn_cast(MI)) { + SPIRVWord SourceAlignVal = MTI->getSourceAlignment(); + assert(SourceAlignVal && "Missed Source alignment!"); + + // In a case when alignment of source differs from dest one + // least value is guaranteed anyway. + AlignVal = std::min(AlignVal, SourceAlignVal); + } MemoryAccess.push_back(AlignVal); } if (MI->isVolatile()) @@ -1233,9 +1277,6 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II, GetMemoryAccess(MSI), BB); } break; case Intrinsic::memcpy: - assert(cast(II)->getSourceAlignment() == - cast(II)->getDestAlignment() && - "Alignment mismatch!"); return BM->addCopyMemorySizedInst( transValue(II->getOperand(0), BB), transValue(II->getOperand(1), BB), transValue(II->getOperand(2), BB), @@ -1417,6 +1458,59 @@ bool LLVMToSPIRV::transGlobalVariables() { return true; } +bool LLVMToSPIRV::isAnyFunctionReachableFromFunction( + const Function *FS, + const std::unordered_set Funcs) const { + std::unordered_set Done; + std::unordered_set ToDo; + ToDo.insert(FS); + + while (!ToDo.empty()) { + auto It = ToDo.begin(); + const Function *F = *It; + + if (Funcs.find(F) != Funcs.end()) + return true; + + ToDo.erase(It); + Done.insert(F); + + const CallGraphNode *FN = (*CG)[F]; + for (unsigned I = 0; I < FN->size(); ++I) { + const CallGraphNode *NN = (*FN)[I]; + const Function *NNF = NN->getFunction(); + if (!NNF) + continue; + if (Done.find(NNF) == Done.end()) { + ToDo.insert(NNF); + } + } + } + + return false; +} + +void LLVMToSPIRV::collectInputOutputVariables(SPIRVFunction *SF, Function *F) { + for (auto &GV : M->globals()) { + const auto AS = GV.getAddressSpace(); + if (AS != SPIRAS_Input && AS != SPIRAS_Output) + continue; + + std::unordered_set Funcs; + + for (const auto &U : GV.uses()) { + const Instruction *Inst = dyn_cast(U.getUser()); + if (!Inst) + continue; + Funcs.insert(Inst->getFunction()); + } + + if (isAnyFunctionReachableFromFunction(F, Funcs)) { + SF->addVariable(ValueMap[&GV]); + } + } +} + void LLVMToSPIRV::mutateFuncArgType( const std::map &ChangedType, Function *F) { for (auto &I : ChangedType) { @@ -1458,6 +1552,9 @@ void LLVMToSPIRV::transFunction(Function *I) { BF->addExecutionMode(BF->getModule()->add( new SPIRVExecutionMode(BF, spv::ExecutionModeContractionOff))); } + if (BF->getModule()->isEntryPoint(spv::ExecutionModelKernel, BF->getId())) { + collectInputOutputVariables(BF, I); + } } bool LLVMToSPIRV::translate() { diff --git a/llvm-spirv/lib/SPIRV/SPIRVWriter.h b/llvm-spirv/lib/SPIRV/SPIRVWriter.h index a58af9b9ffc26..cdc41058ea393 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVWriter.h +++ b/llvm-spirv/lib/SPIRV/SPIRVWriter.h @@ -57,6 +57,7 @@ #include "SPIRVUtil.h" #include "SPIRVValue.h" +#include "llvm/Analysis/CallGraph.h" #include "llvm/IR/IntrinsicInst.h" #include @@ -128,6 +129,7 @@ class LLVMToSPIRV : public ModulePass { SPIRVWord SrcLang; SPIRVWord SrcLangVer; std::unique_ptr DbgTran; + std::unique_ptr CG; SPIRVType *mapType(Type *T, SPIRVType *BT); SPIRVValue *mapValue(Value *V, SPIRVValue *BV); @@ -178,6 +180,11 @@ class LLVMToSPIRV : public ModulePass { SPIRVId addInt32(int); void transFunction(Function *I); SPIRV::SPIRVLinkageTypeKind transLinkageType(const GlobalValue *GV); + + bool isAnyFunctionReachableFromFunction( + const Function *FS, + const std::unordered_set Funcs) const; + void collectInputOutputVariables(SPIRVFunction *SF, Function *F); }; } // namespace SPIRV diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVDecorate.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVDecorate.h index cfbd83cae8414..0e4ce55d0e40e 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVDecorate.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVDecorate.h @@ -136,6 +136,16 @@ class SPIRVDecorate : public SPIRVDecorateGeneric { // Incomplete constructor SPIRVDecorate() : SPIRVDecorateGeneric(OC) {} + SPIRVExtSet getRequiredExtensions() const override { + switch (Dec) { + case DecorationNoSignedWrap: + case DecorationNoUnsignedWrap: + return getSet(SPV_KHR_no_integer_wrap_decoration); + default: + return SPIRVExtSet(); + } + } + _SPIRV_DCL_ENCDEC void setWordCount(SPIRVWord) override; void validate() const override { diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.cpp b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.cpp index 1fa174412101f..89295a9d83dbf 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.cpp +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.cpp @@ -438,17 +438,18 @@ std::istream &operator>>(std::istream &I, SPIRVEntry &E) { SPIRVEntryPoint::SPIRVEntryPoint(SPIRVModule *TheModule, SPIRVExecutionModelKind TheExecModel, - SPIRVId TheId, const std::string &TheName) + SPIRVId TheId, const std::string &TheName, + std::vector Variables) : SPIRVAnnotation(TheModule->get(TheId), - getSizeInWords(TheName) + 3), - ExecModel(TheExecModel), Name(TheName) {} + getSizeInWords(TheName) + Variables.size() + 3), + ExecModel(TheExecModel), Name(TheName), Variables(Variables) {} void SPIRVEntryPoint::encode(spv_ostream &O) const { - getEncoder(O) << ExecModel << Target << Name; + getEncoder(O) << ExecModel << Target << Name << Variables; } void SPIRVEntryPoint::decode(std::istream &I) { - getDecoder(I) >> ExecModel >> Target >> Name; + getDecoder(I) >> ExecModel >> Target >> Name >> Variables; Module->setName(getOrCreateTarget(), Name); Module->addEntryPoint(ExecModel, Target); } diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h index 8073561dff8d0..edf8e6e8e4173 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h @@ -288,6 +288,7 @@ class SPIRVEntry { Op getOpCode() const { return OpCode; } SPIRVModule *getModule() const { return Module; } virtual SPIRVCapVec getRequiredCapability() const { return SPIRVCapVec(); } + virtual SPIRVExtSet getRequiredExtensions() const { return SPIRVExtSet(); } const std::string &getName() const { return Name; } bool hasDecorate(Decoration Kind, size_t Index = 0, SPIRVWord *Result = 0) const; @@ -478,12 +479,16 @@ template class SPIRVAnnotation : public SPIRVAnnotationGeneric { class SPIRVEntryPoint : public SPIRVAnnotation { public: SPIRVEntryPoint(SPIRVModule *TheModule, SPIRVExecutionModelKind, - SPIRVId TheId, const std::string &TheName); + SPIRVId TheId, const std::string &TheName, + std::vector Variables); SPIRVEntryPoint() : ExecModel(ExecutionModelKernel) {} _SPIRV_DCL_ENCDEC protected: SPIRVExecutionModelKind ExecModel; std::string Name; + +private: + std::vector Variables; }; class SPIRVName : public SPIRVAnnotation { diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEnum.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEnum.h index 8a62cb16eb492..17110d9dcc609 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEnum.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEnum.h @@ -113,6 +113,19 @@ typedef spv::GroupOperation SPIRVGroupOperationKind; typedef spv::Dim SPIRVImageDimKind; typedef std::vector SPIRVCapVec; +enum SPIRVExtensionKind { + SPV_INTEL_device_side_avc_motion_estimation, + SPV_KHR_no_integer_wrap_decoration +}; + +typedef std::set SPIRVExtSet; + +template <> inline void SPIRVMap::init() { + add(SPV_INTEL_device_side_avc_motion_estimation, + "SPV_INTEL_device_side_avc_motion_estimation"); + add(SPV_KHR_no_integer_wrap_decoration, "SPV_KHR_no_integer_wrap_decoration"); +}; + template <> inline void SPIRVMap::init() { add(SPIRVEIS_OpenCL, "OpenCL.std"); add(SPIRVEIS_Debug, "SPIRV.debug"); @@ -344,6 +357,10 @@ template <> inline void SPIRVMap::init() { ADD_VEC_INIT(DecorationBankwidthINTEL, {CapabilityFPGAMemoryAttributesINTEL}); ADD_VEC_INIT(DecorationMaxconcurrencyINTEL, {CapabilityFPGAMemoryAttributesINTEL}); + ADD_VEC_INIT(DecorationSinglepumpINTEL, + {CapabilityFPGAMemoryAttributesINTEL}); + ADD_VEC_INIT(DecorationDoublepumpINTEL, + {CapabilityFPGAMemoryAttributesINTEL}); } template <> inline void SPIRVMap::init() { diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVFunction.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVFunction.h index aebe969b42e83..dd1f7ee155a19 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVFunction.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVFunction.h @@ -105,6 +105,15 @@ class SPIRVFunction : public SPIRVValue, public SPIRVComponentExecutionModes { return getFunctionType()->getNumParameters(); } SPIRVId getArgumentId(size_t I) const { return Parameters[I]->getId(); } + const std::vector getVariables() const { + std::vector Ids; + for (auto Variable : Variables) + Ids.push_back(Variable->getId()); + return Ids; + } + void addVariable(const SPIRVValue *Variable) { + Variables.push_back(Variable); + } SPIRVFunctionParameter *getArgument(size_t I) const { return Parameters[I]; } void foreachArgument(std::function Func) { for (size_t I = 0, E = getNumArguments(); I != E; ++I) @@ -170,6 +179,7 @@ class SPIRVFunction : public SPIRVValue, public SPIRVComponentExecutionModes { SPIRVWord FCtrlMask; // Function control mask std::vector Parameters; + std::vector Variables; typedef std::vector SPIRVLBasicBlockVector; SPIRVLBasicBlockVector BBVec; diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h index 04d33cab72c36..696a087366889 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h @@ -2246,6 +2246,10 @@ class SPIRVSubgroupAVCIntelInstBase : public SPIRVInstTemplateBase { SPIRVCapVec getRequiredCapability() const override { return getVec(CapabilitySubgroupAvcMotionEstimationINTEL); } + + SPIRVExtSet getRequiredExtensions() const override { + return getSet(SPV_INTEL_device_side_avc_motion_estimation); + } }; // Intel Subgroup AVC Motion Estimation Instructions diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h index 77d58d42ca66a..b60f9085f4492 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h @@ -402,6 +402,8 @@ inline bool isValid(spv::Decoration V) { case DecorationNumbanksINTEL: case DecorationBankwidthINTEL: case DecorationMaxconcurrencyINTEL: + case DecorationSinglepumpINTEL: + case DecorationDoublepumpINTEL: return true; default: return false; diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.cpp b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.cpp index 2ce79ed7efcae..1dd2862337ca4 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.cpp +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.cpp @@ -181,6 +181,7 @@ class SPIRVModuleImpl : public SPIRVModule { void setCurrentLine(const std::shared_ptr &Line) override; void addCapability(SPIRVCapabilityKind) override; void addCapabilityInternal(SPIRVCapabilityKind) override; + void addExtension(SPIRVExtensionKind) override; const SPIRVDecorateGeneric *addDecorate(SPIRVDecorateGeneric *) override; SPIRVDecorationGroup *addDecorationGroup() override; SPIRVDecorationGroup * @@ -523,6 +524,12 @@ SPIRVValue *SPIRVModuleImpl::addPipeStorageConstant(SPIRVType *TheType, this, TheType, getId(), PacketSize, PacketAlign, Capacity)); } +void SPIRVModuleImpl::addExtension(SPIRVExtensionKind Ext) { + std::string ExtName; + SPIRVMap::find(Ext, &ExtName); + SPIRVExt.insert(ExtName); +} + void SPIRVModuleImpl::addCapability(SPIRVCapabilityKind Cap) { addCapabilities(SPIRV::getCapability(Cap)); SPIRVDBG(spvdbgs() << "addCapability: " << Cap << '\n'); @@ -624,6 +631,14 @@ SPIRVEntry *SPIRVModuleImpl::addEntry(SPIRVEntry *Entry) { Entry->getRequiredCapability().end(), [this](SPIRVCapabilityKind &val) { return !CapMap.count(val); })); } + if (AutoAddExtensions) { + // While we are reading existing SPIR-V we need to read it as-is and don't + // add required extensions for each entry automatically + for (auto &E : Entry->getRequiredExtensions()) { + addExtension(E); + } + } + return Entry; } @@ -1420,8 +1435,8 @@ spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M) { for (auto &I : MI.EntryPointVec) for (auto &II : I.second) - O << SPIRVEntryPoint(&M, I.first, II, - M.get(II)->getName()); + O << SPIRVEntryPoint(&M, I.first, II, M.get(II)->getName(), + M.get(II)->getVariables()); for (auto &I : MI.EntryPointVec) for (auto &II : I.second) @@ -1526,6 +1541,7 @@ std::istream &operator>>(std::istream &I, SPIRVModule &M) { SPIRVModuleImpl &MI = *static_cast(&M); // Disable automatic capability filling. MI.setAutoAddCapability(false); + MI.setAutoAddExtensions(false); SPIRVWord Magic; Decoder >> Magic; @@ -1538,7 +1554,7 @@ std::istream &operator>>(std::istream &I, SPIRVModule &M) { Decoder >> MI.SPIRVVersion; if (!M.getErrorLog().checkError(MI.SPIRVVersion <= SPV_VERSION, SPIRVEC_InvalidModule, - "unsupported SPIRV version number")) { + "unsupported SPIR-V version number")) { M.setInvalid(); return I; } diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h index ee62575f1dc51..c61dd1e777382 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h @@ -155,6 +155,7 @@ class SPIRVModule { virtual void optimizeDecorates() = 0; virtual void setAutoAddCapability(bool E) { AutoAddCapability = E; } virtual void setValidateCapability(bool E) { ValidateCapability = E; } + virtual void setAutoAddExtensions(bool E) { AutoAddExtensions = E; } virtual void setGeneratorId(unsigned short) = 0; virtual void setGeneratorVer(unsigned short) = 0; virtual void resolveUnknownStructFields() = 0; @@ -280,6 +281,7 @@ class SPIRVModule { for (auto I : Caps) addCapability(I); } + virtual void addExtension(SPIRVExtensionKind) = 0; /// Used by SPIRV entries to add required capability internally. /// Should not be used by users directly. virtual void addCapabilityInternal(SPIRVCapabilityKind) = 0; @@ -382,6 +384,7 @@ class SPIRVModule { protected: bool AutoAddCapability; bool ValidateCapability; + bool AutoAddExtensions = true; private: bool IsValid; diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h index 57ced25a974c8..ca80c10c6853e 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h @@ -336,6 +336,8 @@ template <> inline void SPIRVMap::init() { add(DecorationNumbanksINTEL, "NumbanksINTEL"); add(DecorationBankwidthINTEL, "BankwidthINTEL"); add(DecorationMaxconcurrencyINTEL, "MaxconcurrencyINTEL"); + add(DecorationSinglepumpINTEL, "SinglepumpINTEL"); + add(DecorationDoublepumpINTEL, "DoublepumpINTEL"); } SPIRV_DEF_NAMEMAP(Decoration, SPIRVDecorationNameMap) diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVType.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVType.h index f63b92c0155dc..e198210b908cd 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVType.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVType.h @@ -779,6 +779,10 @@ class SPIRVTypeVmeImageINTEL : public SPIRVType { return getVec(CapabilitySubgroupAvcMotionEstimationINTEL); } + SPIRVExtSet getRequiredExtensions() const override { + return getSet(SPV_INTEL_device_side_avc_motion_estimation); + } + protected: SPIRVTypeImage *ImgTy; _SPIRV_DEF_ENCDEC2(Id, ImgTy) @@ -830,6 +834,10 @@ class SPIRVTypeSubgroupAvcINTEL : public SPIRVType { return getVec(CapabilitySubgroupAvcMotionEstimationINTEL); } + SPIRVExtSet getRequiredExtensions() const override { + return getSet(SPV_INTEL_device_side_avc_motion_estimation); + } + SPIRVValue *getOperand() { return getValue(Opn); } protected: diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVUtil.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVUtil.h index 84485482e7bfb..794b76cf2f314 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVUtil.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVUtil.h @@ -362,6 +362,12 @@ inline std::vector getVec(const std::string &Str) { return V; } +template inline std::set getSet(T Op1) { + std::set S; + S.insert(Op1); + return S; +} + template inline std::vector getVec(T Op1) { std::vector V; V.push_back(Op1); diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVValue.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVValue.h index 3a7f75d04453f..7b1ee3e17880e 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVValue.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVValue.h @@ -120,6 +120,13 @@ class SPIRVValue : public SPIRVEntry { return Type->getRequiredCapability(); } + SPIRVExtSet getRequiredExtensions() const override { + SPIRVExtSet EV; + if (!hasType()) + return EV; + return Type->getRequiredExtensions(); + } + protected: void setHasNoType() { Attrib |= SPIRVEA_NOTYPE; } void setHasType() { Attrib &= ~SPIRVEA_NOTYPE; } diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/spirv.hpp b/llvm-spirv/lib/SPIRV/libSPIRV/spirv.hpp index 39fa3a2bc3976..5321b16975df6 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/spirv.hpp +++ b/llvm-spirv/lib/SPIRV/libSPIRV/spirv.hpp @@ -393,6 +393,8 @@ enum Decoration { DecorationNumbanksINTEL = 5827, DecorationBankwidthINTEL = 5828, DecorationMaxconcurrencyINTEL = 5829, + DecorationSinglepumpINTEL = 5830, + DecorationDoublepumpINTEL = 5831, DecorationMax = 0x7fffffff, }; diff --git a/llvm-spirv/test/IntelFPGAMemoryAttributes.ll b/llvm-spirv/test/IntelFPGAMemoryAttributes.ll index d0c9a4d853801..2471502a9bc39 100644 --- a/llvm-spirv/test/IntelFPGAMemoryAttributes.ll +++ b/llvm-spirv/test/IntelFPGAMemoryAttributes.ll @@ -6,11 +6,13 @@ ; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM ; CHECK-SPIRV: Decorate {{[0-9]+}} MemoryINTEL "DEFAULT" -; CHECK-SPIRV: Decorate {{[0-9]+}} RegisterINTEL 1 +; CHECK-SPIRV: Decorate {{[0-9]+}} RegisterINTEL ; CHECK-SPIRV: Decorate {{[0-9]+}} MemoryINTEL "BLOCK_RAM" ; CHECK-SPIRV: Decorate {{[0-9]+}} NumbanksINTEL 4 ; CHECK-SPIRV: Decorate {{[0-9]+}} BankwidthINTEL 8 ; CHECK-SPIRV: Decorate {{[0-9]+}} MaxconcurrencyINTEL 4 +; CHECK-SPIRV: Decorate {{[0-9]+}} SinglepumpINTEL +; CHECK-SPIRV: Decorate {{[0-9]+}} DoublepumpINTEL target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir64-unknown-linux" @@ -22,12 +24,16 @@ target triple = "spir64-unknown-linux" ; CHECK-LLVM: [[STR3:@[a-zA-Z0-9_.]+]] = {{.*}}{memory:BLOCK_RAM} ; CHECK-LLVM: [[STR4:@[a-zA-Z0-9_.]+]] = {{.*}}{memory:DEFAULT}{bankwidth:8} ; CHECK-LLVM: [[STR5:@[a-zA-Z0-9_.]+]] = {{.*}}{memory:DEFAULT}{max_concurrency:4} +; CHECK-LLVM: [[STR6:@[a-zA-Z0-9_.]+]] = {{.*}}{memory:DEFAULT}{pump:1} +; CHECK-LLVM: [[STR7:@[a-zA-Z0-9_.]+]] = {{.*}}{memory:DEFAULT}{pump:2} @.str = private unnamed_addr constant [29 x i8] c"{memory:DEFAULT}{numbanks:4}\00", section "llvm.metadata" @.str.1 = private unnamed_addr constant [13 x i8] c"test_var.cpp\00", section "llvm.metadata" @.str.2 = private unnamed_addr constant [13 x i8] c"{register:1}\00", section "llvm.metadata" @.str.3 = private unnamed_addr constant [19 x i8] c"{memory:BLOCK_RAM}\00", section "llvm.metadata" @.str.4 = private unnamed_addr constant [30 x i8] c"{memory:DEFAULT}{bankwidth:8}\00", section "llvm.metadata" @.str.5 = private unnamed_addr constant [36 x i8] c"{memory:DEFAULT}{max_concurrency:4}\00", section "llvm.metadata" +@.str.6 = private unnamed_addr constant [25 x i8] c"{memory:DEFAULT}{pump:1}\00", section "llvm.metadata" +@.str.7 = private unnamed_addr constant [25 x i8] c"{memory:DEFAULT}{pump:2}\00", section "llvm.metadata" ; Function Attrs: nounwind define spir_kernel void @_ZTSZ4mainE15kernel_function() #0 !kernel_arg_addr_space !4 !kernel_arg_access_qual !4 !kernel_arg_type !4 !kernel_arg_base_type !4 !kernel_arg_type_qual !4 { @@ -65,6 +71,8 @@ entry: %var_three = alloca i32, align 4 %var_four = alloca i32, align 4 %var_five = alloca i8, align 1 + %var_six = alloca i32, align 4 + %var_seven = alloca i32, align 4 %0 = bitcast i32* %var_one to i8* call void @llvm.lifetime.start.p0i8(i64 4, i8* %0) #4 %var_one1 = bitcast i32* %var_one to i8* @@ -88,15 +96,29 @@ entry: call void @llvm.lifetime.start.p0i8(i64 1, i8* %var_five) #4 ; CHECK-LLVM: call void @llvm.var.annotation(i8* [[VAR5:%[a-zA-Z0-9_]+]], i8* getelementptr inbounds ([36 x i8], [36 x i8]* [[STR5]], i32 0, i32 0), i8* undef, i32 undef) call void @llvm.var.annotation(i8* %var_five, i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str.5, i32 0, i32 0), i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.1, i32 0, i32 0), i32 6) - call void @llvm.lifetime.end.p0i8(i64 1, i8* %var_five) #4 - %4 = bitcast i32* %var_four to i8* - call void @llvm.lifetime.end.p0i8(i64 4, i8* %4) #4 - %5 = bitcast i32* %var_three to i8* - call void @llvm.lifetime.end.p0i8(i64 4, i8* %5) #4 - %6 = bitcast i32* %var_two to i8* + %4 = bitcast i32* %var_six to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* %4) #4 + %var_six6 = bitcast i32* %var_six to i8* + ; CHECK-LLVM: call void @llvm.var.annotation(i8* [[VAR6:%[a-zA-Z0-9_]+]], i8* getelementptr inbounds ([25 x i8], [25 x i8]* [[STR6]], i32 0, i32 0), i8* undef, i32 undef) + call void @llvm.var.annotation(i8* %var_six6, i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.6, i32 0, i32 0), i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.1, i32 0, i32 0), i32 7) + %5 = bitcast i32* %var_seven to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* %5) #4 + %var_seven7 = bitcast i32* %var_seven to i8* + ; CHECK-LLVM: call void @llvm.var.annotation(i8* [[VAR7:%[a-zA-Z0-9_]+]], i8* getelementptr inbounds ([25 x i8], [25 x i8]* [[STR7]], i32 0, i32 0), i8* undef, i32 undef) + call void @llvm.var.annotation(i8* %var_seven7, i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.7, i32 0, i32 0), i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.1, i32 0, i32 0), i32 8) + call void @llvm.lifetime.end.p0i8(i64 4, i8* %var_five) #4 + %6 = bitcast i32* %var_seven to i8* call void @llvm.lifetime.end.p0i8(i64 4, i8* %6) #4 - %7 = bitcast i32* %var_one to i8* + %7 = bitcast i32* %var_six to i8* call void @llvm.lifetime.end.p0i8(i64 4, i8* %7) #4 + %8 = bitcast i32* %var_four to i8* + call void @llvm.lifetime.end.p0i8(i64 4, i8* %8) #4 + %9 = bitcast i32* %var_three to i8* + call void @llvm.lifetime.end.p0i8(i64 4, i8* %9) #4 + %10 = bitcast i32* %var_two to i8* + call void @llvm.lifetime.end.p0i8(i64 4, i8* %10) #4 + %11 = bitcast i32* %var_one to i8* + call void @llvm.lifetime.end.p0i8(i64 4, i8* %11) #4 ret void } diff --git a/llvm-spirv/test/IntelFPGAMemoryAttributesForStruct.ll b/llvm-spirv/test/IntelFPGAMemoryAttributesForStruct.ll index 263bd1f3b7967..b58edff9baa41 100644 --- a/llvm-spirv/test/IntelFPGAMemoryAttributesForStruct.ll +++ b/llvm-spirv/test/IntelFPGAMemoryAttributesForStruct.ll @@ -5,31 +5,37 @@ ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM -; CHECK-SPIRV: MemberDecorate {{[0-9]+}} 1 RegisterINTEL 1 +; CHECK-SPIRV: MemberDecorate {{[0-9]+}} 1 RegisterINTEL ; CHECK-SPIRV: MemberDecorate {{[0-9]+}} 0 MemoryINTEL "DEFAULT" ; CHECK-SPIRV: MemberDecorate {{[0-9]+}} 3 MemoryINTEL "DEFAULT" ; CHECK-SPIRV: MemberDecorate {{[0-9]+}} 2 MemoryINTEL "MLAB" ; CHECK-SPIRV: MemberDecorate {{[0-9]+}} 0 NumbanksINTEL 4 ; CHECK-SPIRV: MemberDecorate {{[0-9]+}} 3 BankwidthINTEL 8 ; CHECK-SPIRV: MemberDecorate {{[0-9]+}} 4 MaxconcurrencyINTEL 4 +; CHECK-SPIRV: MemberDecorate {{[0-9]+}} 5 SinglepumpINTEL +; CHECK-SPIRV: MemberDecorate {{[0-9]+}} 6 DoublepumpINTEL target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir64-unknown-linux" %class.anon = type { i8 } -%struct.foo = type { i32, i32, i32, i32, i8 } +%struct.foo = type { i32, i32, i32, i32, i8, i32, i32 } ; CHECK-LLVM: [[STR1:@[a-zA-Z0-9_.]+]] = {{.*}}{memory:DEFAULT}{numbanks:4} ; CHECK-LLVM: [[STR2:@[a-zA-Z0-9_.]+]] = {{.*}}{register:1} ; CHECK-LLVM: [[STR3:@[a-zA-Z0-9_.]+]] = {{.*}}{memory:MLAB} ; CHECK-LLVM: [[STR4:@[a-zA-Z0-9_.]+]] = {{.*}}{memory:DEFAULT}{bankwidth:8} ; CHECK-LLVM: [[STR5:@[a-zA-Z0-9_.]+]] = {{.*}}{memory:DEFAULT}{max_concurrency:4} +; CHECK-LLVM: [[STR6:@[a-zA-Z0-9_.]+]] = {{.*}}{memory:DEFAULT}{pump:1} +; CHECK-LLVM: [[STR7:@[a-zA-Z0-9_.]+]] = {{.*}}{memory:DEFAULT}{pump:2} @.str = private unnamed_addr constant [29 x i8] c"{memory:DEFAULT}{numbanks:4}\00", section "llvm.metadata" @.str.1 = private unnamed_addr constant [16 x i8] c"test_struct.cpp\00", section "llvm.metadata" @.str.2 = private unnamed_addr constant [13 x i8] c"{register:1}\00", section "llvm.metadata" @.str.3 = private unnamed_addr constant [14 x i8] c"{memory:MLAB}\00", section "llvm.metadata" @.str.4 = private unnamed_addr constant [30 x i8] c"{memory:DEFAULT}{bankwidth:8}\00", section "llvm.metadata" @.str.5 = private unnamed_addr constant [36 x i8] c"{memory:DEFAULT}{max_concurrency:4}\00", section "llvm.metadata" +@.str.6 = private unnamed_addr constant [25 x i8] c"{memory:DEFAULT}{pump:1}\00", section "llvm.metadata" +@.str.7 = private unnamed_addr constant [25 x i8] c"{memory:DEFAULT}{pump:2}\00", section "llvm.metadata" ; Function Attrs: nounwind define spir_kernel void @_ZTSZ4mainE15kernel_function() #0 !kernel_arg_addr_space !4 !kernel_arg_access_qual !4 !kernel_arg_type !4 !kernel_arg_base_type !4 !kernel_arg_type_qual !4 { @@ -102,8 +108,24 @@ entry: %f5 = getelementptr inbounds %struct.foo, %struct.foo* %s1, i32 0, i32 4 %13 = call i8* @llvm.ptr.annotation.p0i8(i8* %f5, i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str.5, i32 0, i32 0), i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.1, i32 0, i32 0), i32 6) store i8 0, i8* %13, align 4, !tbaa !15 - %14 = bitcast %struct.foo* %s1 to i8* - call void @llvm.lifetime.end.p0i8(i64 20, i8* %14) #4 + ; CHECK-LLVM: %[[FIELD6:.*]] = getelementptr inbounds %struct.foo, %struct.foo* %{{[a-zA-Z0-9]+}}, i32 0, i32 5 + ; CHECK-LLVM: %[[CAST6:.*]] = bitcast{{.*}}%[[FIELD6]] + ; CHECK-LLVM: call i8* @llvm.ptr.annotation.p0i8{{.*}}%[[CAST6]]{{.*}}[[STR6]] + %f6 = getelementptr inbounds %struct.foo, %struct.foo* %s1, i32 0, i32 5 + %14 = bitcast i32* %f6 to i8* + %15 = call i8* @llvm.ptr.annotation.p0i8(i8* %14, i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.6, i32 0, i32 0), i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.1, i32 0, i32 0), i32 7) + %16 = bitcast i8* %15 to i32* + store i32 0, i32* %16, align 4, !tbaa !16 + ; CHECK-LLVM: %[[FIELD7:.*]] = getelementptr inbounds %struct.foo, %struct.foo* %{{[a-zA-Z0-9]+}}, i32 0, i32 6 + ; CHECK-LLVM: %[[CAST7:.*]] = bitcast{{.*}}%[[FIELD7]] + ; CHECK-LLVM: call i8* @llvm.ptr.annotation.p0i8{{.*}}%[[CAST7]]{{.*}}[[STR7]] + %f7 = getelementptr inbounds %struct.foo, %struct.foo* %s1, i32 0, i32 6 + %17 = bitcast i32* %f7 to i8* + %18 = call i8* @llvm.ptr.annotation.p0i8(i8* %17, i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.7, i32 0, i32 0), i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.1, i32 0, i32 0), i32 8) + %19 = bitcast i8* %18 to i32* + store i32 0, i32* %19, align 4, !tbaa !17 + %20 = bitcast %struct.foo* %s1 to i8* + call void @llvm.lifetime.end.p0i8(i64 28, i8* %20) #4 ret void } @@ -131,9 +153,11 @@ attributes #4 = { nounwind } !7 = !{!"omnipotent char", !8, i64 0} !8 = !{!"Simple C++ TBAA"} !9 = !{!10, !11, i64 0} -!10 = !{!"_ZTS3foo", !11, i64 0, !11, i64 4, !11, i64 8, !11, i64 12, !11, i64 16} +!10 = !{!"_ZTS3foo", !11, i64 0, !11, i64 4, !11, i64 8, !11, i64 12, !11, i64 16, !11, i64 20, !11, i64 24} !11 = !{!"int", !7, i64 0} !12 = !{!10, !11, i64 4} !13 = !{!10, !11, i64 8} !14 = !{!10, !11, i64 12} -!15 = !{!10, !11, i64 16} \ No newline at end of file +!15 = !{!10, !11, i64 16} +!16 = !{!10, !11, i64 20} +!17 = !{!10, !11, i64 24} diff --git a/llvm-spirv/test/NoSignedUnsignedWrap.ll b/llvm-spirv/test/NoSignedUnsignedWrap.ll index 049a39eb04ee2..10e29b28b1e66 100644 --- a/llvm-spirv/test/NoSignedUnsignedWrap.ll +++ b/llvm-spirv/test/NoSignedUnsignedWrap.ll @@ -12,6 +12,8 @@ ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM +; CHECK-SPIRV: Extension "SPV_KHR_no_integer_wrap_decoration" + ; CHECK-SPIRV: Decorate {{[0-9]+}} NoSignedWrap ; CHECK-SPIRV: Decorate {{[0-9]+}} NoUnsignedWrap diff --git a/llvm-spirv/test/transcoding/subgroup_avc_intel_generic.ll b/llvm-spirv/test/transcoding/subgroup_avc_intel_generic.ll index 24c4f8dd77c43..e11747f18a715 100644 --- a/llvm-spirv/test/transcoding/subgroup_avc_intel_generic.ll +++ b/llvm-spirv/test/transcoding/subgroup_avc_intel_generic.ll @@ -52,6 +52,7 @@ ; CHECK: Capability SubgroupAvcMotionEstimationINTEL ; CHECK: Capability SubgroupAvcMotionEstimationIntraINTEL ; CHECK: Capability SubgroupAvcMotionEstimationChromaINTEL +; CHECK: Extension "SPV_INTEL_device_side_avc_motion_estimation" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir64" diff --git a/llvm-spirv/test/transcoding/subgroup_avc_intel_types.ll b/llvm-spirv/test/transcoding/subgroup_avc_intel_types.ll index 2df3b05bd228a..7ee83ac14017c 100644 --- a/llvm-spirv/test/transcoding/subgroup_avc_intel_types.ll +++ b/llvm-spirv/test/transcoding/subgroup_avc_intel_types.ll @@ -24,6 +24,7 @@ ; CHECK: Capability Groups ; CHECK: Capability SubgroupAvcMotionEstimationINTEL +; CHECK: Extension "SPV_INTEL_device_side_avc_motion_estimation" ; CHECK: TypeAvcMcePayloadINTEL ; CHECK: TypeAvcImePayloadINTEL [[IME_PAYLOAD:[0-9]]] diff --git a/llvm-spirv/test/transcoding/subgroup_avc_intel_vme_image.ll b/llvm-spirv/test/transcoding/subgroup_avc_intel_vme_image.ll index c207c5df62e37..4da31b482c3a8 100644 --- a/llvm-spirv/test/transcoding/subgroup_avc_intel_vme_image.ll +++ b/llvm-spirv/test/transcoding/subgroup_avc_intel_vme_image.ll @@ -52,6 +52,8 @@ target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir64" +; CHECK: Extension "SPV_INTEL_device_side_avc_motion_estimation" + ; CHECK: TypeImage [[ImageTy:[0-9]+]] ; CHECK: TypeSampler [[SamplerTy:[0-9]+]] ; CHECK: TypeAvcImePayloadINTEL [[ImePayloadTy:[0-9]+]] diff --git a/llvm-spirv/test/transcoding/subgroup_avc_intel_wrappers.ll b/llvm-spirv/test/transcoding/subgroup_avc_intel_wrappers.ll index d767a157964b6..b6c1e58b36405 100644 --- a/llvm-spirv/test/transcoding/subgroup_avc_intel_wrappers.ll +++ b/llvm-spirv/test/transcoding/subgroup_avc_intel_wrappers.ll @@ -38,6 +38,8 @@ target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir64" +; CHECK: Extension "SPV_INTEL_device_side_avc_motion_estimation" + ; CHECK: TypeAvcImePayloadINTEL [[ImePayloadTy:[0-9]+]] ; CHECK: TypeAvcImeResultINTEL [[ImeResultTy:[0-9]+]] ; CHECK: TypeAvcRefPayloadINTEL [[RefPayloadTy:[0-9]+]] diff --git a/llvm-spirv/tools/llvm-spirv/llvm-spirv.cpp b/llvm-spirv/tools/llvm-spirv/llvm-spirv.cpp index 537dc0e0d49ad..6bb03537bd3b9 100644 --- a/llvm-spirv/tools/llvm-spirv/llvm-spirv.cpp +++ b/llvm-spirv/tools/llvm-spirv/llvm-spirv.cpp @@ -33,11 +33,11 @@ /// \file /// /// Common Usage: -/// llvm-spirv - Read LLVM bitcode from stdin, write SPIRV to stdout +/// llvm-spirv - Read LLVM bitcode from stdin, write SPIR-V to stdout /// llvm-spirv x.bc - Read LLVM bitcode from the x.bc file, write SPIR-V /// to x.bil file -/// llvm-spirv -r - Read SPIRV from stdin, write LLVM bitcode to stdout -/// llvm-spirv -r x.bil - Read SPIRV from the x.bil file, write SPIR-V to +/// llvm-spirv -r - Read SPIR-V from stdin, write LLVM bitcode to stdout +/// llvm-spirv -r x.bil - Read SPIR-V from the x.bil file, write SPIR-V to /// the x.bc file /// /// Options: @@ -139,14 +139,14 @@ static int convertLLVMToSPIRV() { std::string Err; bool Success = false; if (OutputFile != "-") { - std::ofstream OutFile(OutputFile); + std::ofstream OutFile(OutputFile, std::ios::binary); Success = writeSpirv(M.get(), OutFile, Err); } else { Success = writeSpirv(M.get(), std::cout, Err); } if (!Success) { - errs() << "Fails to save LLVM as SPIRV: " << Err << '\n'; + errs() << "Fails to save LLVM as SPIR-V: " << Err << '\n'; return -1; } return 0; @@ -159,7 +159,7 @@ static int convertSPIRVToLLVM() { std::string Err; if (!readSpirv(Context, IFS, M, Err)) { - errs() << "Fails to load SPIRV as LLVM Module: " << Err << '\n'; + errs() << "Fails to load SPIR-V as LLVM Module: " << Err << '\n'; return -1; } @@ -243,7 +243,7 @@ static int regularizeLLVM() { std::string Err; if (!regularizeLlvmForSpirv(M.get(), Err)) { - errs() << "Fails to save LLVM as SPIRV: " << Err << '\n'; + errs() << "Fails to save LLVM as SPIR-V: " << Err << '\n'; return -1; }