From 4c718fdbeacfc3385a493349b66b61c857b8e772 Mon Sep 17 00:00:00 2001 From: Yusra Syeda <99052248+ysyeda@users.noreply.github.com> Date: Mon, 8 Apr 2024 11:05:42 -0400 Subject: [PATCH 1/6] [SystemZ][z/OS] TXT records in the GOFF reader (#87648) This PR adds handling for TXT records in the GOFF reader. --------- Co-authored-by: Yusra Syeda --- llvm/include/llvm/Object/GOFF.h | 20 +++ llvm/include/llvm/Object/GOFFObjectFile.h | 56 +++++-- llvm/lib/Object/GOFFObjectFile.cpp | 167 +++++++++++++++++++ llvm/unittests/Object/GOFFObjectFileTest.cpp | 97 +++++++++++ 4 files changed, 326 insertions(+), 14 deletions(-) diff --git a/llvm/include/llvm/Object/GOFF.h b/llvm/include/llvm/Object/GOFF.h index 91762457ae056..9fb8876e893d5 100644 --- a/llvm/include/llvm/Object/GOFF.h +++ b/llvm/include/llvm/Object/GOFF.h @@ -73,6 +73,26 @@ class Record { } }; +class TXTRecord : public Record { +public: + /// \brief Maximum length of data; any more must go in continuation. + static const uint8_t TXTMaxDataLength = 56; + + static Error getData(const uint8_t *Record, SmallString<256> &CompleteData); + + static void getElementEsdId(const uint8_t *Record, uint32_t &EsdId) { + get(Record, 4, EsdId); + } + + static void getOffset(const uint8_t *Record, uint32_t &Offset) { + get(Record, 12, Offset); + } + + static void getDataLength(const uint8_t *Record, uint16_t &Length) { + get(Record, 22, Length); + } +}; + class HDRRecord : public Record { public: static Error getData(const uint8_t *Record, SmallString<256> &CompleteData); diff --git a/llvm/include/llvm/Object/GOFFObjectFile.h b/llvm/include/llvm/Object/GOFFObjectFile.h index 7e1ceb95f6672..6871641e97ec8 100644 --- a/llvm/include/llvm/Object/GOFFObjectFile.h +++ b/llvm/include/llvm/Object/GOFFObjectFile.h @@ -29,7 +29,10 @@ namespace llvm { namespace object { class GOFFObjectFile : public ObjectFile { + friend class GOFFSymbolRef; + IndexedMap EsdPtrs; // Indexed by EsdId. + SmallVector TextPtrs; mutable DenseMap>> EsdNamesCache; @@ -38,7 +41,7 @@ class GOFFObjectFile : public ObjectFile { // (EDID, 0) code, r/o data section // (EDID,PRID) r/w data section SmallVector SectionList; - mutable DenseMap SectionDataCache; + mutable DenseMap> SectionDataCache; public: Expected getSymbolName(SymbolRef Symbol) const; @@ -66,6 +69,10 @@ class GOFFObjectFile : public ObjectFile { return true; } + bool isSectionNoLoad(DataRefImpl Sec) const; + bool isSectionReadOnlyData(DataRefImpl Sec) const; + bool isSectionZeroInit(DataRefImpl Sec) const; + private: // SymbolRef. Expected getSymbolName(DataRefImpl Symb) const override; @@ -75,27 +82,24 @@ class GOFFObjectFile : public ObjectFile { Expected getSymbolFlags(DataRefImpl Symb) const override; Expected getSymbolType(DataRefImpl Symb) const override; Expected getSymbolSection(DataRefImpl Symb) const override; + uint64_t getSymbolSize(DataRefImpl Symb) const; const uint8_t *getSymbolEsdRecord(DataRefImpl Symb) const; bool isSymbolUnresolved(DataRefImpl Symb) const; bool isSymbolIndirect(DataRefImpl Symb) const; // SectionRef. - void moveSectionNext(DataRefImpl &Sec) const override {} - virtual Expected getSectionName(DataRefImpl Sec) const override { - return StringRef(); - } - uint64_t getSectionAddress(DataRefImpl Sec) const override { return 0; } - uint64_t getSectionSize(DataRefImpl Sec) const override { return 0; } + void moveSectionNext(DataRefImpl &Sec) const override; + virtual Expected getSectionName(DataRefImpl Sec) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; virtual Expected> - getSectionContents(DataRefImpl Sec) const override { - return ArrayRef(); - } - uint64_t getSectionIndex(DataRefImpl Sec) const override { return 0; } - uint64_t getSectionAlignment(DataRefImpl Sec) const override { return 0; } + getSectionContents(DataRefImpl Sec) const override; + uint64_t getSectionIndex(DataRefImpl Sec) const override { return Sec.d.a; } + uint64_t getSectionAlignment(DataRefImpl Sec) const override; bool isSectionCompressed(DataRefImpl Sec) const override { return false; } - bool isSectionText(DataRefImpl Sec) const override { return false; } - bool isSectionData(DataRefImpl Sec) const override { return false; } + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override { return false; } bool isSectionVirtual(DataRefImpl Sec) const override { return false; } relocation_iterator section_rel_begin(DataRefImpl Sec) const override { @@ -109,6 +113,7 @@ class GOFFObjectFile : public ObjectFile { const uint8_t *getSectionPrEsdRecord(DataRefImpl &Sec) const; const uint8_t *getSectionEdEsdRecord(uint32_t SectionIndex) const; const uint8_t *getSectionPrEsdRecord(uint32_t SectionIndex) const; + uint32_t getSectionDefEsdId(DataRefImpl &Sec) const; // RelocationRef. void moveRelocationNext(DataRefImpl &Rel) const override {} @@ -122,6 +127,29 @@ class GOFFObjectFile : public ObjectFile { SmallVectorImpl &Result) const override {} }; +class GOFFSymbolRef : public SymbolRef { +public: + GOFFSymbolRef(const SymbolRef &B) : SymbolRef(B) { + assert(isa(SymbolRef::getObject())); + } + + const GOFFObjectFile *getObject() const { + return cast(BasicSymbolRef::getObject()); + } + + Expected getSymbolGOFFFlags() const { + return getObject()->getSymbolFlags(getRawDataRefImpl()); + } + + Expected getSymbolGOFFType() const { + return getObject()->getSymbolType(getRawDataRefImpl()); + } + + uint64_t getSize() const { + return getObject()->getSymbolSize(getRawDataRefImpl()); + } +}; + } // namespace object } // namespace llvm diff --git a/llvm/lib/Object/GOFFObjectFile.cpp b/llvm/lib/Object/GOFFObjectFile.cpp index d3dfd5d1540cf..550aebfe0670d 100644 --- a/llvm/lib/Object/GOFFObjectFile.cpp +++ b/llvm/lib/Object/GOFFObjectFile.cpp @@ -165,6 +165,11 @@ GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err) LLVM_DEBUG(dbgs() << " -- ESD " << EsdId << "\n"); break; } + case GOFF::RT_TXT: + // Save TXT records. + TextPtrs.emplace_back(I); + LLVM_DEBUG(dbgs() << " -- TXT\n"); + break; case GOFF::RT_END: LLVM_DEBUG(dbgs() << " -- END (GOFF record type) unhandled\n"); break; @@ -361,6 +366,13 @@ GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { std::to_string(SymEdId)); } +uint64_t GOFFObjectFile::getSymbolSize(DataRefImpl Symb) const { + const uint8_t *Record = getSymbolEsdRecord(Symb); + uint32_t Length; + ESDRecord::getLength(Record, Length); + return Length; +} + const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(DataRefImpl &Sec) const { SectionEntryImpl EsdIds = SectionList[Sec.d.a]; const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a]; @@ -391,6 +403,154 @@ GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex) const { return EsdRecord; } +uint32_t GOFFObjectFile::getSectionDefEsdId(DataRefImpl &Sec) const { + const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); + uint32_t Length; + ESDRecord::getLength(EsdRecord, Length); + if (Length == 0) { + const uint8_t *PrEsdRecord = getSectionPrEsdRecord(Sec); + if (PrEsdRecord) + EsdRecord = PrEsdRecord; + } + + uint32_t DefEsdId; + ESDRecord::getEsdId(EsdRecord, DefEsdId); + LLVM_DEBUG(dbgs() << "Got def EsdId: " << DefEsdId << '\n'); + return DefEsdId; +} + +void GOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const { + Sec.d.a++; + if ((Sec.d.a) >= SectionList.size()) + Sec.d.a = 0; +} + +Expected GOFFObjectFile::getSectionName(DataRefImpl Sec) const { + DataRefImpl EdSym; + SectionEntryImpl EsdIds = SectionList[Sec.d.a]; + EdSym.d.a = EsdIds.d.a; + Expected Name = getSymbolName(EdSym); + if (Name) { + StringRef Res = *Name; + LLVM_DEBUG(dbgs() << "Got section: " << Res << '\n'); + LLVM_DEBUG(dbgs() << "Final section name: " << Res << '\n'); + Name = Res; + } + return Name; +} + +uint64_t GOFFObjectFile::getSectionAddress(DataRefImpl Sec) const { + uint32_t Offset; + const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); + ESDRecord::getOffset(EsdRecord, Offset); + return Offset; +} + +uint64_t GOFFObjectFile::getSectionSize(DataRefImpl Sec) const { + uint32_t Length; + uint32_t DefEsdId = getSectionDefEsdId(Sec); + const uint8_t *EsdRecord = EsdPtrs[DefEsdId]; + ESDRecord::getLength(EsdRecord, Length); + LLVM_DEBUG(dbgs() << "Got section size: " << Length << '\n'); + return static_cast(Length); +} + +// Unravel TXT records and expand fill characters to produce +// a contiguous sequence of bytes. +Expected> +GOFFObjectFile::getSectionContents(DataRefImpl Sec) const { + if (SectionDataCache.count(Sec.d.a)) { + auto &Buf = SectionDataCache[Sec.d.a]; + return ArrayRef(Buf); + } + uint64_t SectionSize = getSectionSize(Sec); + uint32_t DefEsdId = getSectionDefEsdId(Sec); + + const uint8_t *EdEsdRecord = getSectionEdEsdRecord(Sec); + bool FillBytePresent; + ESDRecord::getFillBytePresent(EdEsdRecord, FillBytePresent); + uint8_t FillByte = '\0'; + if (FillBytePresent) + ESDRecord::getFillByteValue(EdEsdRecord, FillByte); + + // Initialize section with fill byte. + SmallVector Data(SectionSize, FillByte); + + // Replace section with content from text records. + for (const uint8_t *TxtRecordInt : TextPtrs) { + const uint8_t *TxtRecordPtr = TxtRecordInt; + uint32_t TxtEsdId; + TXTRecord::getElementEsdId(TxtRecordPtr, TxtEsdId); + LLVM_DEBUG(dbgs() << "Got txt EsdId: " << TxtEsdId << '\n'); + + if (TxtEsdId != DefEsdId) + continue; + + uint32_t TxtDataOffset; + TXTRecord::getOffset(TxtRecordPtr, TxtDataOffset); + + uint16_t TxtDataSize; + TXTRecord::getDataLength(TxtRecordPtr, TxtDataSize); + + LLVM_DEBUG(dbgs() << "Record offset " << TxtDataOffset << ", data size " + << TxtDataSize << "\n"); + + SmallString<256> CompleteData; + CompleteData.reserve(TxtDataSize); + if (Error Err = TXTRecord::getData(TxtRecordPtr, CompleteData)) + return std::move(Err); + assert(CompleteData.size() == TxtDataSize && "Wrong length of data"); + std::copy(CompleteData.data(), CompleteData.data() + TxtDataSize, + Data.begin() + TxtDataOffset); + } + SectionDataCache[Sec.d.a] = Data; + return ArrayRef(SectionDataCache[Sec.d.a]); +} + +uint64_t GOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { + const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); + GOFF::ESDAlignment Pow2Alignment; + ESDRecord::getAlignment(EsdRecord, Pow2Alignment); + return 1 << static_cast(Pow2Alignment); +} + +bool GOFFObjectFile::isSectionText(DataRefImpl Sec) const { + const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); + GOFF::ESDExecutable Executable; + ESDRecord::getExecutable(EsdRecord, Executable); + return Executable == GOFF::ESD_EXE_CODE; +} + +bool GOFFObjectFile::isSectionData(DataRefImpl Sec) const { + const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); + GOFF::ESDExecutable Executable; + ESDRecord::getExecutable(EsdRecord, Executable); + return Executable == GOFF::ESD_EXE_DATA; +} + +bool GOFFObjectFile::isSectionNoLoad(DataRefImpl Sec) const { + const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); + GOFF::ESDLoadingBehavior LoadingBehavior; + ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior); + return LoadingBehavior == GOFF::ESD_LB_NoLoad; +} + +bool GOFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const { + if (!isSectionData(Sec)) + return false; + + const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); + GOFF::ESDLoadingBehavior LoadingBehavior; + ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior); + return LoadingBehavior == GOFF::ESD_LB_Initial; +} + +bool GOFFObjectFile::isSectionZeroInit(DataRefImpl Sec) const { + // GOFF uses fill characters and fill characters are applied + // on getSectionContents() - so we say false to zero init. + return false; +} + section_iterator GOFFObjectFile::section_begin() const { DataRefImpl Sec; moveSectionNext(Sec); @@ -473,6 +633,13 @@ Error ESDRecord::getData(const uint8_t *Record, return getContinuousData(Record, DataSize, 72, CompleteData); } +Error TXTRecord::getData(const uint8_t *Record, + SmallString<256> &CompleteData) { + uint16_t Length; + getDataLength(Record, Length); + return getContinuousData(Record, Length, 24, CompleteData); +} + Error ENDRecord::getData(const uint8_t *Record, SmallString<256> &CompleteData) { uint16_t Length = getNameLength(Record); diff --git a/llvm/unittests/Object/GOFFObjectFileTest.cpp b/llvm/unittests/Object/GOFFObjectFileTest.cpp index 734dac6b8507a..69f60d016a808 100644 --- a/llvm/unittests/Object/GOFFObjectFileTest.cpp +++ b/llvm/unittests/Object/GOFFObjectFileTest.cpp @@ -502,3 +502,100 @@ TEST(GOFFObjectFileTest, InvalidERSymbolType) { FailedWithMessage("ESD record 1 has unknown Executable type 0x03")); } } + +TEST(GOFFObjectFileTest, TXTConstruct) { + char GOFFData[GOFF::RecordLength * 6] = {}; + + // HDR record. + GOFFData[0] = 0x03; + GOFFData[1] = 0xF0; + GOFFData[50] = 0x01; + + // ESD record. + GOFFData[GOFF::RecordLength] = 0x03; + GOFFData[GOFF::RecordLength + 7] = 0x01; // ESDID. + GOFFData[GOFF::RecordLength + 71] = 0x05; // Size of symbol name. + GOFFData[GOFF::RecordLength + 72] = 0xa5; // Symbol name is v. + GOFFData[GOFF::RecordLength + 73] = 0x81; // Symbol name is a. + GOFFData[GOFF::RecordLength + 74] = 0x99; // Symbol name is r. + GOFFData[GOFF::RecordLength + 75] = 0x7b; // Symbol name is #. + GOFFData[GOFF::RecordLength + 76] = 0x83; // Symbol name is c. + + // ESD record. + GOFFData[GOFF::RecordLength * 2] = 0x03; + GOFFData[GOFF::RecordLength * 2 + 3] = 0x01; + GOFFData[GOFF::RecordLength * 2 + 7] = 0x02; // ESDID. + GOFFData[GOFF::RecordLength * 2 + 11] = 0x01; // Parent ESDID. + GOFFData[GOFF::RecordLength * 2 + 27] = 0x08; // Length. + GOFFData[GOFF::RecordLength * 2 + 40] = 0x01; // Name Space ID. + GOFFData[GOFF::RecordLength * 2 + 41] = 0x80; + GOFFData[GOFF::RecordLength * 2 + 60] = 0x04; // Size of symbol name. + GOFFData[GOFF::RecordLength * 2 + 61] = 0x04; // Size of symbol name. + GOFFData[GOFF::RecordLength * 2 + 63] = 0x0a; // Size of symbol name. + GOFFData[GOFF::RecordLength * 2 + 66] = 0x03; // Size of symbol name. + GOFFData[GOFF::RecordLength * 2 + 71] = 0x08; // Size of symbol name. + GOFFData[GOFF::RecordLength * 2 + 72] = 0xc3; // Symbol name is c. + GOFFData[GOFF::RecordLength * 2 + 73] = 0x6d; // Symbol name is _. + GOFFData[GOFF::RecordLength * 2 + 74] = 0xc3; // Symbol name is c. + GOFFData[GOFF::RecordLength * 2 + 75] = 0xd6; // Symbol name is o. + GOFFData[GOFF::RecordLength * 2 + 76] = 0xc4; // Symbol name is D. + GOFFData[GOFF::RecordLength * 2 + 77] = 0xc5; // Symbol name is E. + GOFFData[GOFF::RecordLength * 2 + 78] = 0xf6; // Symbol name is 6. + GOFFData[GOFF::RecordLength * 2 + 79] = 0xf4; // Symbol name is 4. + + // ESD record. + GOFFData[GOFF::RecordLength * 3] = 0x03; + GOFFData[GOFF::RecordLength * 3 + 3] = 0x02; + GOFFData[GOFF::RecordLength * 3 + 7] = 0x03; // ESDID. + GOFFData[GOFF::RecordLength * 3 + 11] = 0x02; // Parent ESDID. + GOFFData[GOFF::RecordLength * 3 + 71] = 0x05; // Size of symbol name. + GOFFData[GOFF::RecordLength * 3 + 72] = 0xa5; // Symbol name is v. + GOFFData[GOFF::RecordLength * 3 + 73] = 0x81; // Symbol name is a. + GOFFData[GOFF::RecordLength * 3 + 74] = 0x99; // Symbol name is r. + GOFFData[GOFF::RecordLength * 3 + 75] = 0x7b; // Symbol name is #. + GOFFData[GOFF::RecordLength * 3 + 76] = 0x83; // Symbol name is c. + + // TXT record. + GOFFData[GOFF::RecordLength * 4] = 0x03; + GOFFData[GOFF::RecordLength * 4 + 1] = 0x10; + GOFFData[GOFF::RecordLength * 4 + 7] = 0x02; + GOFFData[GOFF::RecordLength * 4 + 23] = 0x08; // Data Length. + GOFFData[GOFF::RecordLength * 4 + 24] = 0x12; + GOFFData[GOFF::RecordLength * 4 + 25] = 0x34; + GOFFData[GOFF::RecordLength * 4 + 26] = 0x56; + GOFFData[GOFF::RecordLength * 4 + 27] = 0x78; + GOFFData[GOFF::RecordLength * 4 + 28] = 0x9a; + GOFFData[GOFF::RecordLength * 4 + 29] = 0xbc; + GOFFData[GOFF::RecordLength * 4 + 30] = 0xde; + GOFFData[GOFF::RecordLength * 4 + 31] = 0xf0; + + // END record. + GOFFData[GOFF::RecordLength * 5] = 0x03; + GOFFData[GOFF::RecordLength * 5 + 1] = 0x40; + GOFFData[GOFF::RecordLength * 5 + 11] = 0x06; + + StringRef Data(GOFFData, GOFF::RecordLength * 6); + + Expected> GOFFObjOrErr = + object::ObjectFile::createGOFFObjectFile( + MemoryBufferRef(Data, "dummyGOFF")); + + ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded()); + + GOFFObjectFile *GOFFObj = dyn_cast((*GOFFObjOrErr).get()); + auto Symbols = GOFFObj->symbols(); + ASSERT_EQ(std::distance(Symbols.begin(), Symbols.end()), 1); + SymbolRef Symbol = *Symbols.begin(); + Expected SymbolNameOrErr = GOFFObj->getSymbolName(Symbol); + ASSERT_THAT_EXPECTED(SymbolNameOrErr, Succeeded()); + StringRef SymbolName = SymbolNameOrErr.get(); + EXPECT_EQ(SymbolName, "var#c"); + + auto Sections = GOFFObj->sections(); + ASSERT_EQ(std::distance(Sections.begin(), Sections.end()), 1); + SectionRef Section = *Sections.begin(); + Expected SectionContent = Section.getContents(); + ASSERT_THAT_EXPECTED(SectionContent, Succeeded()); + StringRef Contents = SectionContent.get(); + EXPECT_EQ(Contents, "\x12\x34\x56\x78\x9a\xbc\xde\xf0"); +} From 1107b47dcd145518c7b811bf10e2b848782b0478 Mon Sep 17 00:00:00 2001 From: Edwin Vane Date: Mon, 8 Apr 2024 11:22:19 -0400 Subject: [PATCH 2/6] [clang-tidy] rename designated initializers (#86976) readability-identifier-naming now supports renaming designated initializers. --- .../utils/RenamerClangTidyCheck.cpp | 22 ++++++++++++++++--- clang-tools-extra/docs/ReleaseNotes.rst | 3 ++- .../readability/identifier-naming.cpp | 10 +++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp index da1433aa2d05d..69b7d40ef628d 100644 --- a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp @@ -31,13 +31,12 @@ struct DenseMapInfo { using NamingCheckId = clang::tidy::RenamerClangTidyCheck::NamingCheckId; static inline NamingCheckId getEmptyKey() { - return {DenseMapInfo::getEmptyKey(), - "EMPTY"}; + return {DenseMapInfo::getEmptyKey(), "EMPTY"}; } static inline NamingCheckId getTombstoneKey() { return {DenseMapInfo::getTombstoneKey(), - "TOMBSTONE"}; + "TOMBSTONE"}; } static unsigned getHashValue(NamingCheckId Val) { @@ -367,6 +366,23 @@ class RenamerClangTidyVisitor return true; } + bool VisitDesignatedInitExpr(DesignatedInitExpr *Expr) { + for (const DesignatedInitExpr::Designator &D : Expr->designators()) { + if (!D.isFieldDesignator()) + continue; + const FieldDecl *FD = D.getFieldDecl(); + if (!FD) + continue; + const IdentifierInfo *II = FD->getIdentifier(); + if (!II) + continue; + SourceRange FixLocation{D.getFieldLoc(), D.getFieldLoc()}; + Check->addUsage(FD, FixLocation, SM); + } + + return true; + } + private: RenamerClangTidyCheck *Check; const SourceManager *SM; diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 2babb1406b977..bdd53f06e7e2f 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -266,7 +266,8 @@ Changes in existing checks - Improved :doc:`readability-identifier-naming ` check in `GetConfigPerFile` mode by resolving symbolic links to header files. Fixed handling of Hungarian - Prefix when configured to `LowerCase`. + Prefix when configured to `LowerCase`. Added support for renaming designated + initializers. - Improved :doc:`readability-implicit-bool-conversion ` check to provide diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming.cpp index d2e89a7c9855c..57ef4aae5ddb7 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming.cpp @@ -766,3 +766,13 @@ STATIC_MACRO void someFunc(MyFunPtr, const MyFunPtr****) {} // CHECK-FIXES: {{^}}STATIC_MACRO void someFunc(my_fun_ptr_t, const my_fun_ptr_t****) {} #undef STATIC_MACRO } + +struct Some_struct { + int SomeMember; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for public member 'SomeMember' [readability-identifier-naming] +// CHECK-FIXES: {{^}} int some_member; +}; +Some_struct g_s1{ .SomeMember = 1 }; +// CHECK-FIXES: {{^}}Some_struct g_s1{ .some_member = 1 }; +Some_struct g_s2{.SomeMember=1}; +// CHECK-FIXES: {{^}}Some_struct g_s2{.some_member=1}; From 312b9297bb9284bddb36980f64661c24c876eef0 Mon Sep 17 00:00:00 2001 From: lntue <35648136+lntue@users.noreply.github.com> Date: Mon, 8 Apr 2024 11:31:07 -0400 Subject: [PATCH 3/6] [libc] Increase timeout for death tests. (#87959) Fix test timeout on RISCV bots. Fixes https://github.com/llvm/llvm-project/issues/87096 --- libc/test/UnitTest/LibcDeathTestExecutors.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libc/test/UnitTest/LibcDeathTestExecutors.cpp b/libc/test/UnitTest/LibcDeathTestExecutors.cpp index e891c4e3c0b58..fa6d16410bb7a 100644 --- a/libc/test/UnitTest/LibcDeathTestExecutors.cpp +++ b/libc/test/UnitTest/LibcDeathTestExecutors.cpp @@ -19,7 +19,7 @@ namespace testing { bool Test::testProcessKilled(testutils::FunctionCaller *Func, int Signal, const char *LHSStr, const char *RHSStr, internal::Location Loc) { - testutils::ProcessStatus Result = testutils::invoke_in_subprocess(Func, 500); + testutils::ProcessStatus Result = testutils::invoke_in_subprocess(Func, 1000); if (const char *error = Result.get_error()) { Ctx->markFail(); @@ -31,7 +31,7 @@ bool Test::testProcessKilled(testutils::FunctionCaller *Func, int Signal, if (Result.timed_out()) { Ctx->markFail(); tlog << Loc; - tlog << "Process timed out after " << 500 << " milliseconds.\n"; + tlog << "Process timed out after " << 1000 << " milliseconds.\n"; return false; } @@ -62,7 +62,7 @@ bool Test::testProcessKilled(testutils::FunctionCaller *Func, int Signal, bool Test::testProcessExits(testutils::FunctionCaller *Func, int ExitCode, const char *LHSStr, const char *RHSStr, internal::Location Loc) { - testutils::ProcessStatus Result = testutils::invoke_in_subprocess(Func, 500); + testutils::ProcessStatus Result = testutils::invoke_in_subprocess(Func, 1000); if (const char *error = Result.get_error()) { Ctx->markFail(); @@ -74,7 +74,7 @@ bool Test::testProcessExits(testutils::FunctionCaller *Func, int ExitCode, if (Result.timed_out()) { Ctx->markFail(); tlog << Loc; - tlog << "Process timed out after " << 500 << " milliseconds.\n"; + tlog << "Process timed out after " << 1000 << " milliseconds.\n"; return false; } From ed1b24bf8b76871ab00f365d8dc066b3f7f76202 Mon Sep 17 00:00:00 2001 From: Slava Zakharin Date: Mon, 8 Apr 2024 08:32:03 -0700 Subject: [PATCH 4/6] [flang][runtime] Added simplified std::toupper implementation. (#87850) --- .../flang/Runtime/freestanding-tools.h | 19 +++++++++++++++++++ flang/lib/Decimal/decimal-to-binary.cpp | 16 ++++++++-------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/flang/include/flang/Runtime/freestanding-tools.h b/flang/include/flang/Runtime/freestanding-tools.h index 7f8d37d87e0e6..e94cb0a6c938c 100644 --- a/flang/include/flang/Runtime/freestanding-tools.h +++ b/flang/include/flang/Runtime/freestanding-tools.h @@ -12,6 +12,7 @@ #include "flang/Common/api-attrs.h" #include "flang/Runtime/c-or-cpp.h" #include +#include #include // The file defines a set of utilities/classes that might be @@ -57,6 +58,11 @@ #define STD_STRCMP_UNSUPPORTED 1 #endif +#if !defined(STD_TOUPPER_UNSUPPORTED) && \ + (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) +#define STD_TOUPPER_UNSUPPORTED 1 +#endif + namespace Fortran::runtime { #if STD_FILL_N_UNSUPPORTED @@ -195,5 +201,18 @@ static inline RT_API_ATTRS int strcmp(const char *lhs, const char *rhs) { using std::strcmp; #endif // !STD_STRCMP_UNSUPPORTED +#if STD_TOUPPER_UNSUPPORTED +// Provides alternative implementation for std::toupper(), if +// it is not supported. +static inline RT_API_ATTRS int toupper(int ch) { + if (ch >= 'a' && ch <= 'z') { + return ch - 'a' + 'A'; + } + return ch; +} +#else // !STD_TOUPPER_UNSUPPORTED +using std::toupper; +#endif // !STD_TOUPPER_UNSUPPORTED + } // namespace Fortran::runtime #endif // FORTRAN_RUNTIME_FREESTANDING_TOOLS_H_ diff --git a/flang/lib/Decimal/decimal-to-binary.cpp b/flang/lib/Decimal/decimal-to-binary.cpp index dc4aa82ac6fe4..eebd0736b67ad 100644 --- a/flang/lib/Decimal/decimal-to-binary.cpp +++ b/flang/lib/Decimal/decimal-to-binary.cpp @@ -11,9 +11,9 @@ #include "flang/Common/leading-zero-bit-count.h" #include "flang/Decimal/binary-floating-point.h" #include "flang/Decimal/decimal.h" +#include "flang/Runtime/freestanding-tools.h" #include #include -#include #include namespace Fortran::decimal { @@ -468,8 +468,8 @@ BigRadixFloatingPointNumber::ConvertToBinary( ++q; } } - if ((!limit || limit >= q + 3) && toupper(q[0]) == 'N' && - toupper(q[1]) == 'A' && toupper(q[2]) == 'N') { + if ((!limit || limit >= q + 3) && runtime::toupper(q[0]) == 'N' && + runtime::toupper(q[1]) == 'A' && runtime::toupper(q[2]) == 'N') { // NaN p = q + 3; bool isQuiet{true}; @@ -493,11 +493,11 @@ BigRadixFloatingPointNumber::ConvertToBinary( } return {Real{NaN(isQuiet)}}; } else { // Inf? - if ((!limit || limit >= q + 3) && toupper(q[0]) == 'I' && - toupper(q[1]) == 'N' && toupper(q[2]) == 'F') { - if ((!limit || limit >= q + 8) && toupper(q[3]) == 'I' && - toupper(q[4]) == 'N' && toupper(q[5]) == 'I' && - toupper(q[6]) == 'T' && toupper(q[7]) == 'Y') { + if ((!limit || limit >= q + 3) && runtime::toupper(q[0]) == 'I' && + runtime::toupper(q[1]) == 'N' && runtime::toupper(q[2]) == 'F') { + if ((!limit || limit >= q + 8) && runtime::toupper(q[3]) == 'I' && + runtime::toupper(q[4]) == 'N' && runtime::toupper(q[5]) == 'I' && + runtime::toupper(q[6]) == 'T' && runtime::toupper(q[7]) == 'Y') { p = q + 8; } else { p = q + 3; From 4a1c53f9fabbc18d436dcd4d5b572b82656fbbf9 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Fri, 5 Apr 2024 14:29:26 -0400 Subject: [PATCH 5/6] [SLP]Improve minbitwidth analysis for abs/smin/smax/umin/umax intrinsics. https://alive2.llvm.org/ce/z/ivPZ26 for the abs transformations. Reviewers: RKSimon Reviewed By: RKSimon Pull Request: https://github.com/llvm/llvm-project/pull/86135 --- .../Transforms/Vectorize/SLPVectorizer.cpp | 119 +++++++++++++++--- .../X86/call-arg-reduced-by-minbitwidth.ll | 4 +- .../cmp-after-intrinsic-call-minbitwidth.ll | 12 +- .../X86/store-abs-minbitwidth.ll | 9 +- 4 files changed, 117 insertions(+), 27 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 6a662b2791bdc..b41229e25a34b 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -7056,19 +7056,16 @@ bool BoUpSLP::areAllUsersVectorized( static std::pair getVectorCallCosts(CallInst *CI, FixedVectorType *VecTy, - TargetTransformInfo *TTI, TargetLibraryInfo *TLI) { + TargetTransformInfo *TTI, TargetLibraryInfo *TLI, + ArrayRef ArgTys) { Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI); // Calculate the cost of the scalar and vector calls. - SmallVector VecTys; - for (Use &Arg : CI->args()) - VecTys.push_back( - FixedVectorType::get(Arg->getType(), VecTy->getNumElements())); FastMathFlags FMF; if (auto *FPCI = dyn_cast(CI)) FMF = FPCI->getFastMathFlags(); SmallVector Arguments(CI->args()); - IntrinsicCostAttributes CostAttrs(ID, VecTy, Arguments, VecTys, FMF, + IntrinsicCostAttributes CostAttrs(ID, VecTy, Arguments, ArgTys, FMF, dyn_cast(CI)); auto IntrinsicCost = TTI->getIntrinsicInstrCost(CostAttrs, TTI::TCK_RecipThroughput); @@ -7081,8 +7078,8 @@ getVectorCallCosts(CallInst *CI, FixedVectorType *VecTy, if (!CI->isNoBuiltin() && VecFunc) { // Calculate the cost of the vector library call. // If the corresponding vector call is cheaper, return its cost. - LibCost = TTI->getCallInstrCost(nullptr, VecTy, VecTys, - TTI::TCK_RecipThroughput); + LibCost = + TTI->getCallInstrCost(nullptr, VecTy, ArgTys, TTI::TCK_RecipThroughput); } return {IntrinsicCost, LibCost}; } @@ -8508,6 +8505,30 @@ TTI::CastContextHint BoUpSLP::getCastContextHint(const TreeEntry &TE) const { return TTI::CastContextHint::None; } +/// Builds the arguments types vector for the given call instruction with the +/// given \p ID for the specified vector factor. +static SmallVector buildIntrinsicArgTypes(const CallInst *CI, + const Intrinsic::ID ID, + const unsigned VF, + unsigned MinBW) { + SmallVector ArgTys; + for (auto [Idx, Arg] : enumerate(CI->args())) { + if (ID != Intrinsic::not_intrinsic) { + if (isVectorIntrinsicWithScalarOpAtArg(ID, Idx)) { + ArgTys.push_back(Arg->getType()); + continue; + } + if (MinBW > 0) { + ArgTys.push_back(FixedVectorType::get( + IntegerType::get(CI->getContext(), MinBW), VF)); + continue; + } + } + ArgTys.push_back(FixedVectorType::get(Arg->getType(), VF)); + } + return ArgTys; +} + InstructionCost BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals, SmallPtrSetImpl &CheckedExtracts) { @@ -9074,7 +9095,11 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals, }; auto GetVectorCost = [=](InstructionCost CommonCost) { auto *CI = cast(VL0); - auto VecCallCosts = getVectorCallCosts(CI, VecTy, TTI, TLI); + Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI); + SmallVector ArgTys = + buildIntrinsicArgTypes(CI, ID, VecTy->getNumElements(), + It != MinBWs.end() ? It->second.first : 0); + auto VecCallCosts = getVectorCallCosts(CI, VecTy, TTI, TLI, ArgTys); return std::min(VecCallCosts.first, VecCallCosts.second) + CommonCost; }; return GetCostDiff(GetScalarCost, GetVectorCost); @@ -12548,7 +12573,10 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI); - auto VecCallCosts = getVectorCallCosts(CI, VecTy, TTI, TLI); + SmallVector ArgTys = + buildIntrinsicArgTypes(CI, ID, VecTy->getNumElements(), + It != MinBWs.end() ? It->second.first : 0); + auto VecCallCosts = getVectorCallCosts(CI, VecTy, TTI, TLI, ArgTys); bool UseIntrinsic = ID != Intrinsic::not_intrinsic && VecCallCosts.first <= VecCallCosts.second; @@ -12557,8 +12585,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { SmallVector TysForDecl; // Add return type if intrinsic is overloaded on it. if (UseIntrinsic && isVectorIntrinsicWithOverloadTypeAtArg(ID, -1)) - TysForDecl.push_back( - FixedVectorType::get(CI->getType(), E->Scalars.size())); + TysForDecl.push_back(VecTy); auto *CEI = cast(VL0); for (unsigned I : seq(0, CI->arg_size())) { ValueList OpVL; @@ -12566,7 +12593,12 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { // vectorized. if (UseIntrinsic && isVectorIntrinsicWithScalarOpAtArg(ID, I)) { ScalarArg = CEI->getArgOperand(I); - OpVecs.push_back(CEI->getArgOperand(I)); + // if decided to reduce bitwidth of abs intrinsic, it second argument + // must be set false (do not return poison, if value issigned min). + if (ID == Intrinsic::abs && It != MinBWs.end() && + It->second.first < DL->getTypeSizeInBits(CEI->getType())) + ScalarArg = Builder.getFalse(); + OpVecs.push_back(ScalarArg); if (isVectorIntrinsicWithOverloadTypeAtArg(ID, I)) TysForDecl.push_back(ScalarArg->getType()); continue; @@ -12579,10 +12611,13 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { } ScalarArg = CEI->getArgOperand(I); if (cast(OpVec->getType())->getElementType() != - ScalarArg->getType()) { + ScalarArg->getType() && + It == MinBWs.end()) { auto *CastTy = FixedVectorType::get(ScalarArg->getType(), VecTy->getNumElements()); OpVec = Builder.CreateIntCast(OpVec, CastTy, GetOperandSignedness(I)); + } else if (It != MinBWs.end()) { + OpVec = Builder.CreateIntCast(OpVec, VecTy, GetOperandSignedness(I)); } LLVM_DEBUG(dbgs() << "SLP: OpVec[" << I << "]: " << *OpVec << "\n"); OpVecs.push_back(OpVec); @@ -14326,6 +14361,62 @@ bool BoUpSLP::collectValuesToDemote( return TryProcessInstruction(I, *ITE, BitWidth, Ops); } + case Instruction::Call: { + auto *IC = dyn_cast(I); + if (!IC) + break; + Intrinsic::ID ID = getVectorIntrinsicIDForCall(IC, TLI); + if (ID != Intrinsic::abs && ID != Intrinsic::smin && + ID != Intrinsic::smax && ID != Intrinsic::umin && ID != Intrinsic::umax) + break; + SmallVector Operands(1, I->getOperand(0)); + function_ref CallChecker; + auto CompChecker = [&](unsigned BitWidth, unsigned OrigBitWidth) { + assert(BitWidth <= OrigBitWidth && "Unexpected bitwidths!"); + if (ID == Intrinsic::umin || ID == Intrinsic::umax) { + APInt Mask = APInt::getBitsSetFrom(OrigBitWidth, BitWidth); + return MaskedValueIsZero(I->getOperand(0), Mask, SimplifyQuery(*DL)) && + MaskedValueIsZero(I->getOperand(1), Mask, SimplifyQuery(*DL)); + } + assert((ID == Intrinsic::smin || ID == Intrinsic::smax) && + "Expected min/max intrinsics only."); + unsigned SignBits = OrigBitWidth - BitWidth; + return SignBits <= ComputeNumSignBits(I->getOperand(0), *DL, 0, AC, + nullptr, DT) && + SignBits <= + ComputeNumSignBits(I->getOperand(1), *DL, 0, AC, nullptr, DT); + }; + End = 1; + if (ID != Intrinsic::abs) { + Operands.push_back(I->getOperand(1)); + End = 2; + CallChecker = CompChecker; + } + InstructionCost BestCost = + std::numeric_limits::max(); + unsigned BestBitWidth = BitWidth; + unsigned VF = ITE->Scalars.size(); + // Choose the best bitwidth based on cost estimations. + auto Checker = [&](unsigned BitWidth, unsigned) { + unsigned MinBW = PowerOf2Ceil(BitWidth); + SmallVector ArgTys = buildIntrinsicArgTypes(IC, ID, VF, MinBW); + auto VecCallCosts = getVectorCallCosts( + IC, + FixedVectorType::get(IntegerType::get(IC->getContext(), MinBW), VF), + TTI, TLI, ArgTys); + InstructionCost Cost = std::min(VecCallCosts.first, VecCallCosts.second); + if (Cost < BestCost) { + BestCost = Cost; + BestBitWidth = BitWidth; + } + return false; + }; + [[maybe_unused]] bool NeedToExit; + (void)AttemptCheckBitwidth(Checker, NeedToExit); + BitWidth = BestBitWidth; + return TryProcessInstruction(I, *ITE, BitWidth, Operands, CallChecker); + } + // Otherwise, conservatively give up. default: break; diff --git a/llvm/test/Transforms/SLPVectorizer/X86/call-arg-reduced-by-minbitwidth.ll b/llvm/test/Transforms/SLPVectorizer/X86/call-arg-reduced-by-minbitwidth.ll index 27c9655f94d3c..82966124d3baa 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/call-arg-reduced-by-minbitwidth.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/call-arg-reduced-by-minbitwidth.ll @@ -11,9 +11,7 @@ define void @test(ptr %0, i8 %1, i1 %cmp12.i) { ; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <8 x i8> [[TMP4]], <8 x i8> poison, <8 x i32> zeroinitializer ; CHECK-NEXT: br label [[PRE:%.*]] ; CHECK: pre: -; CHECK-NEXT: [[TMP6:%.*]] = zext <8 x i8> [[TMP5]] to <8 x i32> -; CHECK-NEXT: [[TMP7:%.*]] = call <8 x i32> @llvm.umax.v8i32(<8 x i32> [[TMP6]], <8 x i32> ) -; CHECK-NEXT: [[TMP8:%.*]] = trunc <8 x i32> [[TMP7]] to <8 x i8> +; CHECK-NEXT: [[TMP8:%.*]] = call <8 x i8> @llvm.umax.v8i8(<8 x i8> [[TMP5]], <8 x i8> ) ; CHECK-NEXT: [[TMP9:%.*]] = add <8 x i8> [[TMP8]], ; CHECK-NEXT: [[TMP10:%.*]] = select <8 x i1> [[TMP3]], <8 x i8> [[TMP9]], <8 x i8> [[TMP5]] ; CHECK-NEXT: store <8 x i8> [[TMP10]], ptr [[TMP0]], align 1 diff --git a/llvm/test/Transforms/SLPVectorizer/X86/cmp-after-intrinsic-call-minbitwidth.ll b/llvm/test/Transforms/SLPVectorizer/X86/cmp-after-intrinsic-call-minbitwidth.ll index a05d4fdd6315b..9fa88084aaa0a 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/cmp-after-intrinsic-call-minbitwidth.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/cmp-after-intrinsic-call-minbitwidth.ll @@ -5,12 +5,14 @@ define void @test() { ; CHECK-LABEL: define void @test( ; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> zeroinitializer, <2 x i32> zeroinitializer) -; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> zeroinitializer, <2 x i32> zeroinitializer, <2 x i32> [[TMP0]] -; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i32> [[TMP1]], zeroinitializer -; CHECK-NEXT: [[ADD:%.*]] = extractelement <2 x i32> [[TMP2]], i32 1 +; CHECK-NEXT: [[TMP0:%.*]] = call <2 x i2> @llvm.smin.v2i2(<2 x i2> zeroinitializer, <2 x i2> zeroinitializer) +; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> zeroinitializer, <2 x i2> zeroinitializer, <2 x i2> [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i2> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x i2> [[TMP2]], i32 1 +; CHECK-NEXT: [[ADD:%.*]] = zext i2 [[TMP3]] to i32 ; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[ADD]], 0 -; CHECK-NEXT: [[ADD45:%.*]] = extractelement <2 x i32> [[TMP2]], i32 0 +; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i2> [[TMP2]], i32 0 +; CHECK-NEXT: [[ADD45:%.*]] = zext i2 [[TMP5]] to i32 ; CHECK-NEXT: [[ADD152:%.*]] = or i32 [[ADD45]], [[ADD]] ; CHECK-NEXT: [[IDXPROM153:%.*]] = sext i32 [[ADD152]] to i64 ; CHECK-NEXT: [[ARRAYIDX154:%.*]] = getelementptr i8, ptr null, i64 [[IDXPROM153]] diff --git a/llvm/test/Transforms/SLPVectorizer/X86/store-abs-minbitwidth.ll b/llvm/test/Transforms/SLPVectorizer/X86/store-abs-minbitwidth.ll index e8b854b7cea6c..df7312e3d2b56 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/store-abs-minbitwidth.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/store-abs-minbitwidth.ll @@ -13,14 +13,13 @@ define i32 @test(ptr noalias %in, ptr noalias %inn, ptr %out) { ; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <2 x i8> [[TMP3]], <2 x i8> poison, <4 x i32> ; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <2 x i8> [[TMP2]], <2 x i8> poison, <4 x i32> ; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <4 x i8> [[TMP5]], <4 x i8> [[TMP6]], <4 x i32> -; CHECK-NEXT: [[TMP8:%.*]] = sext <4 x i8> [[TMP7]] to <4 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = sext <4 x i8> [[TMP7]] to <4 x i16> ; CHECK-NEXT: [[TMP9:%.*]] = shufflevector <2 x i8> [[TMP1]], <2 x i8> poison, <4 x i32> ; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <2 x i8> [[TMP4]], <2 x i8> poison, <4 x i32> ; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <4 x i8> [[TMP9]], <4 x i8> [[TMP10]], <4 x i32> -; CHECK-NEXT: [[TMP12:%.*]] = sext <4 x i8> [[TMP11]] to <4 x i32> -; CHECK-NEXT: [[TMP13:%.*]] = sub <4 x i32> [[TMP12]], [[TMP8]] -; CHECK-NEXT: [[TMP14:%.*]] = call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[TMP13]], i1 true) -; CHECK-NEXT: [[TMP15:%.*]] = trunc <4 x i32> [[TMP14]] to <4 x i16> +; CHECK-NEXT: [[TMP12:%.*]] = sext <4 x i8> [[TMP11]] to <4 x i16> +; CHECK-NEXT: [[TMP13:%.*]] = sub <4 x i16> [[TMP12]], [[TMP8]] +; CHECK-NEXT: [[TMP15:%.*]] = call <4 x i16> @llvm.abs.v4i16(<4 x i16> [[TMP13]], i1 false) ; CHECK-NEXT: store <4 x i16> [[TMP15]], ptr [[OUT:%.*]], align 2 ; CHECK-NEXT: ret i32 undef ; From b439140e2982dd77ef28a9069e16ae77bbe2bc5a Mon Sep 17 00:00:00 2001 From: Fraser Cormack Date: Mon, 8 Apr 2024 16:51:30 +0100 Subject: [PATCH 6/6] [libclc] Fix more spirv build dependencies The last fix was incomplete. --- libclc/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt index 770f69a15a300..c6e3cdf23fe0c 100644 --- a/libclc/CMakeLists.txt +++ b/libclc/CMakeLists.txt @@ -332,7 +332,7 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} ) if( ${ARCH} STREQUAL "spirv" OR ${ARCH} STREQUAL "spirv64" ) set( spv_suffix ${arch_suffix}.spv ) add_custom_command( OUTPUT "${spv_suffix}" - COMMAND ${LLVM_SPIRV} ${spvflags} -o "${spv_suffix}" ${builtins_link_lib_tgt} + COMMAND ${LLVM_SPIRV} ${spvflags} -o "${spv_suffix}" $ DEPENDS ${builtins_link_lib_tgt} ) add_custom_target( "prepare-${spv_suffix}" ALL DEPENDS "${spv_suffix}" ) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${spv_suffix}