From 276335389133d6acf5f9d7d2f8ce09f9c610cb9c Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 28 Mar 2024 09:10:34 -0700 Subject: [PATCH 0001/1292] [Object,ELFType] Rename TargetEndianness to Endianness (#86604) `TargetEndianness` is long and unwieldy. "Target" in the name is confusing. Rename it to "Endianness". I cannot find noticeable out-of-tree users of `TargetEndianness`, but keep `TargetEndianness` to make this patch safer. `TargetEndianness` will be removed by a subsequent change. --- lld/ELF/Arch/Mips.cpp | 6 +- lld/ELF/DWARF.h | 2 +- lld/ELF/InputFiles.cpp | 6 +- lld/ELF/InputSection.cpp | 4 +- lld/ELF/SyntheticSections.cpp | 4 +- .../llvm/ExecutionEngine/Orc/ExecutionUtils.h | 2 +- llvm/include/llvm/Object/ELFObjectFile.h | 16 ++- llvm/include/llvm/Object/ELFTypes.h | 101 +++++++++--------- .../JITLink/ELFLinkGraphBuilder.h | 2 +- .../ExecutionEngine/Orc/ExecutionUtils.cpp | 4 +- llvm/lib/InterfaceStub/ELFObjHandler.cpp | 2 +- llvm/lib/ObjCopy/ELF/ELFObject.cpp | 15 ++- llvm/lib/ObjectYAML/ELFEmitter.cpp | 58 +++++----- llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h | 9 +- llvm/tools/llvm-readobj/ELFDumper.cpp | 37 +++---- 15 files changed, 130 insertions(+), 138 deletions(-) diff --git a/lld/ELF/Arch/Mips.cpp b/lld/ELF/Arch/Mips.cpp index b02ad10649d9..e36e9d59a740 100644 --- a/lld/ELF/Arch/Mips.cpp +++ b/lld/ELF/Arch/Mips.cpp @@ -380,7 +380,7 @@ bool MIPS::needsThunk(RelExpr expr, RelType type, const InputFile *file, template int64_t MIPS::getImplicitAddend(const uint8_t *buf, RelType type) const { - const endianness e = ELFT::TargetEndianness; + const endianness e = ELFT::Endianness; switch (type) { case R_MIPS_32: case R_MIPS_REL32: @@ -521,7 +521,7 @@ static uint64_t fixupCrossModeJump(uint8_t *loc, RelType type, uint64_t val) { // to a microMIPS target and vice versa. In that cases jump // instructions need to be replaced by their "cross-mode" // equivalents. - const endianness e = ELFT::TargetEndianness; + const endianness e = ELFT::Endianness; bool isMicroTgt = val & 0x1; bool isCrossJump = (isMicroTgt && isBranchReloc(type)) || (!isMicroTgt && isMicroBranchReloc(type)); @@ -567,7 +567,7 @@ static uint64_t fixupCrossModeJump(uint8_t *loc, RelType type, uint64_t val) { template void MIPS::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { - const endianness e = ELFT::TargetEndianness; + const endianness e = ELFT::Endianness; RelType type = rel.type; if (ELFT::Is64Bits || config->mipsN32Abi) diff --git a/lld/ELF/DWARF.h b/lld/ELF/DWARF.h index 1b9a3e3f7794..d56895277bcc 100644 --- a/lld/ELF/DWARF.h +++ b/lld/ELF/DWARF.h @@ -74,7 +74,7 @@ public: StringRef getLineStrSection() const override { return lineStrSection; } bool isLittleEndian() const override { - return ELFT::TargetEndianness == llvm::endianness::little; + return ELFT::Endianness == llvm::endianness::little; } std::optional find(const llvm::DWARFSection &sec, diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 42761b6e1209..725c6f166fff 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -971,8 +971,8 @@ template static uint32_t readAndFeatures(const InputSection &sec) { const uint8_t *place = desc.data(); if (desc.size() < 8) reportFatal(place, "program property is too short"); - uint32_t type = read32(desc.data()); - uint32_t size = read32(desc.data() + 4); + uint32_t type = read32(desc.data()); + uint32_t size = read32(desc.data() + 4); desc = desc.slice(8); if (desc.size() < size) reportFatal(place, "program property is too short"); @@ -983,7 +983,7 @@ template static uint32_t readAndFeatures(const InputSection &sec) { // accumulate the bits set. if (size < 4) reportFatal(place, "FEATURE_1_AND entry is too short"); - featuresSet |= read32(desc.data()); + featuresSet |= read32(desc.data()); } // Padding is present in the note descriptor, if necessary. diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index c34bf08757b1..4f88313b868b 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -1258,10 +1258,10 @@ void EhInputSection::split(ArrayRef rels) { msg = "CIE/FDE too small"; break; } - uint64_t size = endian::read32(d.data()); + uint64_t size = endian::read32(d.data()); if (size == 0) // ZERO terminator break; - uint32_t id = endian::read32(d.data() + 4); + uint32_t id = endian::read32(d.data() + 4); size += 4; if (LLVM_UNLIKELY(size > d.size())) { // If it is 0xFFFFFFFF, the next 8 bytes contain the size instead, diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 650bd6cd3900..8708bfeef8fa 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -415,7 +415,7 @@ void EhFrameSection::addRecords(EhInputSection *sec, ArrayRef rels) { for (EhSectionPiece &cie : sec->cies) offsetToCie[cie.inputOff] = addCie(cie, rels); for (EhSectionPiece &fde : sec->fdes) { - uint32_t id = endian::read32(fde.data().data() + 4); + uint32_t id = endian::read32(fde.data().data() + 4); CieRecord *rec = offsetToCie[fde.inputOff + 4 - id]; if (!rec) fatal(toString(sec) + ": invalid CIE reference"); @@ -448,7 +448,7 @@ void EhFrameSection::iterateFDEWithLSDAAux( if (hasLSDA(cie)) ciesWithLSDA.insert(cie.inputOff); for (EhSectionPiece &fde : sec.fdes) { - uint32_t id = endian::read32(fde.data().data() + 4); + uint32_t id = endian::read32(fde.data().data() + 4); if (!ciesWithLSDA.contains(fde.inputOff + 4 - id)) continue; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h index f7c286bec778..ed30a792e9e9 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h @@ -352,7 +352,7 @@ private: : ES(ES), L(L) {} static Expected getTargetPointerSize(const Triple &TT); - static Expected getTargetEndianness(const Triple &TT); + static Expected getEndianness(const Triple &TT); Expected> createStubsGraph(const SymbolMap &Resolved); diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h index f57a7ab8882a..1d457be93741 100644 --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -419,7 +419,7 @@ protected: if (Contents[0] != ELFAttrs::Format_Version || Contents.size() == 1) return Error::success(); - if (Error E = Attributes.parse(Contents, ELFT::TargetEndianness)) + if (Error E = Attributes.parse(Contents, ELFT::Endianness)) return E; break; } @@ -482,7 +482,7 @@ public: bool isDyldType() const { return isDyldELFObject; } static bool classof(const Binary *v) { return v->getType() == - getELFType(ELFT::TargetEndianness == llvm::endianness::little, + getELFType(ELFT::Endianness == llvm::endianness::little, ELFT::Is64Bits); } @@ -1155,10 +1155,9 @@ ELFObjectFile::ELFObjectFile(MemoryBufferRef Object, ELFFile EF, const Elf_Shdr *DotDynSymSec, const Elf_Shdr *DotSymtabSec, const Elf_Shdr *DotSymtabShndx) - : ELFObjectFileBase( - getELFType(ELFT::TargetEndianness == llvm::endianness::little, - ELFT::Is64Bits), - Object), + : ELFObjectFileBase(getELFType(ELFT::Endianness == llvm::endianness::little, + ELFT::Is64Bits), + Object), EF(EF), DotDynSymSec(DotDynSymSec), DotSymtabSec(DotSymtabSec), DotSymtabShndxSec(DotSymtabShndx) {} @@ -1226,8 +1225,7 @@ uint8_t ELFObjectFile::getBytesInAddress() const { template StringRef ELFObjectFile::getFileFormatName() const { - constexpr bool IsLittleEndian = - ELFT::TargetEndianness == llvm::endianness::little; + constexpr bool IsLittleEndian = ELFT::Endianness == llvm::endianness::little; switch (EF.getHeader().e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: switch (EF.getHeader().e_machine) { @@ -1305,7 +1303,7 @@ StringRef ELFObjectFile::getFileFormatName() const { } template Triple::ArchType ELFObjectFile::getArch() const { - bool IsLittleEndian = ELFT::TargetEndianness == llvm::endianness::little; + bool IsLittleEndian = ELFT::Endianness == llvm::endianness::little; switch (EF.getHeader().e_machine) { case ELF::EM_68K: return Triple::m68k; diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h index 4986ecf8323d..4617b70a2f12 100644 --- a/llvm/include/llvm/Object/ELFTypes.h +++ b/llvm/include/llvm/Object/ELFTypes.h @@ -52,6 +52,7 @@ private: public: static const endianness TargetEndianness = E; + static const endianness Endianness = E; static const bool Is64Bits = Is64; using uint = std::conditional_t; @@ -145,9 +146,9 @@ using ELF64BE = ELFType; // Section header. template struct Elf_Shdr_Base; -template -struct Elf_Shdr_Base> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template +struct Elf_Shdr_Base> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Word sh_flags; // Section flags (SHF_*) @@ -160,9 +161,9 @@ struct Elf_Shdr_Base> { Elf_Word sh_entsize; // Size of records contained within the section }; -template -struct Elf_Shdr_Base> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template +struct Elf_Shdr_Base> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Xword sh_flags; // Section flags (SHF_*) @@ -190,9 +191,9 @@ struct Elf_Shdr_Impl : Elf_Shdr_Base { template struct Elf_Sym_Base; -template -struct Elf_Sym_Base> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template +struct Elf_Sym_Base> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Word st_name; // Symbol name (index into string table) Elf_Addr st_value; // Value or address associated with the symbol Elf_Word st_size; // Size of the symbol @@ -201,9 +202,9 @@ struct Elf_Sym_Base> { Elf_Half st_shndx; // Which section (header table index) it's defined in }; -template -struct Elf_Sym_Base> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template +struct Elf_Sym_Base> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Word st_name; // Symbol name (index into string table) unsigned char st_info; // Symbol's type and binding attributes unsigned char st_other; // Must be zero; reserved @@ -349,9 +350,9 @@ struct Elf_Vernaux_Impl { /// table section (.dynamic) look like. template struct Elf_Dyn_Base; -template -struct Elf_Dyn_Base> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template +struct Elf_Dyn_Base> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Sword d_tag; union { Elf_Word d_val; @@ -359,9 +360,9 @@ struct Elf_Dyn_Base> { } d_un; }; -template -struct Elf_Dyn_Base> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template +struct Elf_Dyn_Base> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Sxword d_tag; union { Elf_Xword d_val; @@ -381,9 +382,9 @@ struct Elf_Dyn_Impl : Elf_Dyn_Base { uintX_t getPtr() const { return d_un.d_ptr; } }; -template -struct Elf_Rel_Impl, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template +struct Elf_Rel_Impl, false> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) static const bool IsRela = false; Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Word r_info; // Symbol table index and type of relocation to apply @@ -416,17 +417,17 @@ struct Elf_Rel_Impl, false> { } }; -template -struct Elf_Rel_Impl, true> - : public Elf_Rel_Impl, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template +struct Elf_Rel_Impl, true> + : public Elf_Rel_Impl, false> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) static const bool IsRela = true; Elf_Sword r_addend; // Compute value for relocatable field by adding this }; -template -struct Elf_Rel_Impl, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template +struct Elf_Rel_Impl, false> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) static const bool IsRela = false; Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Xword r_info; // Symbol table index and type of relocation to apply @@ -469,10 +470,10 @@ struct Elf_Rel_Impl, false> { } }; -template -struct Elf_Rel_Impl, true> - : public Elf_Rel_Impl, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template +struct Elf_Rel_Impl, true> + : public Elf_Rel_Impl, false> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) static const bool IsRela = true; Elf_Sxword r_addend; // Compute value for relocatable field by adding this. }; @@ -504,9 +505,9 @@ struct Elf_Ehdr_Impl { unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } }; -template -struct Elf_Phdr_Impl> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template +struct Elf_Phdr_Impl> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Word p_type; // Type of segment Elf_Off p_offset; // FileOffset where segment is located, in bytes Elf_Addr p_vaddr; // Virtual Address of beginning of segment @@ -517,9 +518,9 @@ struct Elf_Phdr_Impl> { Elf_Word p_align; // Segment alignment constraint }; -template -struct Elf_Phdr_Impl> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template +struct Elf_Phdr_Impl> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Word p_type; // Type of segment Elf_Word p_flags; // Segment flags Elf_Off p_offset; // FileOffset where segment is located, in bytes @@ -574,17 +575,17 @@ struct Elf_GnuHash_Impl { // Compressed section headers. // http://www.sco.com/developers/gabi/latest/ch4.sheader.html#compression_header -template -struct Elf_Chdr_Impl> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template +struct Elf_Chdr_Impl> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Word ch_type; Elf_Word ch_size; Elf_Word ch_addralign; }; -template -struct Elf_Chdr_Impl> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template +struct Elf_Chdr_Impl> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Word ch_type; Elf_Word ch_reserved; Elf_Xword ch_size; @@ -742,17 +743,17 @@ template struct Elf_CGProfile_Impl { template struct Elf_Mips_RegInfo; -template -struct Elf_Mips_RegInfo> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template +struct Elf_Mips_RegInfo> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Word ri_gprmask; // bit-mask of used general registers Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers Elf_Addr ri_gp_value; // gp register value }; -template -struct Elf_Mips_RegInfo> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template +struct Elf_Mips_RegInfo> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Word ri_gprmask; // bit-mask of used general registers Elf_Word ri_pad; // unused padding field Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers diff --git a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h index e1b11dfcfc21..5dae60062939 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h +++ b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h @@ -193,7 +193,7 @@ ELFLinkGraphBuilder::ELFLinkGraphBuilder( StringRef FileName, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName) : ELFLinkGraphBuilderBase(std::make_unique( FileName.str(), Triple(std::move(TT)), std::move(Features), - ELFT::Is64Bits ? 8 : 4, llvm::endianness(ELFT::TargetEndianness), + ELFT::Is64Bits ? 8 : 4, llvm::endianness(ELFT::Endianness), std::move(GetEdgeKindName))), Obj(Obj) { LLVM_DEBUG( diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp index 3952445bb1aa..670c8cf996fd 100644 --- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp @@ -545,7 +545,7 @@ DLLImportDefinitionGenerator::getTargetPointerSize(const Triple &TT) { } Expected -DLLImportDefinitionGenerator::getTargetEndianness(const Triple &TT) { +DLLImportDefinitionGenerator::getEndianness(const Triple &TT) { switch (TT.getArch()) { case Triple::x86_64: return llvm::endianness::little; @@ -562,7 +562,7 @@ DLLImportDefinitionGenerator::createStubsGraph(const SymbolMap &Resolved) { auto PointerSize = getTargetPointerSize(TT); if (!PointerSize) return PointerSize.takeError(); - auto Endianness = getTargetEndianness(TT); + auto Endianness = getEndianness(TT); if (!Endianness) return Endianness.takeError(); diff --git a/llvm/lib/InterfaceStub/ELFObjHandler.cpp b/llvm/lib/InterfaceStub/ELFObjHandler.cpp index c1256563d0d6..9c81a8832c0f 100644 --- a/llvm/lib/InterfaceStub/ELFObjHandler.cpp +++ b/llvm/lib/InterfaceStub/ELFObjHandler.cpp @@ -57,7 +57,7 @@ static void initELFHeader(typename ELFT::Ehdr &ElfHeader, uint16_t Machine) { ElfHeader.e_ident[EI_MAG2] = ElfMagic[EI_MAG2]; ElfHeader.e_ident[EI_MAG3] = ElfMagic[EI_MAG3]; ElfHeader.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32; - bool IsLittleEndian = ELFT::TargetEndianness == llvm::endianness::little; + bool IsLittleEndian = ELFT::Endianness == llvm::endianness::little; ElfHeader.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB; ElfHeader.e_ident[EI_VERSION] = EV_CURRENT; ElfHeader.e_ident[EI_OSABI] = ELFOSABI_NONE; diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp index 9547cc10d2a0..8b6a0035dae3 100644 --- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp +++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp @@ -33,6 +33,7 @@ using namespace llvm; using namespace llvm::ELF; using namespace llvm::objcopy::elf; using namespace llvm::object; +using namespace llvm::support; template void ELFWriter::writePhdr(const Segment &Seg) { uint8_t *B = reinterpret_cast(Buf->getBufferStart()) + @@ -1175,9 +1176,9 @@ template Error ELFSectionWriter::visit(const GroupSection &Sec) { ELF::Elf32_Word *Buf = reinterpret_cast(Out.getBufferStart() + Sec.Offset); - support::endian::write32(Buf++, Sec.FlagWord); + endian::write32(Buf++, Sec.FlagWord); for (SectionBase *S : Sec.GroupMembers) - support::endian::write32(Buf++, S->Index); + endian::write32(Buf++, S->Index); return Error::success(); } @@ -1522,10 +1523,9 @@ Error ELFBuilder::initGroupSection(GroupSection *GroupSec) { reinterpret_cast(GroupSec->Contents.data()); const ELF::Elf32_Word *End = Word + GroupSec->Contents.size() / sizeof(ELF::Elf32_Word); - GroupSec->setFlagWord( - support::endian::read32(Word++)); + GroupSec->setFlagWord(endian::read32(Word++)); for (; Word != End; ++Word) { - uint32_t Index = support::endian::read32(Word); + uint32_t Index = support::endian::read32(Word); Expected Sec = SecTable.getSection( Index, "group member index " + Twine(Index) + " in section '" + GroupSec->Name + "' is invalid"); @@ -1993,9 +1993,8 @@ template void ELFWriter::writeEhdr() { Ehdr.e_ident[EI_MAG2] = 'L'; Ehdr.e_ident[EI_MAG3] = 'F'; Ehdr.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32; - Ehdr.e_ident[EI_DATA] = ELFT::TargetEndianness == llvm::endianness::big - ? ELFDATA2MSB - : ELFDATA2LSB; + Ehdr.e_ident[EI_DATA] = + ELFT::Endianness == llvm::endianness::big ? ELFDATA2MSB : ELFDATA2LSB; Ehdr.e_ident[EI_VERSION] = EV_CURRENT; Ehdr.e_ident[EI_OSABI] = Obj.OSABI; Ehdr.e_ident[EI_ABIVERSION] = Obj.ABIVersion; diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp index 58a725f8d877..b7118a543fae 100644 --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -1314,7 +1314,7 @@ void ELFState::writeSectionContent(Elf_Shdr &SHeader, if (!ELFT::Is64Bits && E > UINT32_MAX) reportError(Section.Name + ": the value is too large for 32-bits: 0x" + Twine::utohexstr(E)); - CBA.write(E, ELFT::TargetEndianness); + CBA.write(E, ELFT::Endianness); } SHeader.sh_size = sizeof(uintX_t) * Section.Entries->size(); @@ -1333,7 +1333,7 @@ void ELFState::writeSectionContent( return; for (uint32_t E : *Shndx.Entries) - CBA.write(E, ELFT::TargetEndianness); + CBA.write(E, ELFT::Endianness); SHeader.sh_size = Shndx.Entries->size() * SHeader.sh_entsize; } @@ -1357,7 +1357,7 @@ void ELFState::writeSectionContent(Elf_Shdr &SHeader, SectionIndex = llvm::ELF::GRP_COMDAT; else SectionIndex = toSectionIndex(Member.sectionNameOrType, Section.Name); - CBA.write(SectionIndex, ELFT::TargetEndianness); + CBA.write(SectionIndex, ELFT::Endianness); } SHeader.sh_size = SHeader.sh_entsize * Section.Members->size(); } @@ -1370,7 +1370,7 @@ void ELFState::writeSectionContent(Elf_Shdr &SHeader, return; for (uint16_t Version : *Section.Entries) - CBA.write(Version, ELFT::TargetEndianness); + CBA.write(Version, ELFT::Endianness); SHeader.sh_size = Section.Entries->size() * SHeader.sh_entsize; } @@ -1382,7 +1382,7 @@ void ELFState::writeSectionContent( return; for (const ELFYAML::StackSizeEntry &E : *Section.Entries) { - CBA.write(E.Address, ELFT::TargetEndianness); + CBA.write(E.Address, ELFT::Endianness); SHeader.sh_size += sizeof(uintX_t) + CBA.writeULEB128(E.Size); } } @@ -1444,7 +1444,7 @@ void ELFState::writeSectionContent( uint64_t TotalNumBlocks = 0; for (const ELFYAML::BBAddrMapEntry::BBRangeEntry &BBR : *E.BBRanges) { // Write the base address of the range. - CBA.write(BBR.BaseAddress, ELFT::TargetEndianness); + CBA.write(BBR.BaseAddress, ELFT::Endianness); // Write number of BBEntries (number of basic blocks in this basic block // range). This is overridden by the 'NumBlocks' YAML field when // specified. @@ -1558,7 +1558,7 @@ void ELFState::writeSectionContent( return; for (const ELFYAML::CallGraphEntryWeight &E : *Section.Entries) { - CBA.write(E.Weight, ELFT::TargetEndianness); + CBA.write(E.Weight, ELFT::Endianness); SHeader.sh_size += sizeof(object::Elf_CGProfile_Impl); } } @@ -1572,15 +1572,15 @@ void ELFState::writeSectionContent(Elf_Shdr &SHeader, CBA.write( Section.NBucket.value_or(llvm::yaml::Hex64(Section.Bucket->size())), - ELFT::TargetEndianness); + ELFT::Endianness); CBA.write( Section.NChain.value_or(llvm::yaml::Hex64(Section.Chain->size())), - ELFT::TargetEndianness); + ELFT::Endianness); for (uint32_t Val : *Section.Bucket) - CBA.write(Val, ELFT::TargetEndianness); + CBA.write(Val, ELFT::Endianness); for (uint32_t Val : *Section.Chain) - CBA.write(Val, ELFT::TargetEndianness); + CBA.write(Val, ELFT::Endianness); SHeader.sh_size = (2 + Section.Bucket->size() + Section.Chain->size()) * 4; } @@ -1687,8 +1687,8 @@ void ELFState::writeSectionContent( return; for (const ELFYAML::ARMIndexTableEntry &E : *Section.Entries) { - CBA.write(E.Offset, ELFT::TargetEndianness); - CBA.write(E.Value, ELFT::TargetEndianness); + CBA.write(E.Offset, ELFT::Endianness); + CBA.write(E.Value, ELFT::Endianness); } SHeader.sh_size = Section.Entries->size() * 8; } @@ -1729,8 +1729,8 @@ void ELFState::writeSectionContent(Elf_Shdr &SHeader, return; for (const ELFYAML::DynamicEntry &DE : *Section.Entries) { - CBA.write(DE.Tag, ELFT::TargetEndianness); - CBA.write(DE.Val, ELFT::TargetEndianness); + CBA.write(DE.Tag, ELFT::Endianness); + CBA.write(DE.Val, ELFT::Endianness); } SHeader.sh_size = 2 * sizeof(uintX_t) * Section.Entries->size(); } @@ -1758,18 +1758,18 @@ void ELFState::writeSectionContent(Elf_Shdr &SHeader, for (const ELFYAML::NoteEntry &NE : *Section.Notes) { // Write name size. if (NE.Name.empty()) - CBA.write(0, ELFT::TargetEndianness); + CBA.write(0, ELFT::Endianness); else - CBA.write(NE.Name.size() + 1, ELFT::TargetEndianness); + CBA.write(NE.Name.size() + 1, ELFT::Endianness); // Write description size. if (NE.Desc.binary_size() == 0) - CBA.write(0, ELFT::TargetEndianness); + CBA.write(0, ELFT::Endianness); else - CBA.write(NE.Desc.binary_size(), ELFT::TargetEndianness); + CBA.write(NE.Desc.binary_size(), ELFT::Endianness); // Write type. - CBA.write(NE.Type, ELFT::TargetEndianness); + CBA.write(NE.Type, ELFT::Endianness); // Write name, null terminator and padding. if (!NE.Name.empty()) { @@ -1803,35 +1803,35 @@ void ELFState::writeSectionContent(Elf_Shdr &SHeader, // be used to override this field, which is useful for producing broken // objects. if (Section.Header->NBuckets) - CBA.write(*Section.Header->NBuckets, ELFT::TargetEndianness); + CBA.write(*Section.Header->NBuckets, ELFT::Endianness); else - CBA.write(Section.HashBuckets->size(), ELFT::TargetEndianness); + CBA.write(Section.HashBuckets->size(), ELFT::Endianness); // Write the index of the first symbol in the dynamic symbol table accessible // via the hash table. - CBA.write(Section.Header->SymNdx, ELFT::TargetEndianness); + CBA.write(Section.Header->SymNdx, ELFT::Endianness); // Write the number of words in the Bloom filter. As above, the "MaskWords" // property can be used to set this field to any value. if (Section.Header->MaskWords) - CBA.write(*Section.Header->MaskWords, ELFT::TargetEndianness); + CBA.write(*Section.Header->MaskWords, ELFT::Endianness); else - CBA.write(Section.BloomFilter->size(), ELFT::TargetEndianness); + CBA.write(Section.BloomFilter->size(), ELFT::Endianness); // Write the shift constant used by the Bloom filter. - CBA.write(Section.Header->Shift2, ELFT::TargetEndianness); + CBA.write(Section.Header->Shift2, ELFT::Endianness); // We've finished writing the header. Now write the Bloom filter. for (llvm::yaml::Hex64 Val : *Section.BloomFilter) - CBA.write(Val, ELFT::TargetEndianness); + CBA.write(Val, ELFT::Endianness); // Write an array of hash buckets. for (llvm::yaml::Hex32 Val : *Section.HashBuckets) - CBA.write(Val, ELFT::TargetEndianness); + CBA.write(Val, ELFT::Endianness); // Write an array of hash values. for (llvm::yaml::Hex32 Val : *Section.HashValues) - CBA.write(Val, ELFT::TargetEndianness); + CBA.write(Val, ELFT::Endianness); SHeader.sh_size = 16 /*Header size*/ + Section.BloomFilter->size() * sizeof(typename ELFT::uint) + diff --git a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h b/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h index 2e89463e68d5..94a44e3afccb 100644 --- a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h +++ b/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h @@ -113,7 +113,7 @@ void PrinterContext::printEHFrameHdr(const Elf_Phdr *EHFramePHdr) const { if (!Content) reportError(Content.takeError(), ObjF.getFileName()); - DataExtractor DE(*Content, ELFT::TargetEndianness == llvm::endianness::little, + DataExtractor DE(*Content, ELFT::Endianness == llvm::endianness::little, ELFT::Is64Bits ? 8 : 4); DictScope D(W, "Header"); @@ -186,10 +186,9 @@ void PrinterContext::printEHFrame(const Elf_Shdr *EHFrameShdr) const { // Construct DWARFDataExtractor to handle relocations ("PC Begin" fields). std::unique_ptr DICtx = DWARFContext::create( ObjF, DWARFContext::ProcessDebugRelocations::Process, nullptr); - DWARFDataExtractor DE(DICtx->getDWARFObj(), - DICtx->getDWARFObj().getEHFrameSection(), - ELFT::TargetEndianness == llvm::endianness::little, - ELFT::Is64Bits ? 8 : 4); + DWARFDataExtractor DE( + DICtx->getDWARFObj(), DICtx->getDWARFObj().getEHFrameSection(), + ELFT::Endianness == llvm::endianness::little, ELFT::Is64Bits ? 8 : 4); DWARFDebugFrame EHFrame(Triple::ArchType(ObjF.getArch()), /*IsEH=*/true, /*EHFrameAddress=*/Address); if (Error E = EHFrame.parse(DE)) diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index d1c05f437042..4b406ef12aec 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -74,6 +74,7 @@ using namespace llvm; using namespace llvm::object; +using namespace llvm::support; using namespace ELF; #define LLVM_READOBJ_ENUM_CASE(ns, enum) \ @@ -3419,13 +3420,13 @@ template void ELFDumper::printStackMap() const { return; } - if (Error E = StackMapParser::validateHeader( - *ContentOrErr)) { + if (Error E = + StackMapParser::validateHeader(*ContentOrErr)) { Warn(std::move(E)); return; } - prettyPrintStackMap(W, StackMapParser(*ContentOrErr)); + prettyPrintStackMap(W, StackMapParser(*ContentOrErr)); } template @@ -5145,7 +5146,7 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize, OS << format("", DataSize); return OS.str(); } - PrData = support::endian::read32(Data.data()); + PrData = endian::read32(Data.data()); if (PrData == 0) { OS << ""; return OS.str(); @@ -5169,7 +5170,7 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize, OS << format("", DataSize); return OS.str(); } - PrData = support::endian::read32(Data.data()); + PrData = endian::read32(Data.data()); if (PrData == 0) { OS << ""; return OS.str(); @@ -5195,7 +5196,7 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize, OS << format("", DataSize); return OS.str(); } - PrData = support::endian::read32(Data.data()); + PrData = endian::read32(Data.data()); if (PrData == 0) { OS << ""; return OS.str(); @@ -5374,10 +5375,8 @@ static bool printAArch64Note(raw_ostream &OS, uint32_t NoteType, return false; } - uint64_t Platform = - support::endian::read64(Desc.data() + 0); - uint64_t Version = - support::endian::read64(Desc.data() + 8); + uint64_t Platform = endian::read64(Desc.data() + 0); + uint64_t Version = endian::read64(Desc.data() + 8); OS << format("platform 0x%" PRIx64 ", version 0x%" PRIx64, Platform, Version); if (Desc.size() > 16) @@ -5457,16 +5456,14 @@ getFreeBSDNote(uint32_t NoteType, ArrayRef Desc, bool IsCore) { case ELF::NT_FREEBSD_ABI_TAG: if (Desc.size() != 4) return std::nullopt; - return FreeBSDNote{ - "ABI tag", - utostr(support::endian::read32(Desc.data()))}; + return FreeBSDNote{"ABI tag", + utostr(endian::read32(Desc.data()))}; case ELF::NT_FREEBSD_ARCH_TAG: return FreeBSDNote{"Arch tag", toStringRef(Desc).str()}; case ELF::NT_FREEBSD_FEATURE_CTL: { if (Desc.size() != 4) return std::nullopt; - unsigned Value = - support::endian::read32(Desc.data()); + unsigned Value = endian::read32(Desc.data()); std::string FlagsStr; raw_string_ostream OS(FlagsStr); printFlags(Value, ArrayRef(FreeBSDFeatureCtlFlags), OS); @@ -6053,7 +6050,7 @@ template void GNUELFDumper::printNotes() { } else if (Name == "CORE") { if (Type == ELF::NT_FILE) { DataExtractor DescExtractor( - Descriptor, ELFT::TargetEndianness == llvm::endianness::little, + Descriptor, ELFT::Endianness == llvm::endianness::little, sizeof(Elf_Addr)); if (Expected NoteOrErr = readCoreNote(DescExtractor)) { printCoreNote(OS, *NoteOrErr); @@ -7714,10 +7711,8 @@ static bool printAarch64NoteLLVMStyle(uint32_t NoteType, ArrayRef Desc, if (Desc.size() < 16) return false; - uint64_t platform = - support::endian::read64(Desc.data() + 0); - uint64_t version = - support::endian::read64(Desc.data() + 8); + uint64_t platform = endian::read64(Desc.data() + 0); + uint64_t version = endian::read64(Desc.data() + 8); W.printNumber("Platform", platform); W.printNumber("Version", version); @@ -7852,7 +7847,7 @@ template void LLVMELFDumper::printNotes() { } else if (Name == "CORE") { if (Type == ELF::NT_FILE) { DataExtractor DescExtractor( - Descriptor, ELFT::TargetEndianness == llvm::endianness::little, + Descriptor, ELFT::Endianness == llvm::endianness::little, sizeof(Elf_Addr)); if (Expected N = readCoreNote(DescExtractor)) { printCoreNoteLLVMStyle(*N, W); -- GitLab From 0f61051f541a5b8cfce25c84262dfdbadb9ca688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= Date: Thu, 28 Mar 2024 17:18:05 +0100 Subject: [PATCH 0002/1292] [clang][HLSL][SPRI-V] Add convergence intrinsics (#80680) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HLSL has wave operations and other kind of function which required the control flow to either be converged, or respect certain constraints as where and how to re-converge. At the HLSL level, the convergence are mostly obvious: the control flow is expected to re-converge at the end of a scope. Once translated to IR, HLSL scopes disapear. This means we need a way to communicate convergence restrictions down to the backend. For this, the SPIR-V backend uses convergence intrinsics. So this commit adds some code to generate convergence intrinsics when required. --------- Signed-off-by: Nathan Gauër --- clang/include/clang/Basic/Builtins.td | 6 ++ clang/lib/CodeGen/CGBuiltin.cpp | 93 +++++++++++++++++++ clang/lib/CodeGen/CGCall.cpp | 3 + clang/lib/CodeGen/CGLoopInfo.h | 7 +- clang/lib/CodeGen/CodeGenFunction.h | 19 ++++ clang/lib/Headers/hlsl/hlsl_intrinsics.h | 7 +- .../wave_get_lane_index_do_while.hlsl | 40 ++++++++ .../builtins/wave_get_lane_index_simple.hlsl | 14 +++ .../builtins/wave_get_lane_index_subcall.hlsl | 21 +++++ llvm/include/llvm/IR/IntrinsicInst.h | 13 +++ 10 files changed, 221 insertions(+), 2 deletions(-) create mode 100644 clang/test/CodeGenHLSL/builtins/wave_get_lane_index_do_while.hlsl create mode 100644 clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl create mode 100644 clang/test/CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 52c0dd52c28b..f421223ff087 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4599,6 +4599,12 @@ def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> { let Prototype = "unsigned int(bool)"; } +def HLSLWaveGetLaneIndex : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_wave_get_lane_index"]; + let Attributes = [NoThrow, Const]; + let Prototype = "unsigned int()"; +} + def HLSLClamp : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_elementwise_clamp"]; let Attributes = [NoThrow, Const]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 5ab5917c0c8d..287e763bad82 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -1131,8 +1131,92 @@ struct BitTest { static BitTest decodeBitTestBuiltin(unsigned BuiltinID); }; + +// Returns the first convergence entry/loop/anchor instruction found in |BB|. +// std::nullptr otherwise. +llvm::IntrinsicInst *getConvergenceToken(llvm::BasicBlock *BB) { + for (auto &I : *BB) { + auto *II = dyn_cast(&I); + if (II && isConvergenceControlIntrinsic(II->getIntrinsicID())) + return II; + } + return nullptr; +} + } // namespace +llvm::CallBase * +CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input, + llvm::Value *ParentToken) { + llvm::Value *bundleArgs[] = {ParentToken}; + llvm::OperandBundleDef OB("convergencectrl", bundleArgs); + auto Output = llvm::CallBase::addOperandBundle( + Input, llvm::LLVMContext::OB_convergencectrl, OB, Input); + Input->replaceAllUsesWith(Output); + Input->eraseFromParent(); + return Output; +} + +llvm::IntrinsicInst * +CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB, + llvm::Value *ParentToken) { + CGBuilderTy::InsertPoint IP = Builder.saveIP(); + Builder.SetInsertPoint(&BB->front()); + auto CB = Builder.CreateIntrinsic( + llvm::Intrinsic::experimental_convergence_loop, {}, {}); + Builder.restoreIP(IP); + + auto I = addConvergenceControlToken(CB, ParentToken); + return cast(I); +} + +llvm::IntrinsicInst * +CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) { + auto *BB = &F->getEntryBlock(); + auto *token = getConvergenceToken(BB); + if (token) + return token; + + // Adding a convergence token requires the function to be marked as + // convergent. + F->setConvergent(); + + CGBuilderTy::InsertPoint IP = Builder.saveIP(); + Builder.SetInsertPoint(&BB->front()); + auto I = Builder.CreateIntrinsic( + llvm::Intrinsic::experimental_convergence_entry, {}, {}); + assert(isa(I)); + Builder.restoreIP(IP); + + return cast(I); +} + +llvm::IntrinsicInst * +CodeGenFunction::getOrEmitConvergenceLoopToken(const LoopInfo *LI) { + assert(LI != nullptr); + + auto *token = getConvergenceToken(LI->getHeader()); + if (token) + return token; + + llvm::IntrinsicInst *PII = + LI->getParent() + ? emitConvergenceLoopToken( + LI->getHeader(), getOrEmitConvergenceLoopToken(LI->getParent())) + : getOrEmitConvergenceEntryToken(LI->getHeader()->getParent()); + + return emitConvergenceLoopToken(LI->getHeader(), PII); +} + +llvm::CallBase * +CodeGenFunction::addControlledConvergenceToken(llvm::CallBase *Input) { + llvm::Value *ParentToken = + LoopStack.hasInfo() + ? getOrEmitConvergenceLoopToken(&LoopStack.getInfo()) + : getOrEmitConvergenceEntryToken(Input->getFunction()); + return addConvergenceControlToken(Input, ParentToken); +} + BitTest BitTest::decodeBitTestBuiltin(unsigned BuiltinID) { switch (BuiltinID) { // Main portable variants. @@ -5809,6 +5893,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, {NDRange, Kernel, Block})); } + case Builtin::BI__builtin_hlsl_wave_get_lane_index: { + auto *CI = EmitRuntimeCall(CGM.CreateRuntimeFunction( + llvm::FunctionType::get(IntTy, {}, false), "__hlsl_wave_get_lane_index", + {}, false, true)); + if (getTarget().getTriple().isSPIRVLogical()) + CI = dyn_cast(addControlledConvergenceToken(CI)); + return RValue::get(CI); + } + case Builtin::BI__builtin_store_half: case Builtin::BI__builtin_store_halff: { Value *Val = EmitScalarExpr(E->getArg(0)); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index fb0078214b07..a5fe39633679 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -5715,6 +5715,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (!CI->getType()->isVoidTy()) CI->setName("call"); + if (getTarget().getTriple().isSPIRVLogical() && CI->isConvergent()) + CI = addControlledConvergenceToken(CI); + // Update largest vector width from the return type. LargestVectorWidth = std::max(LargestVectorWidth, getMaxVectorWidth(CI->getType())); diff --git a/clang/lib/CodeGen/CGLoopInfo.h b/clang/lib/CodeGen/CGLoopInfo.h index a1c8c7e5307f..0fe33b289130 100644 --- a/clang/lib/CodeGen/CGLoopInfo.h +++ b/clang/lib/CodeGen/CGLoopInfo.h @@ -110,6 +110,10 @@ public: /// been processed. void finish(); + /// Returns the first outer loop containing this loop if any, nullptr + /// otherwise. + const LoopInfo *getParent() const { return Parent; } + private: /// Loop ID metadata. llvm::TempMDTuple TempLoopID; @@ -291,12 +295,13 @@ public: /// Set no progress for the next loop pushed. void setMustProgress(bool P) { StagedAttrs.MustProgress = P; } -private: /// Returns true if there is LoopInfo on the stack. bool hasInfo() const { return !Active.empty(); } /// Return the LoopInfo for the current loop. HasInfo should be called /// first to ensure LoopInfo is present. const LoopInfo &getInfo() const { return *Active.back(); } + +private: /// The set of attributes that will be applied to the next pushed loop. LoopAttributes StagedAttrs; /// Stack of active loops. diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 8dd6da5f85f1..e2a7e28c8211 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4985,6 +4985,25 @@ public: llvm::Value *emitBoolVecConversion(llvm::Value *SrcVec, unsigned NumElementsDst, const llvm::Twine &Name = ""); + // Adds a convergence_ctrl token to |Input| and emits the required parent + // convergence instructions. + llvm::CallBase *addControlledConvergenceToken(llvm::CallBase *Input); + +private: + // Emits a convergence_loop instruction for the given |BB|, with |ParentToken| + // as it's parent convergence instr. + llvm::IntrinsicInst *emitConvergenceLoopToken(llvm::BasicBlock *BB, + llvm::Value *ParentToken); + // Adds a convergence_ctrl token with |ParentToken| as parent convergence + // instr to the call |Input|. + llvm::CallBase *addConvergenceControlToken(llvm::CallBase *Input, + llvm::Value *ParentToken); + // Find the convergence_entry instruction |F|, or emits ones if none exists. + // Returns the convergence instruction. + llvm::IntrinsicInst *getOrEmitConvergenceEntryToken(llvm::Function *F); + // Find the convergence_loop instruction for the loop defined by |LI|, or + // emits one if none exists. Returns the convergence instruction. + llvm::IntrinsicInst *getOrEmitConvergenceLoopToken(const LoopInfo *LI); private: llvm::MDNode *getRangeForLoadFromType(QualType Ty); diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index d47eab453f87..ecf20f6f1136 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1389,7 +1389,12 @@ float4 trunc(float4); /// true, across all active lanes in the current wave. _HLSL_AVAILABILITY(shadermodel, 6.0) _HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_count_bits) -uint WaveActiveCountBits(bool Val); +__attribute__((convergent)) uint WaveActiveCountBits(bool Val); + +/// \brief Returns the index of the current lane within the current wave. +_HLSL_AVAILABILITY(shadermodel, 6.0) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_get_lane_index) +__attribute__((convergent)) uint WaveGetLaneIndex(); } // namespace hlsl #endif //_HLSL_HLSL_INTRINSICS_H_ diff --git a/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_do_while.hlsl b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_do_while.hlsl new file mode 100644 index 000000000000..9481b0d60a27 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_do_while.hlsl @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK: define spir_func void @main() [[A0:#[0-9]+]] { +void main() { +// CHECK: entry: +// CHECK: %[[CT_ENTRY:[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: br label %[[LABEL_WHILE_COND:.+]] + int cond = 0; + +// CHECK: [[LABEL_WHILE_COND]]: +// CHECK: %[[CT_LOOP:[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %[[CT_ENTRY]]) ] +// CHECK: br label %[[LABEL_WHILE_BODY:.+]] + while (true) { + +// CHECK: [[LABEL_WHILE_BODY]]: +// CHECK: br i1 {{%.+}}, label %[[LABEL_IF_THEN:.+]], label %[[LABEL_IF_END:.+]] + +// CHECK: [[LABEL_IF_THEN]]: +// CHECK: call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %[[CT_LOOP]]) ] +// CHECK: br label %[[LABEL_WHILE_END:.+]] + if (cond == 2) { + uint index = WaveGetLaneIndex(); + break; + } + +// CHECK: [[LABEL_IF_END]]: +// CHECK: br label %[[LABEL_WHILE_COND]] + cond++; + } + +// CHECK: [[LABEL_WHILE_END]]: +// CHECK: ret void +} + +// CHECK-DAG: declare i32 @__hlsl_wave_get_lane_index() [[A1:#[0-9]+]] + +// CHECK-DAG: attributes [[A0]] = {{{.*}}convergent{{.*}}} +// CHECK-DAG: attributes [[A1]] = {{{.*}}convergent{{.*}}} + diff --git a/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl new file mode 100644 index 000000000000..8f52d81091c1 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK: define spir_func noundef i32 @_Z6test_1v() [[A0:#[0-9]+]] { +// CHECK: %[[CI:[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %[[CI]]) ] +uint test_1() { + return WaveGetLaneIndex(); +} + +// CHECK: declare i32 @__hlsl_wave_get_lane_index() [[A1:#[0-9]+]] + +// CHECK-DAG: attributes [[A0]] = { {{.*}}convergent{{.*}} } +// CHECK-DAG: attributes [[A1]] = { {{.*}}convergent{{.*}} } diff --git a/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl new file mode 100644 index 000000000000..379c8f118f52 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK: define spir_func noundef i32 @_Z6test_1v() [[A0:#[0-9]+]] { +// CHECK: %[[C1:[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %[[C1]]) ] +uint test_1() { + return WaveGetLaneIndex(); +} + +// CHECK-DAG: declare i32 @__hlsl_wave_get_lane_index() [[A1:#[0-9]+]] + +// CHECK: define spir_func noundef i32 @_Z6test_2v() [[A0]] { +// CHECK: %[[C2:[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: call spir_func noundef i32 @_Z6test_1v() [ "convergencectrl"(token %[[C2]]) ] +uint test_2() { + return test_1(); +} + +// CHECK-DAG: attributes [[A0]] = {{{.*}}convergent{{.*}}} +// CHECK-DAG: attributes [[A1]] = {{{.*}}convergent{{.*}}} diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h index c07b83a81a63..4f22720f1c55 100644 --- a/llvm/include/llvm/IR/IntrinsicInst.h +++ b/llvm/include/llvm/IR/IntrinsicInst.h @@ -1782,6 +1782,19 @@ public: static bool classof(const Value *V) { return isa(V) && classof(cast(V)); } + + // Returns the convergence intrinsic referenced by |I|'s convergencectrl + // attribute if any. + static IntrinsicInst *getParentConvergenceToken(Instruction *I) { + auto *CI = dyn_cast(I); + if (!CI) + return nullptr; + + auto Bundle = CI->getOperandBundle(llvm::LLVMContext::OB_convergencectrl); + assert(Bundle->Inputs.size() == 1 && + Bundle->Inputs[0]->getType()->isTokenTy()); + return dyn_cast(Bundle->Inputs[0].get()); + } }; } // end namespace llvm -- GitLab From 36b86438d7cd652bcac3fce51c1bdfad99536ec8 Mon Sep 17 00:00:00 2001 From: Farzon Lotfi <1802579+farzonl@users.noreply.github.com> Date: Thu, 28 Mar 2024 12:32:28 -0400 Subject: [PATCH 0003/1292] [DXIL] Implement pow lowering (#86733) closes #86179 - `DXILIntrinsicExpansion.cpp` - add the pow expansion to exp2(y*log2(x)) --- .../Target/DirectX/DXILIntrinsicExpansion.cpp | 23 +++++++++++++++ llvm/test/CodeGen/DirectX/pow-vec.ll | 15 ++++++++++ llvm/test/CodeGen/DirectX/pow.ll | 29 +++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 llvm/test/CodeGen/DirectX/pow-vec.ll create mode 100644 llvm/test/CodeGen/DirectX/pow.ll diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp index 3cc375edabde..3e2d10f5ee7a 100644 --- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp +++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp @@ -37,6 +37,7 @@ static bool isIntrinsicExpansion(Function &F) { case Intrinsic::exp: case Intrinsic::log: case Intrinsic::log10: + case Intrinsic::pow: case Intrinsic::dx_any: case Intrinsic::dx_clamp: case Intrinsic::dx_uclamp: @@ -197,6 +198,26 @@ static bool expandLog10Intrinsic(CallInst *Orig) { return expandLogIntrinsic(Orig, numbers::ln2f / numbers::ln10f); } +static bool expandPowIntrinsic(CallInst *Orig) { + + Value *X = Orig->getOperand(0); + Value *Y = Orig->getOperand(1); + Type *Ty = X->getType(); + IRBuilder<> Builder(Orig->getParent()); + Builder.SetInsertPoint(Orig); + + auto *Log2Call = + Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2"); + auto *Mul = Builder.CreateFMul(Log2Call, Y); + auto *Exp2Call = + Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {Mul}, nullptr, "elt.exp2"); + Exp2Call->setTailCall(Orig->isTailCall()); + Exp2Call->setAttributes(Orig->getAttributes()); + Orig->replaceAllUsesWith(Exp2Call); + Orig->eraseFromParent(); + return true; +} + static bool expandRcpIntrinsic(CallInst *Orig) { Value *X = Orig->getOperand(0); IRBuilder<> Builder(Orig->getParent()); @@ -270,6 +291,8 @@ static bool expandIntrinsic(Function &F, CallInst *Orig) { return expandLogIntrinsic(Orig); case Intrinsic::log10: return expandLog10Intrinsic(Orig); + case Intrinsic::pow: + return expandPowIntrinsic(Orig); case Intrinsic::dx_any: return expandAnyIntrinsic(Orig); case Intrinsic::dx_uclamp: diff --git a/llvm/test/CodeGen/DirectX/pow-vec.ll b/llvm/test/CodeGen/DirectX/pow-vec.ll new file mode 100644 index 000000000000..781fa5b8cb24 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/pow-vec.ll @@ -0,0 +1,15 @@ +; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s + +; Make sure dxil operation function calls for pow are generated for float and half. + +; CHECK-LABEL: pow_float4 +; CHECK: call <4 x float> @llvm.log2.v4f32(<4 x float> %a) +; CHECK: fmul <4 x float> %{{.*}}, %b +; CHECK: call <4 x float> @llvm.exp2.v4f32(<4 x float> %{{.*}}) +define noundef <4 x float> @pow_float4(<4 x float> noundef %a, <4 x float> noundef %b) { +entry: + %elt.pow = call <4 x float> @llvm.pow.v4f32(<4 x float> %a, <4 x float> %b) + ret <4 x float> %elt.pow +} + +declare <4 x float> @llvm.pow.v4f32(<4 x float>,<4 x float>) diff --git a/llvm/test/CodeGen/DirectX/pow.ll b/llvm/test/CodeGen/DirectX/pow.ll new file mode 100644 index 000000000000..25ce0fe731d0 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/pow.ll @@ -0,0 +1,29 @@ +; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK + +; Make sure dxil operation function calls for pow are generated. + +define noundef float @pow_float(float noundef %a, float noundef %b) { +entry: +; DOPCHECK: call float @dx.op.unary.f32(i32 23, float %a) +; EXPCHECK: call float @llvm.log2.f32(float %a) +; CHECK: fmul float %{{.*}}, %b +; DOPCHECK: call float @dx.op.unary.f32(i32 21, float %{{.*}}) +; EXPCHECK: call float @llvm.exp2.f32(float %{{.*}}) + %elt.pow = call float @llvm.pow.f32(float %a, float %b) + ret float %elt.pow +} + +define noundef half @pow_half(half noundef %a, half noundef %b) { +entry: +; DOPCHECK: call half @dx.op.unary.f16(i32 23, half %a) +; EXPCHECK: call half @llvm.log2.f16(half %a) +; CHECK: fmul half %{{.*}}, %b +; DOPCHECK: call half @dx.op.unary.f16(i32 21, half %{{.*}}) +; EXPCHECK: call half @llvm.exp2.f16(half %{{.*}}) + %elt.pow = call half @llvm.pow.f16(half %a, half %b) + ret half %elt.pow +} + +declare half @llvm.pow.f16(half,half) +declare float @llvm.pow.f32(float,float) -- GitLab From 39fe729502006f1b108828b75af8d63a27364f80 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Thu, 28 Mar 2024 09:41:08 -0700 Subject: [PATCH 0004/1292] [lld-macho] Ignore -no_warn_duplicate_libraries flag (#86303) This is a new ld64 flag (along with `-warn_duplicate_libraries`), where the warning is enabled by default, and it can be useful to ignore since it can be hard to dedup library flags across large builds. This doesn't ignore the enabling version since if someone manually passed that and lld didn't respect it, we probably want the user to know that. --- lld/MachO/Options.td | 6 ++++++ lld/test/MachO/silent-ignore.s | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td index 19f8509ba714..11458d92b3ab 100644 --- a/lld/MachO/Options.td +++ b/lld/MachO/Options.td @@ -1413,3 +1413,9 @@ def debug_variant : Flag<["-"], "debug_variant">, HelpText<"Do not warn about issues that are only problems for binaries shipping to customers.">, Flags<[HelpHidden]>, Group; + +// NOTE: This flag should be respected if -warn_duplicate_libraries is ever implemented. +def no_warn_duplicate_libraries : Flag<["-"], "no_warn_duplicate_libraries">, + HelpText<"Do not warn if the input contains duplicate library options.">, + Flags<[HelpHidden]>, + Group; diff --git a/lld/test/MachO/silent-ignore.s b/lld/test/MachO/silent-ignore.s index e57342c28a7a..58c3cc148f07 100644 --- a/lld/test/MachO/silent-ignore.s +++ b/lld/test/MachO/silent-ignore.s @@ -20,7 +20,7 @@ ## Check that we don't emit any warnings nor errors for these unimplemented flags. # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o -# RUN: %lld %t.o -o /dev/null -objc_abi_version 2 -debug_variant +# RUN: %lld %t.o -o /dev/null -objc_abi_version 2 -debug_variant -no_warn_duplicate_libraries .globl _main _main: -- GitLab From 706c1302f99d79af21ddf22e23c53d33329f225a Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Thu, 28 Mar 2024 09:43:03 -0700 Subject: [PATCH 0005/1292] [Dialect] Fix a warning This patch fixes: mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp:158:17: error: 'matchAndRewrite' overrides a member function but is not marked 'override' [-Werror,-Wsuggest-override] --- .../Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp b/mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp index 59aa43222175..ff003e486d21 100644 --- a/mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp +++ b/mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp @@ -156,7 +156,7 @@ struct DropRedundantRankExpansionOnInsertSliceOfExtractSlice final using OpRewritePattern::OpRewritePattern; LogicalResult matchAndRewrite(tensor::InsertSliceOp insertSliceOp, - PatternRewriter &rewriter) const { + PatternRewriter &rewriter) const override { auto extractSliceOp = insertSliceOp.getSource().getDefiningOp(); if (!extractSliceOp) { -- GitLab From 423832421b9b259612c3fe4169a6a6e1e2600f95 Mon Sep 17 00:00:00 2001 From: Charlie Barto Date: Thu, 28 Mar 2024 09:52:25 -0700 Subject: [PATCH 0006/1292] [asan][windows] Weak function interception support in instruction size decoder. (#86570) This makes it so we'll be able to decode the instructions used in the weak function stubs from https://github.com/llvm/llvm-project/pull/81677. This code doesn't technically require those changes. Co-authored-by: Amy Wishnousky --- compiler-rt/lib/interception/interception_win.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/compiler-rt/lib/interception/interception_win.cpp b/compiler-rt/lib/interception/interception_win.cpp index a04175ba1e4b..a638e66eccee 100644 --- a/compiler-rt/lib/interception/interception_win.cpp +++ b/compiler-rt/lib/interception/interception_win.cpp @@ -479,6 +479,8 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { switch (*(u8*)address) { case 0x90: // 90 : nop + case 0xC3: // C3 : ret (for small/empty function interception + case 0xCC: // CC : int 3 i.e. registering weak functions) return 1; case 0x50: // push eax / rax @@ -502,7 +504,6 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { // Cannot overwrite control-instruction. Return 0 to indicate failure. case 0xE9: // E9 XX XX XX XX : jmp