[llvm-branch-commits] [llvm] [HLSL] Add descriptor table metadata parsing (PR #142492)
https://github.com/joaosaffran edited https://github.com/llvm/llvm-project/pull/142492 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [SelectionDAG] Deal with POISON for INSERT_VECTOR_ELT/INSERT_SUBVECTOR (part 2) (PR #143103)
https://github.com/bjope updated https://github.com/llvm/llvm-project/pull/143103 From e2556d39b810a074048e143ec083e553cdf4135d Mon Sep 17 00:00:00 2001 From: Bjorn Pettersson Date: Tue, 3 Jun 2025 10:01:01 +0200 Subject: [PATCH] [SelectionDAG] Deal with POISON for INSERT_VECTOR_ELT/INSERT_SUBVECTOR (part 2) Add support in isGuaranteedNotToBeUndefOrPoison to avoid regressions seen after a previous commit fixing #141034. --- llvm/include/llvm/CodeGen/SelectionDAGNodes.h | 6 + .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 70 + llvm/test/CodeGen/Thumb2/mve-vld3.ll | 4 +- .../X86/merge-consecutive-loads-128.ll| 78 ++ llvm/test/CodeGen/X86/mmx-build-vector.ll | 255 +- llvm/test/CodeGen/X86/pr62286.ll | 14 +- .../CodeGen/X86/vector-shuffle-combining.ll | 21 +- llvm/test/CodeGen/X86/vector-trunc.ll | 140 ++ .../zero_extend_vector_inreg_of_broadcast.ll | 3 +- 9 files changed, 205 insertions(+), 386 deletions(-) diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h index 06217337a46f6..94ef11db3584e 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -1881,6 +1881,12 @@ LLVM_ABI SDValue peekThroughExtractSubvectors(SDValue V); /// If \p V is not a truncation, it is returned as-is. LLVM_ABI SDValue peekThroughTruncates(SDValue V); +/// Recursively peek through INSERT_VECTOR_ELT nodes, returning the source +/// vector operand of \p V, as long as \p V is an INSERT_VECTOR_ELT operation +/// that do not insert into any of the demanded vector elts. +LLVM_ABI SDValue peekThroughInsertVectorElt(SDValue V, +const APInt &DemandedElts); + /// Returns true if \p V is a bitwise not operation. Assumes that an all ones /// constant is canonicalized to be operand 1. LLVM_ABI bool isBitwiseNot(SDValue V, bool AllowUndefs = false); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 5ec1ee30bcf4b..8fcfdc344fff2 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -5454,6 +5454,59 @@ bool SelectionDAG::isGuaranteedNotToBeUndefOrPoison(SDValue Op, } return true; + case ISD::INSERT_SUBVECTOR: { +if (Op.getValueType().isScalableVector()) + break; +SDValue Src = Op.getOperand(0); +SDValue Sub = Op.getOperand(1); +uint64_t Idx = Op.getConstantOperandVal(2); +unsigned NumSubElts = Sub.getValueType().getVectorNumElements(); +APInt DemandedSubElts = DemandedElts.extractBits(NumSubElts, Idx); +APInt DemandedSrcElts = DemandedElts; +DemandedSrcElts.clearBits(Idx, Idx + NumSubElts); + +if (!!DemandedSubElts && !isGuaranteedNotToBeUndefOrPoison( + Sub, DemandedSubElts, PoisonOnly, Depth + 1)) + return false; +if (!!DemandedSrcElts && !isGuaranteedNotToBeUndefOrPoison( + Src, DemandedSrcElts, PoisonOnly, Depth + 1)) + return false; +return true; + } + + case ISD::INSERT_VECTOR_ELT: { +SDValue InVec = Op.getOperand(0); +SDValue InVal = Op.getOperand(1); +SDValue EltNo = Op.getOperand(2); +EVT VT = InVec.getValueType(); +auto *IndexC = dyn_cast(EltNo); +if (IndexC && VT.isFixedLengthVector() && +IndexC->getZExtValue() < VT.getVectorNumElements()) { + if (DemandedElts[IndexC->getZExtValue()] && + !isGuaranteedNotToBeUndefOrPoison(InVal, PoisonOnly, Depth + 1)) +return false; + APInt InVecDemandedElts = DemandedElts; + InVecDemandedElts.clearBit(IndexC->getZExtValue()); + if (!!InVecDemandedElts && + !isGuaranteedNotToBeUndefOrPoison( + peekThroughInsertVectorElt(InVec, InVecDemandedElts), + InVecDemandedElts, PoisonOnly, Depth + 1)) +return false; + return true; +} +break; + } + + case ISD::SCALAR_TO_VECTOR: +// If only demanding upper (undef) elements. +if (DemandedElts.ugt(1)) + return PoisonOnly; +// If only demanding element 0, or only considering poison. +if (PoisonOnly || DemandedElts == 0) + return isGuaranteedNotToBeUndefOrPoison(Op.getOperand(0), PoisonOnly, + Depth + 1); +return false; + case ISD::SPLAT_VECTOR: return isGuaranteedNotToBeUndefOrPoison(Op.getOperand(0), PoisonOnly, Depth + 1); @@ -12471,6 +12524,23 @@ SDValue llvm::peekThroughTruncates(SDValue V) { return V; } +SDValue llvm::peekThroughInsertVectorElt(SDValue V, const APInt &DemandedElts) { + while (V.getOpcode() == ISD::INSERT_VECTOR_ELT) { +SDValue InVec = V.getOperand(0); +SDValue EltNo = V.getOperand(2); +EVT VT = InVec.getValueType(); +auto *IndexC = dyn_cast(EltNo);
[llvm-branch-commits] [llvm] TableGen: Handle setting runtime libcall calling conventions (PR #144980)
https://github.com/arsenm ready_for_review https://github.com/llvm/llvm-project/pull/144980 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-doc] add support for concepts (PR #144430)
https://github.com/evelez7 ready_for_review https://github.com/llvm/llvm-project/pull/144430 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] Add a GUIDLIST table to bitcode (PR #139497)
https://github.com/orodley updated https://github.com/llvm/llvm-project/pull/139497 >From bf53f8766fe4e5d4421dea919bf2abb8d4b13004 Mon Sep 17 00:00:00 2001 From: Owen Rodley Date: Mon, 12 May 2025 15:50:22 +1000 Subject: [PATCH] Add a GUIDLIST table to bitcode --- llvm/include/llvm/Bitcode/LLVMBitCodes.h | 3 +++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 11 +++--- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 25 +++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index b362a88963f6c..8fa3a89536d75 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -120,6 +120,9 @@ enum ModuleCodes { // IFUNC: [ifunc value type, addrspace, resolver val#, linkage, visibility] MODULE_CODE_IFUNC = 18, + + // GUIDLIST: [n x i64] + MODULE_CODE_GUIDLIST = 19, }; /// PARAMATTR blocks have code for defining a parameter attribute set. diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index fde934fbb3cf1..3994f8469078b 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -976,6 +976,9 @@ class ModuleSummaryIndexBitcodeReader : public BitcodeReaderBase { /// the CallStackRadixTreeBuilder class in ProfileData/MemProf.h for format. std::vector RadixArray; + // A table which maps ValueID to the GUID for that value. + std::vector DefinedGUIDs; + public: ModuleSummaryIndexBitcodeReader( BitstreamCursor Stream, StringRef Strtab, ModuleSummaryIndex &TheIndex, @@ -7162,9 +7165,7 @@ ModuleSummaryIndexBitcodeReader::getValueInfoFromValueId(unsigned ValueId) { void ModuleSummaryIndexBitcodeReader::setValueGUID( uint64_t ValueID, StringRef ValueName, GlobalValue::LinkageTypes Linkage, StringRef SourceFileName) { - std::string GlobalId = - GlobalValue::getGlobalIdentifier(ValueName, Linkage, SourceFileName); - auto ValueGUID = GlobalValue::getGUIDAssumingExternalLinkage(GlobalId); + auto ValueGUID = DefinedGUIDs[ValueID]; auto OriginalNameID = ValueGUID; if (GlobalValue::isLocalLinkage(Linkage)) OriginalNameID = GlobalValue::getGUIDAssumingExternalLinkage(ValueName); @@ -7387,6 +7388,10 @@ Error ModuleSummaryIndexBitcodeReader::parseModule() { // was historically always the start of the regular bitcode header. VSTOffset = Record[0] - 1; break; +// MODULE_CODE_GUIDLIST: [i64 x N] +case bitc::MODULE_CODE_GUIDLIST: + llvm::append_range(DefinedGUIDs, Record); + break; // v1 GLOBALVAR: [pointer type, isconst, initid, linkage, ...] // v1 FUNCTION: [type, callingconv, isproto, linkage, ...] // v1 ALIAS: [alias type, addrspace, aliasee val#, linkage, ...] diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 628b939af19ce..a72f55bd7d0d1 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -244,6 +244,7 @@ class ModuleBitcodeWriterBase : public BitcodeWriterBase { protected: void writePerModuleGlobalValueSummary(); + void writeGUIDList(); private: void writePerModuleFunctionSummaryRecord( @@ -1583,6 +1584,8 @@ void ModuleBitcodeWriter::writeModuleInfo() { Vals.clear(); } + writeGUIDList(); + // Emit the global variable information. for (const GlobalVariable &GV : M.globals()) { unsigned AbbrevToUse = 0; @@ -4790,6 +4793,26 @@ void ModuleBitcodeWriterBase::writePerModuleGlobalValueSummary() { Stream.ExitBlock(); } +void ModuleBitcodeWriterBase::writeGUIDList() { + std::vector GUIDs; + GUIDs.reserve(M.global_size() + M.size() + M.alias_size()); + + for (const GlobalValue &GV : M.global_objects()) { +if (GV.isDeclaration()) { + GUIDs.push_back( + GlobalValue::getGUIDAssumingExternalLinkage(GV.getName())); +} else { + GUIDs.push_back(GV.getGUID()); +} + } + for (const GlobalAlias &GA : M.aliases()) { +// Equivalent to the above loop, as GlobalAliases are always definitions. +GUIDs.push_back(GA.getGUID()); + } + + Stream.EmitRecord(bitc::MODULE_CODE_GUIDLIST, GUIDs); +} + /// Emit the combined summary section into the combined index file. void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { Stream.EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 4); @@ -5578,6 +5601,8 @@ void ThinLinkBitcodeWriter::writeSimplifiedModuleInfo() { Vals.clear(); } + writeGUIDList(); + // Emit the global variable information. for (const GlobalVariable &GV : M.globals()) { // GLOBALVAR: [strtab offset, strtab size, 0, 0, 0, linkage] ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailm
[llvm-branch-commits] [llvm] Add a GUIDLIST table to bitcode (PR #139497)
https://github.com/orodley updated https://github.com/llvm/llvm-project/pull/139497 >From bf53f8766fe4e5d4421dea919bf2abb8d4b13004 Mon Sep 17 00:00:00 2001 From: Owen Rodley Date: Mon, 12 May 2025 15:50:22 +1000 Subject: [PATCH] Add a GUIDLIST table to bitcode --- llvm/include/llvm/Bitcode/LLVMBitCodes.h | 3 +++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 11 +++--- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 25 +++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index b362a88963f6c..8fa3a89536d75 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -120,6 +120,9 @@ enum ModuleCodes { // IFUNC: [ifunc value type, addrspace, resolver val#, linkage, visibility] MODULE_CODE_IFUNC = 18, + + // GUIDLIST: [n x i64] + MODULE_CODE_GUIDLIST = 19, }; /// PARAMATTR blocks have code for defining a parameter attribute set. diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index fde934fbb3cf1..3994f8469078b 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -976,6 +976,9 @@ class ModuleSummaryIndexBitcodeReader : public BitcodeReaderBase { /// the CallStackRadixTreeBuilder class in ProfileData/MemProf.h for format. std::vector RadixArray; + // A table which maps ValueID to the GUID for that value. + std::vector DefinedGUIDs; + public: ModuleSummaryIndexBitcodeReader( BitstreamCursor Stream, StringRef Strtab, ModuleSummaryIndex &TheIndex, @@ -7162,9 +7165,7 @@ ModuleSummaryIndexBitcodeReader::getValueInfoFromValueId(unsigned ValueId) { void ModuleSummaryIndexBitcodeReader::setValueGUID( uint64_t ValueID, StringRef ValueName, GlobalValue::LinkageTypes Linkage, StringRef SourceFileName) { - std::string GlobalId = - GlobalValue::getGlobalIdentifier(ValueName, Linkage, SourceFileName); - auto ValueGUID = GlobalValue::getGUIDAssumingExternalLinkage(GlobalId); + auto ValueGUID = DefinedGUIDs[ValueID]; auto OriginalNameID = ValueGUID; if (GlobalValue::isLocalLinkage(Linkage)) OriginalNameID = GlobalValue::getGUIDAssumingExternalLinkage(ValueName); @@ -7387,6 +7388,10 @@ Error ModuleSummaryIndexBitcodeReader::parseModule() { // was historically always the start of the regular bitcode header. VSTOffset = Record[0] - 1; break; +// MODULE_CODE_GUIDLIST: [i64 x N] +case bitc::MODULE_CODE_GUIDLIST: + llvm::append_range(DefinedGUIDs, Record); + break; // v1 GLOBALVAR: [pointer type, isconst, initid, linkage, ...] // v1 FUNCTION: [type, callingconv, isproto, linkage, ...] // v1 ALIAS: [alias type, addrspace, aliasee val#, linkage, ...] diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 628b939af19ce..a72f55bd7d0d1 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -244,6 +244,7 @@ class ModuleBitcodeWriterBase : public BitcodeWriterBase { protected: void writePerModuleGlobalValueSummary(); + void writeGUIDList(); private: void writePerModuleFunctionSummaryRecord( @@ -1583,6 +1584,8 @@ void ModuleBitcodeWriter::writeModuleInfo() { Vals.clear(); } + writeGUIDList(); + // Emit the global variable information. for (const GlobalVariable &GV : M.globals()) { unsigned AbbrevToUse = 0; @@ -4790,6 +4793,26 @@ void ModuleBitcodeWriterBase::writePerModuleGlobalValueSummary() { Stream.ExitBlock(); } +void ModuleBitcodeWriterBase::writeGUIDList() { + std::vector GUIDs; + GUIDs.reserve(M.global_size() + M.size() + M.alias_size()); + + for (const GlobalValue &GV : M.global_objects()) { +if (GV.isDeclaration()) { + GUIDs.push_back( + GlobalValue::getGUIDAssumingExternalLinkage(GV.getName())); +} else { + GUIDs.push_back(GV.getGUID()); +} + } + for (const GlobalAlias &GA : M.aliases()) { +// Equivalent to the above loop, as GlobalAliases are always definitions. +GUIDs.push_back(GA.getGUID()); + } + + Stream.EmitRecord(bitc::MODULE_CODE_GUIDLIST, GUIDs); +} + /// Emit the combined summary section into the combined index file. void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { Stream.EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 4); @@ -5578,6 +5601,8 @@ void ThinLinkBitcodeWriter::writeSimplifiedModuleInfo() { Vals.clear(); } + writeGUIDList(); + // Emit the global variable information. for (const GlobalVariable &GV : M.globals()) { // GLOBALVAR: [strtab offset, strtab size, 0, 0, 0, linkage] ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailm
[llvm-branch-commits] [clang-tools-extra] [clang-doc] add support for concepts (PR #144430)
https://github.com/evelez7 updated https://github.com/llvm/llvm-project/pull/144430 >From 2febdc89f0c2b2f9abe47415f5c115ad8305ed2d Mon Sep 17 00:00:00 2001 From: Erick Velez Date: Mon, 16 Jun 2025 10:50:35 -0700 Subject: [PATCH] add serializeArray for infos with URLs --- clang-tools-extra/clang-doc/BitcodeReader.cpp | 72 +++ clang-tools-extra/clang-doc/BitcodeWriter.cpp | 44 ++- clang-tools-extra/clang-doc/BitcodeWriter.h | 12 +- clang-tools-extra/clang-doc/HTMLGenerator.cpp | 4 + .../clang-doc/HTMLMustacheGenerator.cpp | 2 + clang-tools-extra/clang-doc/JSONGenerator.cpp | 50 clang-tools-extra/clang-doc/MDGenerator.cpp | 5 + clang-tools-extra/clang-doc/Mapper.cpp| 4 + clang-tools-extra/clang-doc/Mapper.h | 1 + .../clang-doc/Representation.cpp | 20 +++ clang-tools-extra/clang-doc/Representation.h | 26 +++- clang-tools-extra/clang-doc/Serialize.cpp | 90 + clang-tools-extra/clang-doc/Serialize.h | 4 + clang-tools-extra/clang-doc/YAMLGenerator.cpp | 2 + .../test/clang-doc/json/class-requires.cpp| 18 +-- .../clang-doc/json/compound-constraints.cpp | 121 ++ .../test/clang-doc/json/concept.cpp | 48 +++ .../test/clang-doc/json/function-requires.cpp | 36 +++--- .../unittests/clang-doc/BitcodeTest.cpp | 2 + 19 files changed, 505 insertions(+), 56 deletions(-) create mode 100644 clang-tools-extra/test/clang-doc/json/compound-constraints.cpp diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp index 35058abab0663..5b70280e7dba8 100644 --- a/clang-tools-extra/clang-doc/BitcodeReader.cpp +++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp @@ -92,6 +92,7 @@ static llvm::Error decodeRecord(const Record &R, InfoType &Field, case InfoType::IT_default: case InfoType::IT_enum: case InfoType::IT_typedef: + case InfoType::IT_concept: Field = IT; return llvm::Error::success(); } @@ -108,6 +109,7 @@ static llvm::Error decodeRecord(const Record &R, FieldId &Field, case FieldId::F_type: case FieldId::F_child_namespace: case FieldId::F_child_record: + case FieldId::F_concept: case FieldId::F_default: Field = F; return llvm::Error::success(); @@ -391,6 +393,29 @@ static llvm::Error parseRecord(const Record &R, unsigned ID, "invalid field for TemplateParamInfo"); } +static llvm::Error parseRecord(const Record &R, unsigned ID, + llvm::StringRef Blob, ConceptInfo *I) { + switch (ID) { + case CONCEPT_USR: +return decodeRecord(R, I->USR, Blob); + case CONCEPT_NAME: +return decodeRecord(R, I->Name, Blob); + case CONCEPT_IS_TYPE: +return decodeRecord(R, I->IsType, Blob); + case CONCEPT_CONSTRAINT_EXPRESSION: +return decodeRecord(R, I->ConstraintExpression, Blob); + } + llvm_unreachable("invalid field for ConceptInfo"); +} + +static llvm::Error parseRecord(const Record &R, unsigned ID, + llvm::StringRef Blob, ConstraintInfo *I) { + if (ID == CONSTRAINT_EXPRESSION) +return decodeRecord(R, I->Expression, Blob); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid field for ConstraintInfo"); +} + template static llvm::Expected getCommentInfo(T I) { return llvm::createStringError(llvm::inconvertibleErrorCode(), "invalid type cannot contain CommentInfo"); @@ -429,6 +454,10 @@ template <> llvm::Expected getCommentInfo(CommentInfo *I) { return I->Children.back().get(); } +template <> llvm::Expected getCommentInfo(ConceptInfo *I) { + return &I->Description.emplace_back(); +} + // When readSubBlock encounters a TypeInfo sub-block, it calls addTypeInfo on // the parent block to set it. The template specializations define what to do // for each supported parent block. @@ -584,6 +613,18 @@ template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) { } } +template <> +llvm::Error addReference(ConstraintInfo *I, Reference &&R, FieldId F) { + switch (F) { + case FieldId::F_concept: +I->ConceptRef = std::move(R); +return llvm::Error::success(); + default: +return llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid type cannot contain Reference"); + } +} + template static void addChild(T I, ChildInfoType &&R) { llvm::errs() << "invalid child type for info"; @@ -600,6 +641,9 @@ template <> void addChild(NamespaceInfo *I, EnumInfo &&R) { template <> void addChild(NamespaceInfo *I, TypedefInfo &&R) { I->Children.Typedefs.emplace_back(std::move(R)); } +template <> void addChild(NamespaceInfo *I, ConceptInfo &&R) { + I->Children.Concepts.emplace_back(std::move(R)); +} // Record children: template <> void addChild(RecordInfo *I, FunctionInfo &&R) { @@ -
[llvm-branch-commits] [llvm] [DirectX] Improve error handling and validation in root signature parsing (PR #144577)
https://github.com/joaosaffran edited https://github.com/llvm/llvm-project/pull/144577 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [DirectX] Improve error accumulation in root signature parsing (PR #144465)
https://github.com/joaosaffran edited https://github.com/llvm/llvm-project/pull/144465 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] RuntimeLibcalls: Associate calling convention with libcall impls (PR #144979)
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/144979 Instead of associating the libcall with the RTLIB::Libcall, put it into a table indexed by the RTLIB::LibcallImpl. The LibcallImpls should contain all ABI details for a particular implementation, not the abstract Libcall. In the future the wrappers in terms of the RTLIB::Libcall should be removed. >From 191a077fa9f39768f64abe6e5f017630cfb867f8 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Tue, 17 Jun 2025 16:25:50 +0900 Subject: [PATCH] RuntimeLibcalls: Associate calling convention with libcall impls Instead of associating the libcall with the RTLIB::Libcall, put it into a table indexed by the RTLIB::LibcallImpl. The LibcallImpls should contain all ABI details for a particular implementation, not the abstract Libcall. In the future the wrappers in terms of the RTLIB::Libcall should be removed. --- llvm/include/llvm/CodeGen/TargetLowering.h| 16 - llvm/include/llvm/IR/RuntimeLibcalls.h| 32 ++--- llvm/lib/IR/RuntimeLibcalls.cpp | 70 +++ llvm/lib/Target/ARM/ARMISelLowering.cpp | 24 --- llvm/lib/Target/Lanai/LanaiISelLowering.cpp | 4 +- llvm/lib/Target/MSP430/MSP430ISelLowering.cpp | 3 +- 6 files changed, 98 insertions(+), 51 deletions(-) diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index 69ae4f80297d5..fa08eb64642de 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -3562,6 +3562,11 @@ class LLVM_ABI TargetLoweringBase { Libcalls.setLibcallImpl(Call, Impl); } + /// Get the libcall impl routine name for the specified libcall. + RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const { +return Libcalls.getLibcallImpl(Call); + } + /// Get the libcall routine name for the specified libcall. const char *getLibcallName(RTLIB::Libcall Call) const { return Libcalls.getLibcallName(Call); @@ -3584,11 +3589,18 @@ class LLVM_ABI TargetLoweringBase { } /// Set the CallingConv that should be used for the specified libcall. - void setLibcallCallingConv(RTLIB::Libcall Call, CallingConv::ID CC) { -Libcalls.setLibcallCallingConv(Call, CC); + void setLibcallImplCallingConv(RTLIB::LibcallImpl Call, CallingConv::ID CC) { +Libcalls.setLibcallImplCallingConv(Call, CC); + } + + /// Get the CallingConv that should be used for the specified libcall + /// implementation. + CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const { +return Libcalls.getLibcallImplCallingConv(Call); } /// Get the CallingConv that should be used for the specified libcall. + // FIXME: Remove this wrapper and directly use the used LibcallImpl CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const { return Libcalls.getLibcallCallingConv(Call); } diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h index d69c23753da7a..dce16ab99171f 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.h +++ b/llvm/include/llvm/IR/RuntimeLibcalls.h @@ -37,6 +37,10 @@ template <> struct enum_iteration_traits { static constexpr bool is_iterable = true; }; +template <> struct enum_iteration_traits { + static constexpr bool is_iterable = true; +}; + namespace RTLIB { // Return an iterator over all Libcall values. @@ -44,6 +48,10 @@ static inline auto libcalls() { return enum_seq(static_cast(0), RTLIB::UNKNOWN_LIBCALL); } +static inline auto libcall_impls() { + return enum_seq(static_cast(1), RTLIB::NumLibcallImpls); +} + /// A simple container for information about the supported runtime calls. struct RuntimeLibcallsInfo { explicit RuntimeLibcallsInfo( @@ -76,16 +84,21 @@ struct RuntimeLibcallsInfo { return LibcallImpls[Call]; } - /// Set the CallingConv that should be used for the specified libcall. - // FIXME: This should be a function of RTLIB::LibcallImpl - void setLibcallCallingConv(RTLIB::Libcall Call, CallingConv::ID CC) { -LibcallCallingConvs[Call] = CC; + /// Set the CallingConv that should be used for the specified libcall + /// implementation + void setLibcallImplCallingConv(RTLIB::LibcallImpl Call, CallingConv::ID CC) { +LibcallImplCallingConvs[Call] = CC; } - /// Get the CallingConv that should be used for the specified libcall. - // FIXME: This should be a function of RTLIB::LibcallImpl + // FIXME: Remove this wrapper in favor of directly using + // getLibcallImplCallingConv CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const { -return LibcallCallingConvs[Call]; +return LibcallImplCallingConvs[LibcallImpls[Call]]; + } + + /// Get the CallingConv that should be used for the specified libcall. + CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const { +return LibcallImplCallingConvs[Call]; } ArrayRef getLibcallImpls() const { @@ -130,8 +143,9 @
[llvm-branch-commits] [llvm] TableGen: Allow defining sets of runtime libraries (PR #144978)
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/144978 Add a way to define a SystemLibrary for a complete set of libcalls, subdivided by a predicate based on the triple. Libraries can be defined using dag set operations, and the prior default set can be subtracted from and added to (though I think eventually all targets should move to explicit opt-ins. We're still doing things like reporting ppcf128 libcalls as available dy default on all targets). Start migrating some of the easier targets to only use the new system. Targets that don't define a SystemLibrary are still manually mutating a table set to the old defaults. As a side effect, also fixes a missing # prefix for the windows arm64ec case when emitting __arm_sc libcalls. >From f5f142d6ecc0c42974023c1eb6294004ad192272 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sat, 7 Jun 2025 20:57:31 +0900 Subject: [PATCH] TableGen: Allow defining sets of runtime libraries Add a way to define a SystemLibrary for a complete set of libcalls, subdivided by a predicate based on the triple. Libraries can be defined using dag set operations, and the prior default set can be subtracted from and added to (though I think eventually all targets should move to explicit opt-ins. We're still doing things like reporting ppcf128 libcalls as available dy default on all targets). Start migrating some of the easier targets to only use the new system. Targets that don't define a SystemLibrary are still manually mutating a table set to the old defaults. --- llvm/include/llvm/IR/RuntimeLibcalls.h| 10 +- llvm/include/llvm/IR/RuntimeLibcalls.td | 493 +++--- llvm/include/llvm/IR/RuntimeLibcallsImpl.td | 36 ++ llvm/include/llvm/TableGen/SetTheory.td | 27 + llvm/lib/IR/RuntimeLibcalls.cpp | 127 + .../RuntimeLibcallEmitter-conflict-warning.td | 60 +++ ...eLibcallEmitter-nested-predicates-error.td | 18 + llvm/test/TableGen/RuntimeLibcallEmitter.td | 185 ++- .../TableGen/Basic/RuntimeLibcallsEmitter.cpp | 351 + 9 files changed, 889 insertions(+), 418 deletions(-) create mode 100644 llvm/include/llvm/TableGen/SetTheory.td create mode 100644 llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td create mode 100644 llvm/test/TableGen/RuntimeLibcallEmitter-nested-predicates-error.td diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h index 912715fbf6b19..d69c23753da7a 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.h +++ b/llvm/include/llvm/IR/RuntimeLibcalls.h @@ -52,7 +52,6 @@ struct RuntimeLibcallsInfo { FloatABI::ABIType FloatABI = FloatABI::Default, EABI EABIVersion = EABI::Default) { initSoftFloatCmpLibcallPredicates(); -initDefaultLibCallImpls(); initLibcalls(TT, ExceptionModel, FloatABI, EABIVersion); } @@ -97,6 +96,7 @@ struct RuntimeLibcallsInfo { /// Get the comparison predicate that's to be used to test the result of the /// comparison libcall against zero. This should only be used with /// floating-point compare libcalls. + // FIXME: This should be a function of RTLIB::LibcallImpl CmpInst::Predicate getSoftFloatCmpLibcallPredicate(RTLIB::Libcall Call) const { return SoftFloatCompareLibcallPredicates[Call]; @@ -172,13 +172,7 @@ struct RuntimeLibcallsInfo { void initDefaultLibCallImpls(); /// Generated by tablegen. - void setPPCLibCallNameOverrides(); - - /// Generated by tablegen. - void setZOSLibCallNameOverrides(); - - /// Generated by tablegen. - void setWindowsArm64LibCallNameOverrides(); + void setTargetRuntimeLibcallSets(const Triple &TT); void initSoftFloatCmpLibcallPredicates(); diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index 1d9f02dcf8ba8..e24b4c928b421 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -891,6 +891,17 @@ def calloc : RuntimeLibcallImpl; } // End let IsDefault = true } // End defset DefaultRuntimeLibcallImpls +defvar DefaultLibCalls = +!foreach(entry, DefaultRuntimeLibcallImpls, entry.Provides); + +defvar DefaultRuntimeLibcallImpls_f128 = +!filter(entry, DefaultRuntimeLibcallImpls, +!match(!cast(entry.Provides), "_F128")); + +defvar DefaultRuntimeLibcallImpls_atomic = +!filter(entry, DefaultRuntimeLibcallImpls, +!match(!cast(entry.Provides), "ATOMIC")); + // // Define implementation other libcalls // @@ -915,58 +926,61 @@ def _Unwind_SjLj_Resume : RuntimeLibcallImpl; // F128 libm Runtime Libcalls //===--===// -def logf128 : RuntimeLibcallImpl; -def log2f128 : RuntimeLibcallImpl; -def log10f128 : RuntimeLibcallImpl; -def expf128 : RuntimeLibcallImpl; -def e
[llvm-branch-commits] [llvm] TableGen: Add runtime libcall backend (PR #144972)
arsenm wrote: > [!WARNING] > This pull request is not mergeable via GitHub because a downstack PR is > open. Once all requirements are satisfied, merge this PR as a stack href="https://app.graphite.dev/github/pr/llvm/llvm-project/144972?utm_source=stack-comment-downstack-mergeability-warning"; > >on Graphite. > https://graphite.dev/docs/merge-pull-requests";>Learn more * **#144979** https://app.graphite.dev/github/pr/llvm/llvm-project/144979?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144978** https://app.graphite.dev/github/pr/llvm/llvm-project/144978?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144977** https://app.graphite.dev/github/pr/llvm/llvm-project/144977?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144976** https://app.graphite.dev/github/pr/llvm/llvm-project/144976?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144975** https://app.graphite.dev/github/pr/llvm/llvm-project/144975?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144974** https://app.graphite.dev/github/pr/llvm/llvm-project/144974?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144973** https://app.graphite.dev/github/pr/llvm/llvm-project/144973?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144972** https://app.graphite.dev/github/pr/llvm/llvm-project/144972?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> 👈 https://app.graphite.dev/github/pr/llvm/llvm-project/144972?utm_source=stack-comment-view-in-graphite"; target="_blank">(View in Graphite) * **#143836** https://app.graphite.dev/github/pr/llvm/llvm-project/143836?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * `main` This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn more about https://stacking.dev/?utm_source=stack-comment";>stacking. https://github.com/llvm/llvm-project/pull/144972 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] TableGen: Handle setting runtime libcall calling conventions (PR #144980)
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/144980 Allow associating a non-default CallingConv with a set of library functions, and applying a default for a SystemLibrary. I also wanted to be able to apply a default calling conv to a RuntimeLibcallImpl, but that turned out to be annoying so leave it for later. >From f847af321a1fed66af72cd32e48aa3925d74805b Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Fri, 13 Jun 2025 15:54:41 +0900 Subject: [PATCH] TableGen: Handle setting runtime libcall calling conventions Allow associating a non-default CallingConv with a set of library functions, and applying a default for a SystemLibrary. I also wanted to be able to apply a default calling conv to a RuntimeLibcallImpl, but that turned out to be annoying so leave it for later. --- llvm/include/llvm/IR/RuntimeLibcalls.td | 140 +++-- llvm/include/llvm/IR/RuntimeLibcallsImpl.td | 26 +++- llvm/lib/IR/RuntimeLibcalls.cpp | 141 -- .../RuntimeLibcallEmitter-calling-conv.td | 85 +++ llvm/test/TableGen/RuntimeLibcallEmitter.td | 19 ++- .../TableGen/Basic/RuntimeLibcallsEmitter.cpp | 111 +++--- 6 files changed, 344 insertions(+), 178 deletions(-) create mode 100644 llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index e24b4c928b421..03ac9f5926f87 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -1254,11 +1254,12 @@ def __gnu_h2f_ieee : RuntimeLibcallImpl; //===--===// // Several of the runtime library functions use a special calling conv -def __divmodqi4 : RuntimeLibcallImpl; // CallingConv::AVR_BUILTIN -def __divmodhi4 : RuntimeLibcallImpl; // CallingConv::AVR_BUILTIN +def __divmodqi4 : RuntimeLibcallImpl; +def __divmodhi4 : RuntimeLibcallImpl; +def __udivmodqi4 : RuntimeLibcallImpl; +def __udivmodhi4 : RuntimeLibcallImpl; + //def __divmodsi4 : RuntimeLibcallImpl; -def __udivmodqi4 : RuntimeLibcallImpl; // CallingConv::AVR_BUILTIN -def __udivmodhi4 : RuntimeLibcallImpl; // CallingConv::AVR_BUILTIN //def __udivmodsi4 : RuntimeLibcallImpl; // Standard sinf/cosf name replaced with "sin" and "cos". Define a @@ -1284,9 +1285,12 @@ def AVRSystemLibrary // Standard f64 names are replaced sin, cos, sinf, cosf), - __divmodqi4, __divmodhi4, __divmodsi4, __udivmodqi4, __udivmodhi4, - __udivmodsi4, - + // Several of the runtime library functions use a special calling + // conv + LibcallsWithCC<(add __divmodqi4, __divmodhi4, __udivmodqi4, + __udivmodhi4), + AVR_BUILTIN>, + __divmodsi4, __udivmodsi4, // Trigonometric rtlib functions avr_sin, avr_cos)>; @@ -1509,6 +1513,117 @@ def __mspabi_mpyll : RuntimeLibcallImpl; // setLibcallCallingConv(MUL_I64, CallingConv::MSP430_BUILTIN); +def isMSP430 : RuntimeLibcallPredicate<"TT.getArch() == Triple::msp430">; + +defvar MSP430DefaultOptOut = [ + __addsf3, __divsf3, __extendsfdf2, __truncdfsf2, __fixsfsi, + __fixsfdi, __fixunssfsi, __mulsf3, __eqsf2, __gesf2, __gtsf2, + __divhi3, __divsi3, __ashlsi3, __floatsidf, __floatsisf, + __ashrsi3, __modhi3, __udivsi3, __fixdfsi, __fixunssfdi, + __udivhi3, __umodsi3, __nesf2, __lesf2, __floatundisf, + __fixdfdi, __fixunsdfsi, __modsi3, __floatunsisf, + __fixunsdfdi, __ltsf2, __floatdisf, __floatdidf, + __lshrsi3, __subsf3, __umodhi3, __floatunsidf, + __floatundidf +]; + +// EABI Libcalls - EABI Section 6.2 +def MSP430SystemLibrary +: SystemRuntimeLibrary, + __mspabi_cmpf__oeq, + __mspabi_cmpf__une, + __mspabi_cmpf__oge, + __mspabi_cmpf__olt, + __mspabi_cmpf__ole, + __mspabi_cmpf__ogt, + + // Floating point arithmetic - EABI Table 8 + LibcallsWithCC<(add __mspabi_addd, + __mspabi_subd, + __mspabi_mpyd, + __mspabi_divd), MSP430_BUILTIN>, + + __mspabi_addf, + __mspabi_subf, + __mspabi_mpyf, + __mspabi_divf, + + // The following are NOT implemented in libgcc + // __mspabi_negd, + // __mspabi_negf, + + // Universal Integer Operations - EABI Table 9 + __mspabi_divi, + __mspabi_divli, + LibcallsWithCC<(add __mspabi_divlli), MSP430_BUILTIN>, + __mspabi_divu, + __mspabi_divul, + LibcallsWithCC<(add __mspabi_divull), MSP430_BUILTIN>, + __mspabi_remi, + __mspabi_remli, + LibcallsWithCC<(add __mspabi_remlli), MSP430_BUILTIN>, + __mspabi_remu, + __mspabi_remul, + LibcallsWithCC<(add __mspabi_remull), MSP430_BUILTIN>, + + // Bitwise Operations - EABI Table 10 + // TODO: __mspabi_[srli/srai/slli] ARE implemented in libgcc + __msp
[llvm-branch-commits] [llvm] ARM: Add runtime libcall definitions for aebi memory functions (PR #144974)
arsenm wrote: > [!WARNING] > This pull request is not mergeable via GitHub because a downstack PR is > open. Once all requirements are satisfied, merge this PR as a stack href="https://app.graphite.dev/github/pr/llvm/llvm-project/144974?utm_source=stack-comment-downstack-mergeability-warning"; > >on Graphite. > https://graphite.dev/docs/merge-pull-requests";>Learn more * **#144979** https://app.graphite.dev/github/pr/llvm/llvm-project/144979?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144978** https://app.graphite.dev/github/pr/llvm/llvm-project/144978?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144977** https://app.graphite.dev/github/pr/llvm/llvm-project/144977?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144976** https://app.graphite.dev/github/pr/llvm/llvm-project/144976?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144975** https://app.graphite.dev/github/pr/llvm/llvm-project/144975?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144974** https://app.graphite.dev/github/pr/llvm/llvm-project/144974?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> 👈 https://app.graphite.dev/github/pr/llvm/llvm-project/144974?utm_source=stack-comment-view-in-graphite"; target="_blank">(View in Graphite) * **#144973** https://app.graphite.dev/github/pr/llvm/llvm-project/144973?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144972** https://app.graphite.dev/github/pr/llvm/llvm-project/144972?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#143836** https://app.graphite.dev/github/pr/llvm/llvm-project/143836?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * `main` This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn more about https://stacking.dev/?utm_source=stack-comment";>stacking. https://github.com/llvm/llvm-project/pull/144974 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] AArch64: Add libcall impl declarations for __arm_sc* memory functions (PR #144977)
arsenm wrote: > [!WARNING] > This pull request is not mergeable via GitHub because a downstack PR is > open. Once all requirements are satisfied, merge this PR as a stack href="https://app.graphite.dev/github/pr/llvm/llvm-project/144977?utm_source=stack-comment-downstack-mergeability-warning"; > >on Graphite. > https://graphite.dev/docs/merge-pull-requests";>Learn more * **#144979** https://app.graphite.dev/github/pr/llvm/llvm-project/144979?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144978** https://app.graphite.dev/github/pr/llvm/llvm-project/144978?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144977** https://app.graphite.dev/github/pr/llvm/llvm-project/144977?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> 👈 https://app.graphite.dev/github/pr/llvm/llvm-project/144977?utm_source=stack-comment-view-in-graphite"; target="_blank">(View in Graphite) * **#144976** https://app.graphite.dev/github/pr/llvm/llvm-project/144976?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144975** https://app.graphite.dev/github/pr/llvm/llvm-project/144975?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144974** https://app.graphite.dev/github/pr/llvm/llvm-project/144974?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144973** https://app.graphite.dev/github/pr/llvm/llvm-project/144973?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144972** https://app.graphite.dev/github/pr/llvm/llvm-project/144972?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#143836** https://app.graphite.dev/github/pr/llvm/llvm-project/143836?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * `main` This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn more about https://stacking.dev/?utm_source=stack-comment";>stacking. https://github.com/llvm/llvm-project/pull/144977 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] Hexagon: Add libcall declarations for special memcpy (PR #144975)
arsenm wrote: > [!WARNING] > This pull request is not mergeable via GitHub because a downstack PR is > open. Once all requirements are satisfied, merge this PR as a stack href="https://app.graphite.dev/github/pr/llvm/llvm-project/144975?utm_source=stack-comment-downstack-mergeability-warning"; > >on Graphite. > https://graphite.dev/docs/merge-pull-requests";>Learn more * **#144979** https://app.graphite.dev/github/pr/llvm/llvm-project/144979?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144978** https://app.graphite.dev/github/pr/llvm/llvm-project/144978?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144977** https://app.graphite.dev/github/pr/llvm/llvm-project/144977?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144976** https://app.graphite.dev/github/pr/llvm/llvm-project/144976?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144975** https://app.graphite.dev/github/pr/llvm/llvm-project/144975?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> 👈 https://app.graphite.dev/github/pr/llvm/llvm-project/144975?utm_source=stack-comment-view-in-graphite"; target="_blank">(View in Graphite) * **#144974** https://app.graphite.dev/github/pr/llvm/llvm-project/144974?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144973** https://app.graphite.dev/github/pr/llvm/llvm-project/144973?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144972** https://app.graphite.dev/github/pr/llvm/llvm-project/144972?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#143836** https://app.graphite.dev/github/pr/llvm/llvm-project/143836?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * `main` This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn more about https://stacking.dev/?utm_source=stack-comment";>stacking. https://github.com/llvm/llvm-project/pull/144975 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] XCore: Declare libcalls used for align 4 memcpy (PR #144976)
arsenm wrote: > [!WARNING] > This pull request is not mergeable via GitHub because a downstack PR is > open. Once all requirements are satisfied, merge this PR as a stack href="https://app.graphite.dev/github/pr/llvm/llvm-project/144976?utm_source=stack-comment-downstack-mergeability-warning"; > >on Graphite. > https://graphite.dev/docs/merge-pull-requests";>Learn more * **#144979** https://app.graphite.dev/github/pr/llvm/llvm-project/144979?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144978** https://app.graphite.dev/github/pr/llvm/llvm-project/144978?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144977** https://app.graphite.dev/github/pr/llvm/llvm-project/144977?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144976** https://app.graphite.dev/github/pr/llvm/llvm-project/144976?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> 👈 https://app.graphite.dev/github/pr/llvm/llvm-project/144976?utm_source=stack-comment-view-in-graphite"; target="_blank">(View in Graphite) * **#144975** https://app.graphite.dev/github/pr/llvm/llvm-project/144975?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144974** https://app.graphite.dev/github/pr/llvm/llvm-project/144974?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144973** https://app.graphite.dev/github/pr/llvm/llvm-project/144973?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144972** https://app.graphite.dev/github/pr/llvm/llvm-project/144972?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#143836** https://app.graphite.dev/github/pr/llvm/llvm-project/143836?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * `main` This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn more about https://stacking.dev/?utm_source=stack-comment";>stacking. https://github.com/llvm/llvm-project/pull/144976 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] TableGen: Generate enum for runtime libcall implementations (PR #144973)
arsenm wrote: > [!WARNING] > This pull request is not mergeable via GitHub because a downstack PR is > open. Once all requirements are satisfied, merge this PR as a stack href="https://app.graphite.dev/github/pr/llvm/llvm-project/144973?utm_source=stack-comment-downstack-mergeability-warning"; > >on Graphite. > https://graphite.dev/docs/merge-pull-requests";>Learn more * **#144979** https://app.graphite.dev/github/pr/llvm/llvm-project/144979?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144978** https://app.graphite.dev/github/pr/llvm/llvm-project/144978?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144977** https://app.graphite.dev/github/pr/llvm/llvm-project/144977?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144976** https://app.graphite.dev/github/pr/llvm/llvm-project/144976?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144975** https://app.graphite.dev/github/pr/llvm/llvm-project/144975?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144974** https://app.graphite.dev/github/pr/llvm/llvm-project/144974?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144973** https://app.graphite.dev/github/pr/llvm/llvm-project/144973?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> 👈 https://app.graphite.dev/github/pr/llvm/llvm-project/144973?utm_source=stack-comment-view-in-graphite"; target="_blank">(View in Graphite) * **#144972** https://app.graphite.dev/github/pr/llvm/llvm-project/144972?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#143836** https://app.graphite.dev/github/pr/llvm/llvm-project/143836?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * `main` This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn more about https://stacking.dev/?utm_source=stack-comment";>stacking. https://github.com/llvm/llvm-project/pull/144973 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] XCore: Declare libcalls used for align 4 memcpy (PR #144976)
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/144976 This usage was hidden in XCoreSelectionDAGInfo and bypassed the usual libcall system, so define these for later use. >From 99598fb6ea1451223c65fd1be59ab1cc737eea8b Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 16 Jun 2025 16:27:41 +0900 Subject: [PATCH] XCore: Declare libcalls used for align 4 memcpy This usage was hidden in XCoreSelectionDAGInfo and bypassed the usual libcall system, so define these for later use. --- llvm/include/llvm/IR/RuntimeLibcalls.td | 9 + llvm/lib/IR/RuntimeLibcalls.cpp | 3 +++ llvm/lib/Target/XCore/XCoreSelectionDAGInfo.cpp | 13 - 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index 2efe823a760db..57ad6f09e8b57 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -371,6 +371,9 @@ def AEABI_MEMCLR8 : RuntimeLibcall; // Hexagon calls def HEXAGON_MEMCPY_LIKELY_ALIGNED_MIN32BYTES_MULT8BYTES : RuntimeLibcall; +// XCore calls +def MEMCPY_ALIGN_4 : RuntimeLibcall; + // // Define implementation default libcalls // @@ -1544,6 +1547,12 @@ def _allrem : RuntimeLibcallImpl; // CallingConv::X86_StdCall def _aullrem : RuntimeLibcallImpl; // CallingConv::X86_StdCall def _allmul : RuntimeLibcallImpl; // CallingConv::X86_StdCall +//===--===// +// XCore Runtime Libcalls +//===--===// + +def __memcpy_4 : RuntimeLibcallImpl; + //===--===// // ZOS Runtime Libcalls //===--===// diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp index 873ee6b509e2d..0f92371f05529 100644 --- a/llvm/lib/IR/RuntimeLibcalls.cpp +++ b/llvm/lib/IR/RuntimeLibcalls.cpp @@ -627,4 +627,7 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT, if (TT.isSystemZ() && TT.isOSzOS()) setZOSLibCallNameOverrides(); + + if (TT.getArch() == Triple::ArchType::xcore) +setLibcallImpl(RTLIB::MEMCPY_ALIGN_4, RTLIB::__memcpy_4); } diff --git a/llvm/lib/Target/XCore/XCoreSelectionDAGInfo.cpp b/llvm/lib/Target/XCore/XCoreSelectionDAGInfo.cpp index bc34ab4319690..1bd92a2b49475 100644 --- a/llvm/lib/Target/XCore/XCoreSelectionDAGInfo.cpp +++ b/llvm/lib/Target/XCore/XCoreSelectionDAGInfo.cpp @@ -39,14 +39,17 @@ SDValue XCoreSelectionDAGInfo::EmitTargetCodeForMemcpy( Entry.Node = Src; Args.push_back(Entry); Entry.Node = Size; Args.push_back(Entry); +const char *MemcpyAlign4Name = TLI.getLibcallName(RTLIB::MEMCPY_ALIGN_4); +CallingConv::ID CC = TLI.getLibcallCallingConv(RTLIB::MEMCPY_ALIGN_4); + TargetLowering::CallLoweringInfo CLI(DAG); CLI.setDebugLoc(dl) .setChain(Chain) -.setLibCallee(TLI.getLibcallCallingConv(RTLIB::MEMCPY), - Type::getVoidTy(*DAG.getContext()), - DAG.getExternalSymbol( - "__memcpy_4", TLI.getPointerTy(DAG.getDataLayout())), - std::move(Args)) +.setLibCallee( +CC, Type::getVoidTy(*DAG.getContext()), +DAG.getExternalSymbol(MemcpyAlign4Name, + TLI.getPointerTy(DAG.getDataLayout())), +std::move(Args)) .setDiscardResult(); std::pair CallResult = TLI.LowerCallTo(CLI); ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] AArch64: Add libcall impl declarations for __arm_sc* memory functions (PR #144977)
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/144977 These were bypassing the ordinary libcall emission mechanism. Make sure we have entries in RuntimeLibcalls, which should include all possible calls the compiler could emit. Fixes not emitting the # prefix in the arm64ec case. >From ec3e89d2b07a33225475a43850aba9d23ecd9c96 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 16 Jun 2025 14:56:26 +0900 Subject: [PATCH] AArch64: Add libcall impl declarations for __arm_sc* memory functions These were bypassing the ordinary libcall emission mechanism. Make sure we have entries in RuntimeLibcalls, which should include all possible calls the compiler could emit. Fixes not emitting the # prefix in the arm64ec case. --- llvm/include/llvm/IR/RuntimeLibcalls.td | 9 + llvm/lib/IR/RuntimeLibcalls.cpp | 11 ++- .../Target/AArch64/AArch64SelectionDAGInfo.cpp| 15 +++ llvm/test/CodeGen/AArch64/arm64ec-builtins.ll | 9 +++-- 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index 57ad6f09e8b57..1d9f02dcf8ba8 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -357,6 +357,11 @@ multiclass LibmLongDoubleLibCall; } +// AArch64 calls +def SC_MEMCPY : RuntimeLibcall; +def SC_MEMMOVE : RuntimeLibcall; +def SC_MEMSET : RuntimeLibcall; + // ARM EABI calls def AEABI_MEMCPY4 : RuntimeLibcall; // Align 4 def AEABI_MEMCPY8 : RuntimeLibcall; // Align 8 @@ -985,6 +990,10 @@ defset list AArch64LibcallImpls = { defm __aarch64_ldeor#MemSize : AtomicOrderSizeLibcallImpl<"OUTLINE_ATOMIC_LDEOR"#MemSize>; } + + def __arm_sc_memcpy : RuntimeLibcallImpl; + def __arm_sc_memmove : RuntimeLibcallImpl; + def __arm_sc_memset : RuntimeLibcallImpl; } foreach libcall = AArch64LibcallImpls in { diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp index 0f92371f05529..67f872b4574b1 100644 --- a/llvm/lib/IR/RuntimeLibcalls.cpp +++ b/llvm/lib/IR/RuntimeLibcalls.cpp @@ -521,8 +521,17 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT, } if (TT.isAArch64()) { -if (TT.isWindowsArm64EC()) +if (TT.isWindowsArm64EC()) { setWindowsArm64LibCallNameOverrides(); + setLibcallImpl(RTLIB::SC_MEMCPY, RTLIB::arm64ec___arm_sc_memcpy); + setLibcallImpl(RTLIB::SC_MEMMOVE, RTLIB::arm64ec___arm_sc_memmove); + setLibcallImpl(RTLIB::SC_MEMSET, RTLIB::arm64ec___arm_sc_memset); +} else { + setLibcallImpl(RTLIB::SC_MEMCPY, RTLIB::__arm_sc_memcpy); + setLibcallImpl(RTLIB::SC_MEMMOVE, RTLIB::__arm_sc_memmove); + setLibcallImpl(RTLIB::SC_MEMSET, RTLIB::__arm_sc_memset); +} + setAArch64LibcallNames(*this, TT); } else if (TT.isARM() || TT.isThumb()) { setARMLibcallNames(*this, TT, FloatABI, EABIVersion); diff --git a/llvm/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp b/llvm/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp index 90f6fc2ea664b..d719f234b27f7 100644 --- a/llvm/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp @@ -164,35 +164,34 @@ SDValue AArch64SelectionDAGInfo::EmitStreamingCompatibleMemLibCall( const AArch64Subtarget &STI = DAG.getMachineFunction().getSubtarget(); const AArch64TargetLowering *TLI = STI.getTargetLowering(); - SDValue Symbol; TargetLowering::ArgListEntry DstEntry; DstEntry.Ty = PointerType::getUnqual(*DAG.getContext()); DstEntry.Node = Dst; TargetLowering::ArgListTy Args; Args.push_back(DstEntry); - EVT PointerVT = TLI->getPointerTy(DAG.getDataLayout()); + RTLIB::Libcall NewLC; switch (LC) { case RTLIB::MEMCPY: { +NewLC = RTLIB::SC_MEMCPY; TargetLowering::ArgListEntry Entry; Entry.Ty = PointerType::getUnqual(*DAG.getContext()); -Symbol = DAG.getExternalSymbol("__arm_sc_memcpy", PointerVT); Entry.Node = Src; Args.push_back(Entry); break; } case RTLIB::MEMMOVE: { +NewLC = RTLIB::SC_MEMMOVE; TargetLowering::ArgListEntry Entry; Entry.Ty = PointerType::getUnqual(*DAG.getContext()); -Symbol = DAG.getExternalSymbol("__arm_sc_memmove", PointerVT); Entry.Node = Src; Args.push_back(Entry); break; } case RTLIB::MEMSET: { +NewLC = RTLIB::SC_MEMSET; TargetLowering::ArgListEntry Entry; Entry.Ty = Type::getInt32Ty(*DAG.getContext()); -Symbol = DAG.getExternalSymbol("__arm_sc_memset", PointerVT); Src = DAG.getZExtOrTrunc(Src, DL, MVT::i32); Entry.Node = Src; Args.push_back(Entry); @@ -202,17 +201,17 @@ SDValue AArch64SelectionDAGInfo::EmitStreamingCompatibleMemLibCall( return SDValue(); } + EVT PointerVT = TLI->getPointerTy(DAG.getDataLayout()); + SDValue Symbol = DAG.getExternalSymbol(TLI->getLibcallName(NewLC), PointerVT); TargetLowering::ArgListEntry Siz
[llvm-branch-commits] [llvm] ARM: Add runtime libcall definitions for aebi memory functions (PR #144974)
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/144974 Fix bypassing ordinary RuntimeLibcalls APIs for cases handled in ARMSelectionDAGInfo >From bdbc320f70d3fd80fd4d50f89ec4cdbe5d02b7db Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 16 Jun 2025 15:50:24 +0900 Subject: [PATCH] ARM: Add runtime libcall definitions for eabi memory functions Fix bypassing ordinary RuntimeLibcalls APIs for cases handled in ARMSelectionDAGInfo --- llvm/include/llvm/IR/RuntimeLibcalls.td | 23 + llvm/lib/Target/ARM/ARMISelLowering.cpp | 17 +++ llvm/lib/Target/ARM/ARMSelectionDAGInfo.cpp | 18 +--- 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index c910fce2edd80..71efecdf082af 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -357,6 +357,17 @@ multiclass LibmLongDoubleLibCall; } +// ARM EABI calls +def AEABI_MEMCPY4 : RuntimeLibcall; // Align 4 +def AEABI_MEMCPY8 : RuntimeLibcall; // Align 8 +def AEABI_MEMMOVE4 : RuntimeLibcall; +def AEABI_MEMMOVE8 : RuntimeLibcall; +def AEABI_MEMSET4 : RuntimeLibcall; +def AEABI_MEMSET8 : RuntimeLibcall; +def AEABI_MEMCLR : RuntimeLibcall; +def AEABI_MEMCLR4 : RuntimeLibcall; +def AEABI_MEMCLR8 : RuntimeLibcall; + // // Define implementation default libcalls // @@ -1134,8 +1145,20 @@ def __aeabi_uidivmod : RuntimeLibcallImpl; // CallingConv::ARM_AAP // Memory operations // RTABI chapter 4.3.4 def __aeabi_memcpy : RuntimeLibcallImpl; // CallingConv::ARM_AAPCS +def __aeabi_memcpy4 : RuntimeLibcallImpl; +def __aeabi_memcpy8 : RuntimeLibcallImpl; + def __aeabi_memmove : RuntimeLibcallImpl; // CallingConv::ARM_AAPCS +def __aeabi_memmove4 : RuntimeLibcallImpl; +def __aeabi_memmove8 : RuntimeLibcallImpl; + def __aeabi_memset : RuntimeLibcallImpl; // CallingConv::ARM_AAPCS +def __aeabi_memset4 : RuntimeLibcallImpl; +def __aeabi_memset8 : RuntimeLibcallImpl; + +def __aeabi_memclr : RuntimeLibcallImpl; +def __aeabi_memclr4 : RuntimeLibcallImpl; +def __aeabi_memclr8 : RuntimeLibcallImpl; // isTargetWindows() def __stoi64 : RuntimeLibcallImpl; // CallingConv::ARM_AAPCS_VFP diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 81b535e19bc71..478791699df88 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -704,6 +704,23 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_, {RTLIB::MEMCPY, RTLIB::__aeabi_memcpy, CallingConv::ARM_AAPCS}, {RTLIB::MEMMOVE, RTLIB::__aeabi_memmove, CallingConv::ARM_AAPCS}, {RTLIB::MEMSET, RTLIB::__aeabi_memset, CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMCPY4, RTLIB::__aeabi_memcpy4, + CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMCPY8, RTLIB::__aeabi_memcpy8, + CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMMOVE4, RTLIB::__aeabi_memmove4, + CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMMOVE8, RTLIB::__aeabi_memmove8, + CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMSET4, RTLIB::__aeabi_memset4, + CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMSET8, RTLIB::__aeabi_memset8, + CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMCLR, RTLIB::__aeabi_memclr, CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMCLR4, RTLIB::__aeabi_memclr4, + CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMCLR8, RTLIB::__aeabi_memclr8, + CallingConv::ARM_AAPCS}, }; for (const auto &LC : MemOpsLibraryCalls) { diff --git a/llvm/lib/Target/ARM/ARMSelectionDAGInfo.cpp b/llvm/lib/Target/ARM/ARMSelectionDAGInfo.cpp index 77f4782699c96..b4677a8bfb035 100644 --- a/llvm/lib/Target/ARM/ARMSelectionDAGInfo.cpp +++ b/llvm/lib/Target/ARM/ARMSelectionDAGInfo.cpp @@ -121,18 +121,20 @@ SDValue ARMSelectionDAGInfo::EmitSpecializedLibcall( Args.push_back(Entry); } - char const *FunctionNames[4][3] = { -{ "__aeabi_memcpy", "__aeabi_memcpy4", "__aeabi_memcpy8" }, -{ "__aeabi_memmove", "__aeabi_memmove4", "__aeabi_memmove8" }, -{ "__aeabi_memset", "__aeabi_memset4", "__aeabi_memset8" }, -{ "__aeabi_memclr", "__aeabi_memclr4", "__aeabi_memclr8" } - }; + static const RTLIB::Libcall FunctionImpls[4][3] = { + {RTLIB::MEMCPY, RTLIB::AEABI_MEMCPY4, RTLIB::AEABI_MEMCPY8}, + {RTLIB::MEMMOVE, RTLIB::AEABI_MEMMOVE4, RTLIB::AEABI_MEMMOVE8}, + {RTLIB::MEMSET, RTLIB::AEABI_MEMSET4, RTLIB::AEABI_MEMSET8}, + {RTLIB::AEABI_MEMCLR, RTLIB::AEABI_MEMCLR4, RTLIB::AEABI_MEMCLR8}}; + + RTLIB::Libcall NewLC = FunctionImpls[AEABILibcall][AlignVariant]; + TargetLowering::CallLoweringInfo CLI(DAG); CLI.
[llvm-branch-commits] [llvm] Hexagon: Add libcall declarations for special memcpy (PR #144975)
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/144975 HexagonSelectionDAGInfo was bypassing the ordinary RuntimeLibcallInfo handling for this case, so define a libcall for it and use it. >From a845b0e8b095dad7ce55d0a64b0b57b515602144 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 16 Jun 2025 16:14:09 +0900 Subject: [PATCH] Hexagon: Add libcall declarations for special memcpy HexagonSelectionDAGInfo was bypassing the ordinary RuntimeLibcallInfo handling for this case, so define a libcall for it and use it. --- llvm/include/llvm/IR/RuntimeLibcalls.td | 6 ++ llvm/lib/IR/RuntimeLibcalls.cpp | 4 llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp | 10 ++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index 71efecdf082af..2efe823a760db 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -368,6 +368,9 @@ def AEABI_MEMCLR : RuntimeLibcall; def AEABI_MEMCLR4 : RuntimeLibcall; def AEABI_MEMCLR8 : RuntimeLibcall; +// Hexagon calls +def HEXAGON_MEMCPY_LIKELY_ALIGNED_MIN32BYTES_MULT8BYTES : RuntimeLibcall; + // // Define implementation default libcalls // @@ -1247,6 +1250,9 @@ def __hexagon_fast2_sqrtf : RuntimeLibcallImpl; // This is the only fast library function for sqrtd. def __hexagon_fast2_sqrtdf2 : RuntimeLibcallImpl; +def __hexagon_memcpy_likely_aligned_min32bytes_mult8bytes +: RuntimeLibcallImpl; + //===--===// // Mips16 Runtime Libcalls //===--===// diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp index 5fccb23e6c5ff..873ee6b509e2d 100644 --- a/llvm/lib/IR/RuntimeLibcalls.cpp +++ b/llvm/lib/IR/RuntimeLibcalls.cpp @@ -616,6 +616,10 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT, setLibcallImpl(RTLIB::SQRT_F32, RTLIB::__hexagon_fast2_sqrtf); else setLibcallImpl(RTLIB::SQRT_F32, RTLIB::__hexagon_sqrtf); + +setLibcallImpl( +RTLIB::HEXAGON_MEMCPY_LIKELY_ALIGNED_MIN32BYTES_MULT8BYTES, +RTLIB::__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes); } if (TT.getArch() == Triple::ArchType::msp430) diff --git a/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp b/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp index 1b724e8fcae91..610a81fe45c2f 100644 --- a/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp +++ b/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp @@ -41,18 +41,20 @@ SDValue HexagonSelectionDAGInfo::EmitTargetCodeForMemcpy( Entry.Node = Size; Args.push_back(Entry); - const char *SpecialMemcpyName = - "__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes"; + const char *SpecialMemcpyName = TLI.getLibcallName( + RTLIB::HEXAGON_MEMCPY_LIKELY_ALIGNED_MIN32BYTES_MULT8BYTES); const MachineFunction &MF = DAG.getMachineFunction(); bool LongCalls = MF.getSubtarget().useLongCalls(); unsigned Flags = LongCalls ? HexagonII::HMOTF_ConstExtended : 0; + CallingConv::ID CC = TLI.getLibcallCallingConv( + RTLIB::HEXAGON_MEMCPY_LIKELY_ALIGNED_MIN32BYTES_MULT8BYTES); + TargetLowering::CallLoweringInfo CLI(DAG); CLI.setDebugLoc(dl) .setChain(Chain) .setLibCallee( - TLI.getLibcallCallingConv(RTLIB::MEMCPY), - Type::getVoidTy(*DAG.getContext()), + CC, Type::getVoidTy(*DAG.getContext()), DAG.getTargetExternalSymbol( SpecialMemcpyName, TLI.getPointerTy(DAG.getDataLayout()), Flags), std::move(Args)) ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] TableGen: Add runtime libcall backend (PR #144972)
llvmbot wrote: @llvm/pr-subscribers-llvm-ir Author: Matt Arsenault (arsenm) Changes Replace RuntimeLibcalls.def with a tablegenerated version. This is in preparation for splitting RuntimeLibcalls into two components. For now match the existing functionality. --- Patch is 105.75 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/144972.diff 13 Files Affected: - (modified) llvm/include/llvm/IR/CMakeLists.txt (+3) - (removed) llvm/include/llvm/IR/RuntimeLibcalls.def (-701) - (modified) llvm/include/llvm/IR/RuntimeLibcalls.h (+20-16) - (added) llvm/include/llvm/IR/RuntimeLibcalls.td (+1054) - (added) llvm/include/llvm/IR/RuntimeLibcallsImpl.td (+32) - (modified) llvm/include/module.modulemap (-1) - (modified) llvm/lib/IR/RuntimeLibcalls.cpp (+31-77) - (removed) llvm/lib/IR/ZOSLibcallNames.def (-100) - (modified) llvm/lib/Object/IRSymtab.cpp (+1-1) - (added) llvm/test/TableGen/RuntimeLibcallEmitter.td (+40) - (modified) llvm/utils/TableGen/Basic/CMakeLists.txt (+1) - (added) llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp (+305) - (modified) llvm/utils/gn/secondary/llvm/utils/TableGen/Basic/BUILD.gn (+1) ``diff diff --git a/llvm/include/llvm/IR/CMakeLists.txt b/llvm/include/llvm/IR/CMakeLists.txt index 468d663796ed4..c5c4cc4d21b84 100644 --- a/llvm/include/llvm/IR/CMakeLists.txt +++ b/llvm/include/llvm/IR/CMakeLists.txt @@ -1,6 +1,9 @@ set(LLVM_TARGET_DEFINITIONS Attributes.td) tablegen(LLVM Attributes.inc -gen-attrs) +set(LLVM_TARGET_DEFINITIONS RuntimeLibcalls.td) +tablegen(LLVM RuntimeLibcalls.inc -gen-runtime-libcalls) + set(LLVM_TARGET_DEFINITIONS Intrinsics.td) tablegen(LLVM IntrinsicImpl.inc -gen-intrinsic-impl) tablegen(LLVM IntrinsicEnums.inc -gen-intrinsic-enums) diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.def b/llvm/include/llvm/IR/RuntimeLibcalls.def deleted file mode 100644 index 247643525ff48..0 --- a/llvm/include/llvm/IR/RuntimeLibcalls.def +++ /dev/null @@ -1,701 +0,0 @@ -//===-- llvm/RuntimeLibcalls.def - File that describes libcalls -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===--===// -// -// This file defines all of the runtime library calls the backend can emit. -// The various long double types cannot be merged, because 80-bit library -// functions use "xf" and 128-bit use "tf". -// -// When adding PPCF128 functions here, note that their names generally need -// to be overridden for Darwin with the xxx$LDBL128 form. See -// PPCISelLowering.cpp. -// -//===--===// - -// NOTE: NO INCLUDE GUARD DESIRED! - -// Provide definitions of macros so that users of this file do not have to -// define everything to use it... - -// Declare the enumerator for each libcall, along with its default name. Some -// libcalls have different names on particular OSes or architectures. These -// are set in InitLibcalls() in TargetLoweringBase.cpp and/or by targets -// using TargetLoweringBase::setLibcallName() -#ifndef HANDLE_LIBCALL -#error "HANDLE_LIBCALL must be defined" -#endif - -// Integer -HANDLE_LIBCALL(SHL_I16, "__ashlhi3") -HANDLE_LIBCALL(SHL_I32, "__ashlsi3") -HANDLE_LIBCALL(SHL_I64, "__ashldi3") -HANDLE_LIBCALL(SHL_I128, "__ashlti3") -HANDLE_LIBCALL(SRL_I16, "__lshrhi3") -HANDLE_LIBCALL(SRL_I32, "__lshrsi3") -HANDLE_LIBCALL(SRL_I64, "__lshrdi3") -HANDLE_LIBCALL(SRL_I128, "__lshrti3") -HANDLE_LIBCALL(SRA_I16, "__ashrhi3") -HANDLE_LIBCALL(SRA_I32, "__ashrsi3") -HANDLE_LIBCALL(SRA_I64, "__ashrdi3") -HANDLE_LIBCALL(SRA_I128, "__ashrti3") -HANDLE_LIBCALL(MUL_I8, "__mulqi3") -HANDLE_LIBCALL(MUL_I16, "__mulhi3") -HANDLE_LIBCALL(MUL_I32, "__mulsi3") -HANDLE_LIBCALL(MUL_I64, "__muldi3") -HANDLE_LIBCALL(MUL_I128, "__multi3") -HANDLE_LIBCALL(MULO_I32, "__mulosi4") -HANDLE_LIBCALL(MULO_I64, "__mulodi4") -HANDLE_LIBCALL(MULO_I128, "__muloti4") -HANDLE_LIBCALL(SDIV_I8, "__divqi3") -HANDLE_LIBCALL(SDIV_I16, "__divhi3") -HANDLE_LIBCALL(SDIV_I32, "__divsi3") -HANDLE_LIBCALL(SDIV_I64, "__divdi3") -HANDLE_LIBCALL(SDIV_I128, "__divti3") -HANDLE_LIBCALL(UDIV_I8, "__udivqi3") -HANDLE_LIBCALL(UDIV_I16, "__udivhi3") -HANDLE_LIBCALL(UDIV_I32, "__udivsi3") -HANDLE_LIBCALL(UDIV_I64, "__udivdi3") -HANDLE_LIBCALL(UDIV_I128, "__udivti3") -HANDLE_LIBCALL(SREM_I8, "__modqi3") -HANDLE_LIBCALL(SREM_I16, "__modhi3") -HANDLE_LIBCALL(SREM_I32, "__modsi3") -HANDLE_LIBCALL(SREM_I64, "__moddi3") -HANDLE_LIBCALL(SREM_I128, "__modti3") -HANDLE_LIBCALL(UREM_I8, "__umodqi3") -HANDLE_LIBCALL(UREM_I16, "__umodhi3") -HANDLE_LIBCALL(UREM_I32, "__umodsi3") -HANDLE_LIBCALL(UREM_I64, "__umoddi3") -HANDLE_LIBCALL(UREM_I128, "__umodti3") -HANDLE_LIBCALL(SDIVREM_I8, LIBCALL_NO_NAME) -HANDLE_LIBCALL(SDIVREM_I16, LIBCALL_NO_NAME)
[llvm-branch-commits] [llvm] TableGen: Allow defining sets of runtime libraries (PR #144978)
arsenm wrote: > [!WARNING] > This pull request is not mergeable via GitHub because a downstack PR is > open. Once all requirements are satisfied, merge this PR as a stack href="https://app.graphite.dev/github/pr/llvm/llvm-project/144978?utm_source=stack-comment-downstack-mergeability-warning"; > >on Graphite. > https://graphite.dev/docs/merge-pull-requests";>Learn more * **#144980** https://app.graphite.dev/github/pr/llvm/llvm-project/144980?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144979** https://app.graphite.dev/github/pr/llvm/llvm-project/144979?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144978** https://app.graphite.dev/github/pr/llvm/llvm-project/144978?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> 👈 https://app.graphite.dev/github/pr/llvm/llvm-project/144978?utm_source=stack-comment-view-in-graphite"; target="_blank">(View in Graphite) * **#144977** https://app.graphite.dev/github/pr/llvm/llvm-project/144977?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144976** https://app.graphite.dev/github/pr/llvm/llvm-project/144976?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144975** https://app.graphite.dev/github/pr/llvm/llvm-project/144975?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144974** https://app.graphite.dev/github/pr/llvm/llvm-project/144974?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144973** https://app.graphite.dev/github/pr/llvm/llvm-project/144973?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144972** https://app.graphite.dev/github/pr/llvm/llvm-project/144972?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#143836** https://app.graphite.dev/github/pr/llvm/llvm-project/143836?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * `main` This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn more about https://stacking.dev/?utm_source=stack-comment";>stacking. https://github.com/llvm/llvm-project/pull/144978 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] TableGen: Handle setting runtime libcall calling conventions (PR #144980)
arsenm wrote: > [!WARNING] > This pull request is not mergeable via GitHub because a downstack PR is > open. Once all requirements are satisfied, merge this PR as a stack href="https://app.graphite.dev/github/pr/llvm/llvm-project/144980?utm_source=stack-comment-downstack-mergeability-warning"; > >on Graphite. > https://graphite.dev/docs/merge-pull-requests";>Learn more * **#144980** https://app.graphite.dev/github/pr/llvm/llvm-project/144980?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> 👈 https://app.graphite.dev/github/pr/llvm/llvm-project/144980?utm_source=stack-comment-view-in-graphite"; target="_blank">(View in Graphite) * **#144979** https://app.graphite.dev/github/pr/llvm/llvm-project/144979?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144978** https://app.graphite.dev/github/pr/llvm/llvm-project/144978?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144977** https://app.graphite.dev/github/pr/llvm/llvm-project/144977?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144976** https://app.graphite.dev/github/pr/llvm/llvm-project/144976?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144975** https://app.graphite.dev/github/pr/llvm/llvm-project/144975?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144974** https://app.graphite.dev/github/pr/llvm/llvm-project/144974?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144973** https://app.graphite.dev/github/pr/llvm/llvm-project/144973?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144972** https://app.graphite.dev/github/pr/llvm/llvm-project/144972?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#143836** https://app.graphite.dev/github/pr/llvm/llvm-project/143836?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * `main` This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn more about https://stacking.dev/?utm_source=stack-comment";>stacking. https://github.com/llvm/llvm-project/pull/144980 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] RuntimeLibcalls: Associate calling convention with libcall impls (PR #144979)
arsenm wrote: > [!WARNING] > This pull request is not mergeable via GitHub because a downstack PR is > open. Once all requirements are satisfied, merge this PR as a stack href="https://app.graphite.dev/github/pr/llvm/llvm-project/144979?utm_source=stack-comment-downstack-mergeability-warning"; > >on Graphite. > https://graphite.dev/docs/merge-pull-requests";>Learn more * **#144980** https://app.graphite.dev/github/pr/llvm/llvm-project/144980?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144979** https://app.graphite.dev/github/pr/llvm/llvm-project/144979?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> 👈 https://app.graphite.dev/github/pr/llvm/llvm-project/144979?utm_source=stack-comment-view-in-graphite"; target="_blank">(View in Graphite) * **#144978** https://app.graphite.dev/github/pr/llvm/llvm-project/144978?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144977** https://app.graphite.dev/github/pr/llvm/llvm-project/144977?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144976** https://app.graphite.dev/github/pr/llvm/llvm-project/144976?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144975** https://app.graphite.dev/github/pr/llvm/llvm-project/144975?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144974** https://app.graphite.dev/github/pr/llvm/llvm-project/144974?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144973** https://app.graphite.dev/github/pr/llvm/llvm-project/144973?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#144972** https://app.graphite.dev/github/pr/llvm/llvm-project/144972?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#143836** https://app.graphite.dev/github/pr/llvm/llvm-project/143836?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * `main` This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn more about https://stacking.dev/?utm_source=stack-comment";>stacking. https://github.com/llvm/llvm-project/pull/144979 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] TableGen: Allow defining sets of runtime libraries (PR #144978)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff HEAD~1 HEAD --extensions cpp,h -- llvm/include/llvm/IR/RuntimeLibcalls.h llvm/lib/IR/RuntimeLibcalls.cpp llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp `` View the diff from clang-format here. ``diff diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp index 30fcca47a..a4b6c8d7f 100644 --- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp +++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp @@ -349,9 +349,8 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls( SetTheory Sets; DenseMap> Func2Preds; -Sets.addExpander( -"LibcallImpls", -std::make_unique(*this, Func2Preds)); +Sets.addExpander("LibcallImpls", std::make_unique( + *this, Func2Preds)); const SetTheory::RecVec *Elements = Sets.expand(R->getValueAsDef("MemberList")); `` https://github.com/llvm/llvm-project/pull/144978 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] TableGen: Add runtime libcall backend (PR #144972)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff HEAD~1 HEAD --extensions cpp,h -- llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp llvm/include/llvm/IR/RuntimeLibcalls.h llvm/lib/IR/RuntimeLibcalls.cpp llvm/lib/Object/IRSymtab.cpp `` View the diff from clang-format here. ``diff diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h index e063076fa..fdded7694 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.h +++ b/llvm/include/llvm/IR/RuntimeLibcalls.h @@ -107,8 +107,8 @@ struct RuntimeLibcallsInfo { } private: - static const char *const - DefaultLibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL + 1]; + static const char + *const DefaultLibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL + 1]; /// Stores the name each libcall. const char *LibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL + 1] = {nullptr}; `` https://github.com/llvm/llvm-project/pull/144972 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] TableGen: Add runtime libcall backend (PR #144972)
https://github.com/arsenm ready_for_review https://github.com/llvm/llvm-project/pull/144972 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] Hexagon: Add libcall declarations for special memcpy (PR #144975)
https://github.com/arsenm ready_for_review https://github.com/llvm/llvm-project/pull/144975 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] TableGen: Generate enum for runtime libcall implementations (PR #144973)
llvmbot wrote: @llvm/pr-subscribers-llvm-ir Author: Matt Arsenault (arsenm) Changes Work towards separating the ABI existence of libcalls vs. the lowering selection. Set libcall selection through enums, rather than through raw string names. --- Patch is 122.30 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/144973.diff 12 Files Affected: - (modified) llvm/include/llvm/CodeGen/TargetLowering.h (+2-7) - (modified) llvm/include/llvm/IR/RuntimeLibcalls.h (+38-17) - (modified) llvm/include/llvm/IR/RuntimeLibcalls.td (+561-1) - (modified) llvm/lib/IR/RuntimeLibcalls.cpp (+268-263) - (modified) llvm/lib/LTO/LTO.cpp (+8-2) - (modified) llvm/lib/Object/IRSymtab.cpp (+3-3) - (modified) llvm/lib/Target/ARM/ARMISelLowering.cpp (+108-102) - (modified) llvm/lib/Target/MSP430/MSP430ISelLowering.cpp (+32-32) - (modified) llvm/lib/Target/Mips/Mips16ISelLowering.cpp (+49-40) - (modified) llvm/lib/Target/Sparc/SparcISelLowering.cpp (+43-43) - (modified) llvm/test/TableGen/RuntimeLibcallEmitter.td (+45-8) - (modified) llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp (+60-20) ``diff diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index 727526055e592..69ae4f80297d5 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -3558,13 +3558,8 @@ class LLVM_ABI TargetLoweringBase { return nullptr; } - /// Rename the default libcall routine name for the specified libcall. - void setLibcallName(RTLIB::Libcall Call, const char *Name) { -Libcalls.setLibcallName(Call, Name); - } - - void setLibcallName(ArrayRef Calls, const char *Name) { -Libcalls.setLibcallName(Calls, Name); + void setLibcallImpl(RTLIB::Libcall Call, RTLIB::LibcallImpl Impl) { +Libcalls.setLibcallImpl(Call, Impl); } /// Get the libcall routine name for the specified libcall. diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h index e063076fac71a..912715fbf6b19 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.h +++ b/llvm/include/llvm/IR/RuntimeLibcalls.h @@ -23,6 +23,10 @@ #include "llvm/Support/Compiler.h" #include "llvm/TargetParser/Triple.h" +/// TableGen will produce 2 enums, RTLIB::Libcall and +/// RTLIB::LibcallImpl. RTLIB::Libcall describes abstract functionality the +/// compiler may choose to access, RTLIB::LibcallImpl describes a particular ABI +/// implementation, which includes a name and type signature. #define GET_RUNTIME_LIBCALL_ENUM #include "llvm/IR/RuntimeLibcalls.inc" #undef GET_RUNTIME_LIBCALL_ENUM @@ -48,38 +52,46 @@ struct RuntimeLibcallsInfo { FloatABI::ABIType FloatABI = FloatABI::Default, EABI EABIVersion = EABI::Default) { initSoftFloatCmpLibcallPredicates(); -initDefaultLibCallNames(); +initDefaultLibCallImpls(); initLibcalls(TT, ExceptionModel, FloatABI, EABIVersion); } /// Rename the default libcall routine name for the specified libcall. - void setLibcallName(RTLIB::Libcall Call, const char *Name) { -LibcallRoutineNames[Call] = Name; - } - - void setLibcallName(ArrayRef Calls, const char *Name) { -for (auto Call : Calls) - setLibcallName(Call, Name); + void setLibcallImpl(RTLIB::Libcall Call, RTLIB::LibcallImpl Impl) { +LibcallImpls[Call] = Impl; } /// Get the libcall routine name for the specified libcall. + // FIXME: This should be removed. Only LibcallImpl should have a name. const char *getLibcallName(RTLIB::Libcall Call) const { -return LibcallRoutineNames[Call]; +return LibCallImplNames[LibcallImpls[Call]]; + } + + /// Get the libcall routine name for the specified libcall implementation. + const char *getLibcallImplName(RTLIB::LibcallImpl CallImpl) const { +return LibCallImplNames[CallImpl]; + } + + /// Return the lowering's selection of implementation call for \p Call + RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const { +return LibcallImpls[Call]; } /// Set the CallingConv that should be used for the specified libcall. + // FIXME: This should be a function of RTLIB::LibcallImpl void setLibcallCallingConv(RTLIB::Libcall Call, CallingConv::ID CC) { LibcallCallingConvs[Call] = CC; } /// Get the CallingConv that should be used for the specified libcall. + // FIXME: This should be a function of RTLIB::LibcallImpl CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const { return LibcallCallingConvs[Call]; } - ArrayRef getLibcallNames() const { -// Trim UNKNOWN_LIBCALL from the end -return ArrayRef(LibcallRoutineNames).drop_back(); + ArrayRef getLibcallImpls() const { +// Trim Unsupported from the start +return ArrayRef(LibcallImpls).drop_front(); } /// Get the comparison predicate that's to be used to test the result of the @@ -91,6 +103,7 @@ struct RuntimeLibcallsInfo { } // FIXME: Th
[llvm-branch-commits] [llvm] ARM: Add runtime libcall definitions for aebi memory functions (PR #144974)
llvmbot wrote: @llvm/pr-subscribers-llvm-ir Author: Matt Arsenault (arsenm) Changes Fix bypassing ordinary RuntimeLibcalls APIs for cases handled in ARMSelectionDAGInfo --- Full diff: https://github.com/llvm/llvm-project/pull/144974.diff 3 Files Affected: - (modified) llvm/include/llvm/IR/RuntimeLibcalls.td (+23) - (modified) llvm/lib/Target/ARM/ARMISelLowering.cpp (+17) - (modified) llvm/lib/Target/ARM/ARMSelectionDAGInfo.cpp (+10-8) ``diff diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index c910fce2edd80..71efecdf082af 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -357,6 +357,17 @@ multiclass LibmLongDoubleLibCall; } +// ARM EABI calls +def AEABI_MEMCPY4 : RuntimeLibcall; // Align 4 +def AEABI_MEMCPY8 : RuntimeLibcall; // Align 8 +def AEABI_MEMMOVE4 : RuntimeLibcall; +def AEABI_MEMMOVE8 : RuntimeLibcall; +def AEABI_MEMSET4 : RuntimeLibcall; +def AEABI_MEMSET8 : RuntimeLibcall; +def AEABI_MEMCLR : RuntimeLibcall; +def AEABI_MEMCLR4 : RuntimeLibcall; +def AEABI_MEMCLR8 : RuntimeLibcall; + // // Define implementation default libcalls // @@ -1134,8 +1145,20 @@ def __aeabi_uidivmod : RuntimeLibcallImpl; // CallingConv::ARM_AAP // Memory operations // RTABI chapter 4.3.4 def __aeabi_memcpy : RuntimeLibcallImpl; // CallingConv::ARM_AAPCS +def __aeabi_memcpy4 : RuntimeLibcallImpl; +def __aeabi_memcpy8 : RuntimeLibcallImpl; + def __aeabi_memmove : RuntimeLibcallImpl; // CallingConv::ARM_AAPCS +def __aeabi_memmove4 : RuntimeLibcallImpl; +def __aeabi_memmove8 : RuntimeLibcallImpl; + def __aeabi_memset : RuntimeLibcallImpl; // CallingConv::ARM_AAPCS +def __aeabi_memset4 : RuntimeLibcallImpl; +def __aeabi_memset8 : RuntimeLibcallImpl; + +def __aeabi_memclr : RuntimeLibcallImpl; +def __aeabi_memclr4 : RuntimeLibcallImpl; +def __aeabi_memclr8 : RuntimeLibcallImpl; // isTargetWindows() def __stoi64 : RuntimeLibcallImpl; // CallingConv::ARM_AAPCS_VFP diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 81b535e19bc71..478791699df88 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -704,6 +704,23 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_, {RTLIB::MEMCPY, RTLIB::__aeabi_memcpy, CallingConv::ARM_AAPCS}, {RTLIB::MEMMOVE, RTLIB::__aeabi_memmove, CallingConv::ARM_AAPCS}, {RTLIB::MEMSET, RTLIB::__aeabi_memset, CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMCPY4, RTLIB::__aeabi_memcpy4, + CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMCPY8, RTLIB::__aeabi_memcpy8, + CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMMOVE4, RTLIB::__aeabi_memmove4, + CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMMOVE8, RTLIB::__aeabi_memmove8, + CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMSET4, RTLIB::__aeabi_memset4, + CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMSET8, RTLIB::__aeabi_memset8, + CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMCLR, RTLIB::__aeabi_memclr, CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMCLR4, RTLIB::__aeabi_memclr4, + CallingConv::ARM_AAPCS}, + {RTLIB::AEABI_MEMCLR8, RTLIB::__aeabi_memclr8, + CallingConv::ARM_AAPCS}, }; for (const auto &LC : MemOpsLibraryCalls) { diff --git a/llvm/lib/Target/ARM/ARMSelectionDAGInfo.cpp b/llvm/lib/Target/ARM/ARMSelectionDAGInfo.cpp index 77f4782699c96..b4677a8bfb035 100644 --- a/llvm/lib/Target/ARM/ARMSelectionDAGInfo.cpp +++ b/llvm/lib/Target/ARM/ARMSelectionDAGInfo.cpp @@ -121,18 +121,20 @@ SDValue ARMSelectionDAGInfo::EmitSpecializedLibcall( Args.push_back(Entry); } - char const *FunctionNames[4][3] = { -{ "__aeabi_memcpy", "__aeabi_memcpy4", "__aeabi_memcpy8" }, -{ "__aeabi_memmove", "__aeabi_memmove4", "__aeabi_memmove8" }, -{ "__aeabi_memset", "__aeabi_memset4", "__aeabi_memset8" }, -{ "__aeabi_memclr", "__aeabi_memclr4", "__aeabi_memclr8" } - }; + static const RTLIB::Libcall FunctionImpls[4][3] = { + {RTLIB::MEMCPY, RTLIB::AEABI_MEMCPY4, RTLIB::AEABI_MEMCPY8}, + {RTLIB::MEMMOVE, RTLIB::AEABI_MEMMOVE4, RTLIB::AEABI_MEMMOVE8}, + {RTLIB::MEMSET, RTLIB::AEABI_MEMSET4, RTLIB::AEABI_MEMSET8}, + {RTLIB::AEABI_MEMCLR, RTLIB::AEABI_MEMCLR4, RTLIB::AEABI_MEMCLR8}}; + + RTLIB::Libcall NewLC = FunctionImpls[AEABILibcall][AlignVariant]; + TargetLowering::CallLoweringInfo CLI(DAG); CLI.setDebugLoc(dl) .setChain(Chain) .setLibCallee( - TLI->getLibcallCallingConv(LC), Type::getVoidTy(*DAG.getContext()), - DAG.getExternalSymbol(FunctionNames[AEABILibcall][AlignVariant], + TLI->getLibcallCallingConv(NewLC
[llvm-branch-commits] [llvm] Hexagon: Add libcall declarations for special memcpy (PR #144975)
llvmbot wrote: @llvm/pr-subscribers-llvm-ir Author: Matt Arsenault (arsenm) Changes HexagonSelectionDAGInfo was bypassing the ordinary RuntimeLibcallInfo handling for this case, so define a libcall for it and use it. --- Full diff: https://github.com/llvm/llvm-project/pull/144975.diff 3 Files Affected: - (modified) llvm/include/llvm/IR/RuntimeLibcalls.td (+6) - (modified) llvm/lib/IR/RuntimeLibcalls.cpp (+4) - (modified) llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp (+6-4) ``diff diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index 71efecdf082af..2efe823a760db 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -368,6 +368,9 @@ def AEABI_MEMCLR : RuntimeLibcall; def AEABI_MEMCLR4 : RuntimeLibcall; def AEABI_MEMCLR8 : RuntimeLibcall; +// Hexagon calls +def HEXAGON_MEMCPY_LIKELY_ALIGNED_MIN32BYTES_MULT8BYTES : RuntimeLibcall; + // // Define implementation default libcalls // @@ -1247,6 +1250,9 @@ def __hexagon_fast2_sqrtf : RuntimeLibcallImpl; // This is the only fast library function for sqrtd. def __hexagon_fast2_sqrtdf2 : RuntimeLibcallImpl; +def __hexagon_memcpy_likely_aligned_min32bytes_mult8bytes +: RuntimeLibcallImpl; + //===--===// // Mips16 Runtime Libcalls //===--===// diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp index 5fccb23e6c5ff..873ee6b509e2d 100644 --- a/llvm/lib/IR/RuntimeLibcalls.cpp +++ b/llvm/lib/IR/RuntimeLibcalls.cpp @@ -616,6 +616,10 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT, setLibcallImpl(RTLIB::SQRT_F32, RTLIB::__hexagon_fast2_sqrtf); else setLibcallImpl(RTLIB::SQRT_F32, RTLIB::__hexagon_sqrtf); + +setLibcallImpl( +RTLIB::HEXAGON_MEMCPY_LIKELY_ALIGNED_MIN32BYTES_MULT8BYTES, +RTLIB::__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes); } if (TT.getArch() == Triple::ArchType::msp430) diff --git a/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp b/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp index 1b724e8fcae91..610a81fe45c2f 100644 --- a/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp +++ b/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp @@ -41,18 +41,20 @@ SDValue HexagonSelectionDAGInfo::EmitTargetCodeForMemcpy( Entry.Node = Size; Args.push_back(Entry); - const char *SpecialMemcpyName = - "__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes"; + const char *SpecialMemcpyName = TLI.getLibcallName( + RTLIB::HEXAGON_MEMCPY_LIKELY_ALIGNED_MIN32BYTES_MULT8BYTES); const MachineFunction &MF = DAG.getMachineFunction(); bool LongCalls = MF.getSubtarget().useLongCalls(); unsigned Flags = LongCalls ? HexagonII::HMOTF_ConstExtended : 0; + CallingConv::ID CC = TLI.getLibcallCallingConv( + RTLIB::HEXAGON_MEMCPY_LIKELY_ALIGNED_MIN32BYTES_MULT8BYTES); + TargetLowering::CallLoweringInfo CLI(DAG); CLI.setDebugLoc(dl) .setChain(Chain) .setLibCallee( - TLI.getLibcallCallingConv(RTLIB::MEMCPY), - Type::getVoidTy(*DAG.getContext()), + CC, Type::getVoidTy(*DAG.getContext()), DAG.getTargetExternalSymbol( SpecialMemcpyName, TLI.getPointerTy(DAG.getDataLayout()), Flags), std::move(Args)) `` https://github.com/llvm/llvm-project/pull/144975 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] XCore: Declare libcalls used for align 4 memcpy (PR #144976)
llvmbot wrote: @llvm/pr-subscribers-llvm-ir Author: Matt Arsenault (arsenm) Changes This usage was hidden in XCoreSelectionDAGInfo and bypassed the usual libcall system, so define these for later use. --- Full diff: https://github.com/llvm/llvm-project/pull/144976.diff 3 Files Affected: - (modified) llvm/include/llvm/IR/RuntimeLibcalls.td (+9) - (modified) llvm/lib/IR/RuntimeLibcalls.cpp (+3) - (modified) llvm/lib/Target/XCore/XCoreSelectionDAGInfo.cpp (+8-5) ``diff diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index 2efe823a760db..57ad6f09e8b57 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -371,6 +371,9 @@ def AEABI_MEMCLR8 : RuntimeLibcall; // Hexagon calls def HEXAGON_MEMCPY_LIKELY_ALIGNED_MIN32BYTES_MULT8BYTES : RuntimeLibcall; +// XCore calls +def MEMCPY_ALIGN_4 : RuntimeLibcall; + // // Define implementation default libcalls // @@ -1544,6 +1547,12 @@ def _allrem : RuntimeLibcallImpl; // CallingConv::X86_StdCall def _aullrem : RuntimeLibcallImpl; // CallingConv::X86_StdCall def _allmul : RuntimeLibcallImpl; // CallingConv::X86_StdCall +//===--===// +// XCore Runtime Libcalls +//===--===// + +def __memcpy_4 : RuntimeLibcallImpl; + //===--===// // ZOS Runtime Libcalls //===--===// diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp index 873ee6b509e2d..0f92371f05529 100644 --- a/llvm/lib/IR/RuntimeLibcalls.cpp +++ b/llvm/lib/IR/RuntimeLibcalls.cpp @@ -627,4 +627,7 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT, if (TT.isSystemZ() && TT.isOSzOS()) setZOSLibCallNameOverrides(); + + if (TT.getArch() == Triple::ArchType::xcore) +setLibcallImpl(RTLIB::MEMCPY_ALIGN_4, RTLIB::__memcpy_4); } diff --git a/llvm/lib/Target/XCore/XCoreSelectionDAGInfo.cpp b/llvm/lib/Target/XCore/XCoreSelectionDAGInfo.cpp index bc34ab4319690..1bd92a2b49475 100644 --- a/llvm/lib/Target/XCore/XCoreSelectionDAGInfo.cpp +++ b/llvm/lib/Target/XCore/XCoreSelectionDAGInfo.cpp @@ -39,14 +39,17 @@ SDValue XCoreSelectionDAGInfo::EmitTargetCodeForMemcpy( Entry.Node = Src; Args.push_back(Entry); Entry.Node = Size; Args.push_back(Entry); +const char *MemcpyAlign4Name = TLI.getLibcallName(RTLIB::MEMCPY_ALIGN_4); +CallingConv::ID CC = TLI.getLibcallCallingConv(RTLIB::MEMCPY_ALIGN_4); + TargetLowering::CallLoweringInfo CLI(DAG); CLI.setDebugLoc(dl) .setChain(Chain) -.setLibCallee(TLI.getLibcallCallingConv(RTLIB::MEMCPY), - Type::getVoidTy(*DAG.getContext()), - DAG.getExternalSymbol( - "__memcpy_4", TLI.getPointerTy(DAG.getDataLayout())), - std::move(Args)) +.setLibCallee( +CC, Type::getVoidTy(*DAG.getContext()), +DAG.getExternalSymbol(MemcpyAlign4Name, + TLI.getPointerTy(DAG.getDataLayout())), +std::move(Args)) .setDiscardResult(); std::pair CallResult = TLI.LowerCallTo(CLI); `` https://github.com/llvm/llvm-project/pull/144976 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] AArch64: Add libcall impl declarations for __arm_sc* memory functions (PR #144977)
https://github.com/arsenm ready_for_review https://github.com/llvm/llvm-project/pull/144977 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] TableGen: Allow defining sets of runtime libraries (PR #144978)
https://github.com/arsenm edited https://github.com/llvm/llvm-project/pull/144978 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] ARM: Add runtime libcall definitions for aebi memory functions (PR #144974)
https://github.com/arsenm ready_for_review https://github.com/llvm/llvm-project/pull/144974 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] TableGen: Generate enum for runtime libcall implementations (PR #144973)
https://github.com/arsenm ready_for_review https://github.com/llvm/llvm-project/pull/144973 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] XCore: Declare libcalls used for align 4 memcpy (PR #144976)
https://github.com/arsenm ready_for_review https://github.com/llvm/llvm-project/pull/144976 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] AArch64: Add libcall impl declarations for __arm_sc* memory functions (PR #144977)
llvmbot wrote: @llvm/pr-subscribers-llvm-ir Author: Matt Arsenault (arsenm) Changes These were bypassing the ordinary libcall emission mechanism. Make sure we have entries in RuntimeLibcalls, which should include all possible calls the compiler could emit. Fixes not emitting the # prefix in the arm64ec case. --- Full diff: https://github.com/llvm/llvm-project/pull/144977.diff 4 Files Affected: - (modified) llvm/include/llvm/IR/RuntimeLibcalls.td (+9) - (modified) llvm/lib/IR/RuntimeLibcalls.cpp (+10-1) - (modified) llvm/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp (+7-8) - (modified) llvm/test/CodeGen/AArch64/arm64ec-builtins.ll (+3-6) ``diff diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index 57ad6f09e8b57..1d9f02dcf8ba8 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -357,6 +357,11 @@ multiclass LibmLongDoubleLibCall; } +// AArch64 calls +def SC_MEMCPY : RuntimeLibcall; +def SC_MEMMOVE : RuntimeLibcall; +def SC_MEMSET : RuntimeLibcall; + // ARM EABI calls def AEABI_MEMCPY4 : RuntimeLibcall; // Align 4 def AEABI_MEMCPY8 : RuntimeLibcall; // Align 8 @@ -985,6 +990,10 @@ defset list AArch64LibcallImpls = { defm __aarch64_ldeor#MemSize : AtomicOrderSizeLibcallImpl<"OUTLINE_ATOMIC_LDEOR"#MemSize>; } + + def __arm_sc_memcpy : RuntimeLibcallImpl; + def __arm_sc_memmove : RuntimeLibcallImpl; + def __arm_sc_memset : RuntimeLibcallImpl; } foreach libcall = AArch64LibcallImpls in { diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp index 0f92371f05529..67f872b4574b1 100644 --- a/llvm/lib/IR/RuntimeLibcalls.cpp +++ b/llvm/lib/IR/RuntimeLibcalls.cpp @@ -521,8 +521,17 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT, } if (TT.isAArch64()) { -if (TT.isWindowsArm64EC()) +if (TT.isWindowsArm64EC()) { setWindowsArm64LibCallNameOverrides(); + setLibcallImpl(RTLIB::SC_MEMCPY, RTLIB::arm64ec___arm_sc_memcpy); + setLibcallImpl(RTLIB::SC_MEMMOVE, RTLIB::arm64ec___arm_sc_memmove); + setLibcallImpl(RTLIB::SC_MEMSET, RTLIB::arm64ec___arm_sc_memset); +} else { + setLibcallImpl(RTLIB::SC_MEMCPY, RTLIB::__arm_sc_memcpy); + setLibcallImpl(RTLIB::SC_MEMMOVE, RTLIB::__arm_sc_memmove); + setLibcallImpl(RTLIB::SC_MEMSET, RTLIB::__arm_sc_memset); +} + setAArch64LibcallNames(*this, TT); } else if (TT.isARM() || TT.isThumb()) { setARMLibcallNames(*this, TT, FloatABI, EABIVersion); diff --git a/llvm/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp b/llvm/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp index 90f6fc2ea664b..d719f234b27f7 100644 --- a/llvm/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64SelectionDAGInfo.cpp @@ -164,35 +164,34 @@ SDValue AArch64SelectionDAGInfo::EmitStreamingCompatibleMemLibCall( const AArch64Subtarget &STI = DAG.getMachineFunction().getSubtarget(); const AArch64TargetLowering *TLI = STI.getTargetLowering(); - SDValue Symbol; TargetLowering::ArgListEntry DstEntry; DstEntry.Ty = PointerType::getUnqual(*DAG.getContext()); DstEntry.Node = Dst; TargetLowering::ArgListTy Args; Args.push_back(DstEntry); - EVT PointerVT = TLI->getPointerTy(DAG.getDataLayout()); + RTLIB::Libcall NewLC; switch (LC) { case RTLIB::MEMCPY: { +NewLC = RTLIB::SC_MEMCPY; TargetLowering::ArgListEntry Entry; Entry.Ty = PointerType::getUnqual(*DAG.getContext()); -Symbol = DAG.getExternalSymbol("__arm_sc_memcpy", PointerVT); Entry.Node = Src; Args.push_back(Entry); break; } case RTLIB::MEMMOVE: { +NewLC = RTLIB::SC_MEMMOVE; TargetLowering::ArgListEntry Entry; Entry.Ty = PointerType::getUnqual(*DAG.getContext()); -Symbol = DAG.getExternalSymbol("__arm_sc_memmove", PointerVT); Entry.Node = Src; Args.push_back(Entry); break; } case RTLIB::MEMSET: { +NewLC = RTLIB::SC_MEMSET; TargetLowering::ArgListEntry Entry; Entry.Ty = Type::getInt32Ty(*DAG.getContext()); -Symbol = DAG.getExternalSymbol("__arm_sc_memset", PointerVT); Src = DAG.getZExtOrTrunc(Src, DL, MVT::i32); Entry.Node = Src; Args.push_back(Entry); @@ -202,17 +201,17 @@ SDValue AArch64SelectionDAGInfo::EmitStreamingCompatibleMemLibCall( return SDValue(); } + EVT PointerVT = TLI->getPointerTy(DAG.getDataLayout()); + SDValue Symbol = DAG.getExternalSymbol(TLI->getLibcallName(NewLC), PointerVT); TargetLowering::ArgListEntry SizeEntry; SizeEntry.Node = Size; SizeEntry.Ty = DAG.getDataLayout().getIntPtrType(*DAG.getContext()); Args.push_back(SizeEntry); - assert(Symbol->getOpcode() == ISD::ExternalSymbol && - "Function name is not set"); TargetLowering::CallLoweringInfo CLI(DAG); PointerType *RetTy = PointerType::getUnqual(*DAG.getContext()); CLI.setDebugLoc(DL).setChain(Chain).setLibCallee( - TLI-
[llvm-branch-commits] [llvm] TableGen: Allow defining sets of runtime libraries (PR #144978)
llvmbot wrote: @llvm/pr-subscribers-llvm-ir Author: Matt Arsenault (arsenm) Changes Add a way to define a SystemLibrary for a complete set of libcalls, subdivided by a predicate based on the triple. Libraries can be defined using dag set operations, and the prior default set can be subtracted from and added to (though I think eventually all targets should move to explicit opt-ins. We're still doing things like reporting ppcf128 libcalls as available dy default on all targets). Start migrating some of the easier targets to only use the new system. Targets that don't define a SystemLibrary are still manually mutating a table set to the old defaults. --- Patch is 71.70 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/144978.diff 9 Files Affected: - (modified) llvm/include/llvm/IR/RuntimeLibcalls.h (+2-8) - (modified) llvm/include/llvm/IR/RuntimeLibcalls.td (+309-184) - (modified) llvm/include/llvm/IR/RuntimeLibcallsImpl.td (+36) - (added) llvm/include/llvm/TableGen/SetTheory.td (+27) - (modified) llvm/lib/IR/RuntimeLibcalls.cpp (+6-121) - (added) llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td (+60) - (added) llvm/test/TableGen/RuntimeLibcallEmitter-nested-predicates-error.td (+18) - (modified) llvm/test/TableGen/RuntimeLibcallEmitter.td (+174-11) - (modified) llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp (+257-94) ``diff diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h index 912715fbf6b19..d69c23753da7a 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.h +++ b/llvm/include/llvm/IR/RuntimeLibcalls.h @@ -52,7 +52,6 @@ struct RuntimeLibcallsInfo { FloatABI::ABIType FloatABI = FloatABI::Default, EABI EABIVersion = EABI::Default) { initSoftFloatCmpLibcallPredicates(); -initDefaultLibCallImpls(); initLibcalls(TT, ExceptionModel, FloatABI, EABIVersion); } @@ -97,6 +96,7 @@ struct RuntimeLibcallsInfo { /// Get the comparison predicate that's to be used to test the result of the /// comparison libcall against zero. This should only be used with /// floating-point compare libcalls. + // FIXME: This should be a function of RTLIB::LibcallImpl CmpInst::Predicate getSoftFloatCmpLibcallPredicate(RTLIB::Libcall Call) const { return SoftFloatCompareLibcallPredicates[Call]; @@ -172,13 +172,7 @@ struct RuntimeLibcallsInfo { void initDefaultLibCallImpls(); /// Generated by tablegen. - void setPPCLibCallNameOverrides(); - - /// Generated by tablegen. - void setZOSLibCallNameOverrides(); - - /// Generated by tablegen. - void setWindowsArm64LibCallNameOverrides(); + void setTargetRuntimeLibcallSets(const Triple &TT); void initSoftFloatCmpLibcallPredicates(); diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index 1d9f02dcf8ba8..e24b4c928b421 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -891,6 +891,17 @@ def calloc : RuntimeLibcallImpl; } // End let IsDefault = true } // End defset DefaultRuntimeLibcallImpls +defvar DefaultLibCalls = +!foreach(entry, DefaultRuntimeLibcallImpls, entry.Provides); + +defvar DefaultRuntimeLibcallImpls_f128 = +!filter(entry, DefaultRuntimeLibcallImpls, +!match(!cast(entry.Provides), "_F128")); + +defvar DefaultRuntimeLibcallImpls_atomic = +!filter(entry, DefaultRuntimeLibcallImpls, +!match(!cast(entry.Provides), "ATOMIC")); + // // Define implementation other libcalls // @@ -915,58 +926,61 @@ def _Unwind_SjLj_Resume : RuntimeLibcallImpl; // F128 libm Runtime Libcalls //===--===// -def logf128 : RuntimeLibcallImpl; -def log2f128 : RuntimeLibcallImpl; -def log10f128 : RuntimeLibcallImpl; -def expf128 : RuntimeLibcallImpl; -def exp2f128 : RuntimeLibcallImpl; -def exp10f128 : RuntimeLibcallImpl; -def sinf128 : RuntimeLibcallImpl; -def cosf128 : RuntimeLibcallImpl; -def tanf128 : RuntimeLibcallImpl; -def tanhf128 : RuntimeLibcallImpl; -def sincosf128 : RuntimeLibcallImpl; -def powf128 : RuntimeLibcallImpl; -def fminf128 : RuntimeLibcallImpl; -def fmaxf128 : RuntimeLibcallImpl; -def fmodf128 : RuntimeLibcallImpl; -def sqrtf128 : RuntimeLibcallImpl; -def ceilf128 : RuntimeLibcallImpl; -def floorf128 : RuntimeLibcallImpl; -def truncf128 : RuntimeLibcallImpl; -def roundf128 : RuntimeLibcallImpl; -def lroundf128 : RuntimeLibcallImpl; -def llroundf128 : RuntimeLibcallImpl; -def rintf128 : RuntimeLibcallImpl; -def lrintf128 : RuntimeLibcallImpl; -def llrintf128 : RuntimeLibcallImpl; -def nearbyintf128 : RuntimeLibcallImpl; -def fmaf128 : RuntimeLibcallImpl; -def frexpf128 : RuntimeLibcallImpl; - -def cbrtf128 : RuntimeLibcallImpl; -def fminimumf128 : R
[llvm-branch-commits] [llvm] TableGen: Allow defining sets of runtime libraries (PR #144978)
https://github.com/arsenm ready_for_review https://github.com/llvm/llvm-project/pull/144978 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] RuntimeLibcalls: Associate calling convention with libcall impls (PR #144979)
llvmbot wrote: @llvm/pr-subscribers-llvm-ir Author: Matt Arsenault (arsenm) Changes Instead of associating the libcall with the RTLIB::Libcall, put it into a table indexed by the RTLIB::LibcallImpl. The LibcallImpls should contain all ABI details for a particular implementation, not the abstract Libcall. In the future the wrappers in terms of the RTLIB::Libcall should be removed. --- Full diff: https://github.com/llvm/llvm-project/pull/144979.diff 6 Files Affected: - (modified) llvm/include/llvm/CodeGen/TargetLowering.h (+14-2) - (modified) llvm/include/llvm/IR/RuntimeLibcalls.h (+23-9) - (modified) llvm/lib/IR/RuntimeLibcalls.cpp (+42-28) - (modified) llvm/lib/Target/ARM/ARMISelLowering.cpp (+15-9) - (modified) llvm/lib/Target/Lanai/LanaiISelLowering.cpp (+2-2) - (modified) llvm/lib/Target/MSP430/MSP430ISelLowering.cpp (+2-1) ``diff diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index 69ae4f80297d5..fa08eb64642de 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -3562,6 +3562,11 @@ class LLVM_ABI TargetLoweringBase { Libcalls.setLibcallImpl(Call, Impl); } + /// Get the libcall impl routine name for the specified libcall. + RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const { +return Libcalls.getLibcallImpl(Call); + } + /// Get the libcall routine name for the specified libcall. const char *getLibcallName(RTLIB::Libcall Call) const { return Libcalls.getLibcallName(Call); @@ -3584,11 +3589,18 @@ class LLVM_ABI TargetLoweringBase { } /// Set the CallingConv that should be used for the specified libcall. - void setLibcallCallingConv(RTLIB::Libcall Call, CallingConv::ID CC) { -Libcalls.setLibcallCallingConv(Call, CC); + void setLibcallImplCallingConv(RTLIB::LibcallImpl Call, CallingConv::ID CC) { +Libcalls.setLibcallImplCallingConv(Call, CC); + } + + /// Get the CallingConv that should be used for the specified libcall + /// implementation. + CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const { +return Libcalls.getLibcallImplCallingConv(Call); } /// Get the CallingConv that should be used for the specified libcall. + // FIXME: Remove this wrapper and directly use the used LibcallImpl CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const { return Libcalls.getLibcallCallingConv(Call); } diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h index d69c23753da7a..dce16ab99171f 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.h +++ b/llvm/include/llvm/IR/RuntimeLibcalls.h @@ -37,6 +37,10 @@ template <> struct enum_iteration_traits { static constexpr bool is_iterable = true; }; +template <> struct enum_iteration_traits { + static constexpr bool is_iterable = true; +}; + namespace RTLIB { // Return an iterator over all Libcall values. @@ -44,6 +48,10 @@ static inline auto libcalls() { return enum_seq(static_cast(0), RTLIB::UNKNOWN_LIBCALL); } +static inline auto libcall_impls() { + return enum_seq(static_cast(1), RTLIB::NumLibcallImpls); +} + /// A simple container for information about the supported runtime calls. struct RuntimeLibcallsInfo { explicit RuntimeLibcallsInfo( @@ -76,16 +84,21 @@ struct RuntimeLibcallsInfo { return LibcallImpls[Call]; } - /// Set the CallingConv that should be used for the specified libcall. - // FIXME: This should be a function of RTLIB::LibcallImpl - void setLibcallCallingConv(RTLIB::Libcall Call, CallingConv::ID CC) { -LibcallCallingConvs[Call] = CC; + /// Set the CallingConv that should be used for the specified libcall + /// implementation + void setLibcallImplCallingConv(RTLIB::LibcallImpl Call, CallingConv::ID CC) { +LibcallImplCallingConvs[Call] = CC; } - /// Get the CallingConv that should be used for the specified libcall. - // FIXME: This should be a function of RTLIB::LibcallImpl + // FIXME: Remove this wrapper in favor of directly using + // getLibcallImplCallingConv CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const { -return LibcallCallingConvs[Call]; +return LibcallImplCallingConvs[LibcallImpls[Call]]; + } + + /// Get the CallingConv that should be used for the specified libcall. + CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const { +return LibcallImplCallingConvs[Call]; } ArrayRef getLibcallImpls() const { @@ -130,8 +143,9 @@ struct RuntimeLibcallsInfo { static_assert(static_cast(CallingConv::C) == 0, "default calling conv should be encoded as 0"); - /// Stores the CallingConv that should be used for each libcall. - CallingConv::ID LibcallCallingConvs[RTLIB::UNKNOWN_LIBCALL] = {}; + /// Stores the CallingConv that should be used for each libcall + /// implementation.; + CallingConv::ID LibcallImplCallingConvs[RTLIB::NumLibcallImpls] =
[llvm-branch-commits] [llvm] RuntimeLibcalls: Associate calling convention with libcall impls (PR #144979)
https://github.com/arsenm ready_for_review https://github.com/llvm/llvm-project/pull/144979 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] TableGen: Handle setting runtime libcall calling conventions (PR #144980)
llvmbot wrote: @llvm/pr-subscribers-llvm-ir Author: Matt Arsenault (arsenm) Changes Allow associating a non-default CallingConv with a set of library functions, and applying a default for a SystemLibrary. I also wanted to be able to apply a default calling conv to a RuntimeLibcallImpl, but that turned out to be annoying so leave it for later. --- Patch is 32.05 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/144980.diff 6 Files Affected: - (modified) llvm/include/llvm/IR/RuntimeLibcalls.td (+128-12) - (modified) llvm/include/llvm/IR/RuntimeLibcallsImpl.td (+25-1) - (modified) llvm/lib/IR/RuntimeLibcalls.cpp (-141) - (added) llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td (+85) - (modified) llvm/test/TableGen/RuntimeLibcallEmitter.td (+13-6) - (modified) llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp (+93-18) ``diff diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index e24b4c928b421..03ac9f5926f87 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -1254,11 +1254,12 @@ def __gnu_h2f_ieee : RuntimeLibcallImpl; //===--===// // Several of the runtime library functions use a special calling conv -def __divmodqi4 : RuntimeLibcallImpl; // CallingConv::AVR_BUILTIN -def __divmodhi4 : RuntimeLibcallImpl; // CallingConv::AVR_BUILTIN +def __divmodqi4 : RuntimeLibcallImpl; +def __divmodhi4 : RuntimeLibcallImpl; +def __udivmodqi4 : RuntimeLibcallImpl; +def __udivmodhi4 : RuntimeLibcallImpl; + //def __divmodsi4 : RuntimeLibcallImpl; -def __udivmodqi4 : RuntimeLibcallImpl; // CallingConv::AVR_BUILTIN -def __udivmodhi4 : RuntimeLibcallImpl; // CallingConv::AVR_BUILTIN //def __udivmodsi4 : RuntimeLibcallImpl; // Standard sinf/cosf name replaced with "sin" and "cos". Define a @@ -1284,9 +1285,12 @@ def AVRSystemLibrary // Standard f64 names are replaced sin, cos, sinf, cosf), - __divmodqi4, __divmodhi4, __divmodsi4, __udivmodqi4, __udivmodhi4, - __udivmodsi4, - + // Several of the runtime library functions use a special calling + // conv + LibcallsWithCC<(add __divmodqi4, __divmodhi4, __udivmodqi4, + __udivmodhi4), + AVR_BUILTIN>, + __divmodsi4, __udivmodsi4, // Trigonometric rtlib functions avr_sin, avr_cos)>; @@ -1509,6 +1513,117 @@ def __mspabi_mpyll : RuntimeLibcallImpl; // setLibcallCallingConv(MUL_I64, CallingConv::MSP430_BUILTIN); +def isMSP430 : RuntimeLibcallPredicate<"TT.getArch() == Triple::msp430">; + +defvar MSP430DefaultOptOut = [ + __addsf3, __divsf3, __extendsfdf2, __truncdfsf2, __fixsfsi, + __fixsfdi, __fixunssfsi, __mulsf3, __eqsf2, __gesf2, __gtsf2, + __divhi3, __divsi3, __ashlsi3, __floatsidf, __floatsisf, + __ashrsi3, __modhi3, __udivsi3, __fixdfsi, __fixunssfdi, + __udivhi3, __umodsi3, __nesf2, __lesf2, __floatundisf, + __fixdfdi, __fixunsdfsi, __modsi3, __floatunsisf, + __fixunsdfdi, __ltsf2, __floatdisf, __floatdidf, + __lshrsi3, __subsf3, __umodhi3, __floatunsidf, + __floatundidf +]; + +// EABI Libcalls - EABI Section 6.2 +def MSP430SystemLibrary +: SystemRuntimeLibrary, + __mspabi_cmpf__oeq, + __mspabi_cmpf__une, + __mspabi_cmpf__oge, + __mspabi_cmpf__olt, + __mspabi_cmpf__ole, + __mspabi_cmpf__ogt, + + // Floating point arithmetic - EABI Table 8 + LibcallsWithCC<(add __mspabi_addd, + __mspabi_subd, + __mspabi_mpyd, + __mspabi_divd), MSP430_BUILTIN>, + + __mspabi_addf, + __mspabi_subf, + __mspabi_mpyf, + __mspabi_divf, + + // The following are NOT implemented in libgcc + // __mspabi_negd, + // __mspabi_negf, + + // Universal Integer Operations - EABI Table 9 + __mspabi_divi, + __mspabi_divli, + LibcallsWithCC<(add __mspabi_divlli), MSP430_BUILTIN>, + __mspabi_divu, + __mspabi_divul, + LibcallsWithCC<(add __mspabi_divull), MSP430_BUILTIN>, + __mspabi_remi, + __mspabi_remli, + LibcallsWithCC<(add __mspabi_remlli), MSP430_BUILTIN>, + __mspabi_remu, + __mspabi_remul, + LibcallsWithCC<(add __mspabi_remull), MSP430_BUILTIN>, + + // Bitwise Operations - EABI Table 10 + // TODO: __mspabi_[srli/srai/slli] ARE implemented in libgcc + __mspabi_srll, + __mspabi_sral, + __mspabi_slll + // __mspabi_[srlll/srall/s/rlli/rlll] are NOT implemented in libgcc + ) +>; + //===--===// // NVPTX Runtime Libcalls //===--===// @@ -1655,11 +1770,12 @@ def _Q_ulltoq : RuntimeLibcallImpl; //===-
[llvm-branch-commits] [lld] [llvm] release/20.x: [lld][WebAssembly] Support for the custom-page-sizes WebAssembly proposal (#128942) (PR #129762)
sunfishcode wrote: The patch changes LLVM's public API, so it's not suitable for backporting. This feature will ship in the next release, LLVM 21. https://github.com/llvm/llvm-project/pull/129762 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [lld] [llvm] release/20.x: [lld][WebAssembly] Support for the custom-page-sizes WebAssembly proposal (#128942) (PR #129762)
https://github.com/sunfishcode closed https://github.com/llvm/llvm-project/pull/129762 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [DirectX] Add static sampler support to root signature (PR #143422)
https://github.com/joaosaffran edited https://github.com/llvm/llvm-project/pull/143422 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [HLSL] Add descriptor table metadata parsing (PR #142492)
https://github.com/joaosaffran edited https://github.com/llvm/llvm-project/pull/142492 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [DirectX] Add static sampler support to root signature (PR #143422)
https://github.com/joaosaffran edited https://github.com/llvm/llvm-project/pull/143422 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [flang] [mlir] [flang][OpenMP][NFC] remove globals with mlir::StateStack (PR #144898)
https://github.com/skatrak edited https://github.com/llvm/llvm-project/pull/144898 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [flang] [mlir] [flang][OpenMP][NFC] remove globals with mlir::StateStack (PR #144898)
@@ -200,9 +201,41 @@ class HostEvalInfo { /// the handling of the outer region by keeping a stack of information /// structures, but it will probably still require some further work to support /// reverse offloading. -static llvm::SmallVector hostEvalInfo; -static llvm::SmallVector -sectionsStack; +class HostEvalInfoStackFrame +: public mlir::StateStackFrameBase { +public: + MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(HostEvalInfoStackFrame) + + HostEvalInfo info; +}; + +static HostEvalInfo * +getHostEvalInfoStackTop(lower::AbstractConverter &converter) { + HostEvalInfoStackFrame *frame = + converter.getStateStack().getStackTop(); + return frame ? &frame->info : nullptr; +} + +/// Stack frame for storing the OpenMPSectionsConstruct currently being +/// processed so that it can be refered to when lowering the construct. skatrak wrote: ```suggestion /// processed so that it can be referred to when lowering the construct. ``` https://github.com/llvm/llvm-project/pull/144898 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [flang] [mlir] [flang][OpenMP][NFC] remove globals with mlir::StateStack (PR #144898)
https://github.com/skatrak approved this pull request. Thank you Tom for working on this, I think it's a very nice improvement! LGTM. https://github.com/llvm/llvm-project/pull/144898 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [flang] [mlir] [flang][OpenMP][NFC] remove globals with mlir::StateStack (PR #144898)
@@ -2224,10 +2260,13 @@ genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable, lower::pft::Evaluation &eval, mlir::Location loc, const ConstructQueue &queue, ConstructQueue::const_iterator item) { - assert(!sectionsStack.empty()); + const parser::OpenMPSectionsConstruct *sectionsConstruct = + getSectionsConstructStackTop(converter); + assert(sectionsConstruct); + const auto §ionBlocks = - std::get(sectionsStack.back()->t); - sectionsStack.pop_back(); + std::get(sectionsConstruct->t); + converter.getStateStack().stackPop(); skatrak wrote: Nit: Wouldn't it be possible to let this call be handled by the same function that pushes the stack frame? We could potentially use `SaveStateStack` then. https://github.com/llvm/llvm-project/pull/144898 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [flang] [mlir] [flang][OpenMP][NFC] remove globals with mlir::StateStack (PR #144898)
@@ -1818,16 +1852,17 @@ static void genTargetClauses( llvm::SmallVectorImpl &hasDeviceAddrSyms, llvm::SmallVectorImpl &isDevicePtrSyms, llvm::SmallVectorImpl &mapSyms) { + HostEvalInfo *hostEvalInfo = getHostEvalInfoStackTop(converter); ClauseProcessor cp(converter, semaCtx, clauses); cp.processBare(clauseOps); cp.processDefaultMap(stmtCtx, defaultMaps); cp.processDepend(symTable, stmtCtx, clauseOps); cp.processDevice(stmtCtx, clauseOps); cp.processHasDeviceAddr(stmtCtx, clauseOps, hasDeviceAddrSyms); - if (!hostEvalInfo.empty()) { + if (hostEvalInfo) { skatrak wrote: Nit: For consistency with `genBodyOfTargetOp`, and general conciseness ```suggestion if (HostEvalInfo *hostEvalInfo = getHostEvalInfoStackTop(converter)) { ``` https://github.com/llvm/llvm-project/pull/144898 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [flang] [mlir] [flang][OpenMP][NFC] remove globals with mlir::StateStack (PR #144898)
@@ -2224,10 +2260,13 @@ genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable, lower::pft::Evaluation &eval, mlir::Location loc, const ConstructQueue &queue, ConstructQueue::const_iterator item) { - assert(!sectionsStack.empty()); + const parser::OpenMPSectionsConstruct *sectionsConstruct = + getSectionsConstructStackTop(converter); + assert(sectionsConstruct); skatrak wrote: Nit: Add small message to the assert. https://github.com/llvm/llvm-project/pull/144898 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-doc] add support for concepts (PR #144430)
https://github.com/evelez7 updated https://github.com/llvm/llvm-project/pull/144430 >From 9754f70f3255e250c51c177bb00ef955e8d92f9c Mon Sep 17 00:00:00 2001 From: Erick Velez Date: Mon, 16 Jun 2025 10:50:35 -0700 Subject: [PATCH] add serializeArray for infos with URLs --- clang-tools-extra/clang-doc/BitcodeReader.cpp | 72 +++ clang-tools-extra/clang-doc/BitcodeWriter.cpp | 44 ++- clang-tools-extra/clang-doc/BitcodeWriter.h | 12 +- clang-tools-extra/clang-doc/HTMLGenerator.cpp | 4 + .../clang-doc/HTMLMustacheGenerator.cpp | 2 + clang-tools-extra/clang-doc/JSONGenerator.cpp | 54 clang-tools-extra/clang-doc/MDGenerator.cpp | 5 + clang-tools-extra/clang-doc/Mapper.cpp| 4 + clang-tools-extra/clang-doc/Mapper.h | 1 + .../clang-doc/Representation.cpp | 13 ++ clang-tools-extra/clang-doc/Representation.h | 26 +++- clang-tools-extra/clang-doc/Serialize.cpp | 90 + clang-tools-extra/clang-doc/Serialize.h | 4 + clang-tools-extra/clang-doc/YAMLGenerator.cpp | 2 + .../test/clang-doc/json/class-requires.cpp| 18 +-- .../clang-doc/json/compound-constraints.cpp | 121 ++ .../test/clang-doc/json/concept.cpp | 48 +++ .../test/clang-doc/json/function-requires.cpp | 36 +++--- .../unittests/clang-doc/BitcodeTest.cpp | 2 + 19 files changed, 502 insertions(+), 56 deletions(-) create mode 100644 clang-tools-extra/test/clang-doc/json/compound-constraints.cpp diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp index 35058abab0663..5b70280e7dba8 100644 --- a/clang-tools-extra/clang-doc/BitcodeReader.cpp +++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp @@ -92,6 +92,7 @@ static llvm::Error decodeRecord(const Record &R, InfoType &Field, case InfoType::IT_default: case InfoType::IT_enum: case InfoType::IT_typedef: + case InfoType::IT_concept: Field = IT; return llvm::Error::success(); } @@ -108,6 +109,7 @@ static llvm::Error decodeRecord(const Record &R, FieldId &Field, case FieldId::F_type: case FieldId::F_child_namespace: case FieldId::F_child_record: + case FieldId::F_concept: case FieldId::F_default: Field = F; return llvm::Error::success(); @@ -391,6 +393,29 @@ static llvm::Error parseRecord(const Record &R, unsigned ID, "invalid field for TemplateParamInfo"); } +static llvm::Error parseRecord(const Record &R, unsigned ID, + llvm::StringRef Blob, ConceptInfo *I) { + switch (ID) { + case CONCEPT_USR: +return decodeRecord(R, I->USR, Blob); + case CONCEPT_NAME: +return decodeRecord(R, I->Name, Blob); + case CONCEPT_IS_TYPE: +return decodeRecord(R, I->IsType, Blob); + case CONCEPT_CONSTRAINT_EXPRESSION: +return decodeRecord(R, I->ConstraintExpression, Blob); + } + llvm_unreachable("invalid field for ConceptInfo"); +} + +static llvm::Error parseRecord(const Record &R, unsigned ID, + llvm::StringRef Blob, ConstraintInfo *I) { + if (ID == CONSTRAINT_EXPRESSION) +return decodeRecord(R, I->Expression, Blob); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid field for ConstraintInfo"); +} + template static llvm::Expected getCommentInfo(T I) { return llvm::createStringError(llvm::inconvertibleErrorCode(), "invalid type cannot contain CommentInfo"); @@ -429,6 +454,10 @@ template <> llvm::Expected getCommentInfo(CommentInfo *I) { return I->Children.back().get(); } +template <> llvm::Expected getCommentInfo(ConceptInfo *I) { + return &I->Description.emplace_back(); +} + // When readSubBlock encounters a TypeInfo sub-block, it calls addTypeInfo on // the parent block to set it. The template specializations define what to do // for each supported parent block. @@ -584,6 +613,18 @@ template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) { } } +template <> +llvm::Error addReference(ConstraintInfo *I, Reference &&R, FieldId F) { + switch (F) { + case FieldId::F_concept: +I->ConceptRef = std::move(R); +return llvm::Error::success(); + default: +return llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid type cannot contain Reference"); + } +} + template static void addChild(T I, ChildInfoType &&R) { llvm::errs() << "invalid child type for info"; @@ -600,6 +641,9 @@ template <> void addChild(NamespaceInfo *I, EnumInfo &&R) { template <> void addChild(NamespaceInfo *I, TypedefInfo &&R) { I->Children.Typedefs.emplace_back(std::move(R)); } +template <> void addChild(NamespaceInfo *I, ConceptInfo &&R) { + I->Children.Concepts.emplace_back(std::move(R)); +} // Record children: template <> void addChild(RecordInfo *I, FunctionInfo &&R) { @@ -6
[llvm-branch-commits] [llvm] RuntimeLibcalls: Pass in exception handling type (PR #144696)
arsenm wrote: ### Merge activity * **Jun 19, 9:57 AM UTC**: A user started a stack merge that includes this pull request via [Graphite](https://app.graphite.dev/github/pr/llvm/llvm-project/144696). https://github.com/llvm/llvm-project/pull/144696 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] AMDGPU/GlobalISel: Add waterfall lowering in regbanklegalize (PR #142790)
petar-avramovic wrote: ping https://github.com/llvm/llvm-project/pull/142790 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: prevent false positives due to jump tables (PR #138884)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/138884 >From e72572049530d58764cff1ce1081c1765838188a Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Tue, 6 May 2025 11:31:03 +0300 Subject: [PATCH] [BOLT] Gadget scanner: prevent false positives due to jump tables As part of PAuth hardening, AArch64 LLVM backend can use a special BR_JumpTable pseudo (enabled by -faarch64-jump-table-hardening Clang option) which is expanded in the AsmPrinter into a contiguous sequence without unsafe instructions in the middle. This commit adds another target-specific callback to MCPlusBuilder to make it possible to inhibit false positives for known-safe jump table dispatch sequences. Without special handling, the branch instruction is likely to be reported as a non-protected call (as its destination is not produced by an auth instruction, PC-relative address materialization, etc.) and possibly as a tail call being performed with unsafe link register (as the detection whether the branch instruction is a tail call is an heuristic). For now, only the specific instruction sequence used by the AArch64 LLVM backend is matched. --- bolt/include/bolt/Core/MCInstUtils.h | 9 + bolt/include/bolt/Core/MCPlusBuilder.h| 14 + bolt/lib/Core/MCInstUtils.cpp | 20 + bolt/lib/Passes/PAuthGadgetScanner.cpp| 10 + .../Target/AArch64/AArch64MCPlusBuilder.cpp | 73 ++ .../AArch64/gs-pauth-jump-table.s | 703 ++ 6 files changed, 829 insertions(+) create mode 100644 bolt/test/binary-analysis/AArch64/gs-pauth-jump-table.s diff --git a/bolt/include/bolt/Core/MCInstUtils.h b/bolt/include/bolt/Core/MCInstUtils.h index 50b7d56470c99..33d36cccbcfff 100644 --- a/bolt/include/bolt/Core/MCInstUtils.h +++ b/bolt/include/bolt/Core/MCInstUtils.h @@ -154,6 +154,15 @@ class MCInstReference { return nullptr; } + /// Returns the only preceding instruction, or std::nullopt if multiple or no + /// predecessors are possible. + /// + /// If CFG information is available, basic block boundary can be crossed, + /// provided there is exactly one predecessor. If CFG is not available, the + /// preceding instruction in the offset order is returned, unless this is the + /// first instruction of the function. + std::optional getSinglePredecessor(); + raw_ostream &print(raw_ostream &OS) const; }; diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index c31c9984ed43e..b6f70fc831fca 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -14,6 +14,7 @@ #ifndef BOLT_CORE_MCPLUSBUILDER_H #define BOLT_CORE_MCPLUSBUILDER_H +#include "bolt/Core/MCInstUtils.h" #include "bolt/Core/MCPlus.h" #include "bolt/Core/Relocation.h" #include "llvm/ADT/ArrayRef.h" @@ -700,6 +701,19 @@ class MCPlusBuilder { return std::nullopt; } + /// Tests if BranchInst corresponds to an instruction sequence which is known + /// to be a safe dispatch via jump table. + /// + /// The target can decide which instruction sequences to consider "safe" from + /// the Pointer Authentication point of view, such as any jump table dispatch + /// sequence without function calls inside, any sequence which is contiguous, + /// or only some specific well-known sequences. + virtual bool + isSafeJumpTableBranchForPtrAuth(MCInstReference BranchInst) const { +llvm_unreachable("not implemented"); +return false; + } + virtual bool isTerminator(const MCInst &Inst) const; virtual bool isNoop(const MCInst &Inst) const { diff --git a/bolt/lib/Core/MCInstUtils.cpp b/bolt/lib/Core/MCInstUtils.cpp index 40f6edd59135c..b7c6d898988af 100644 --- a/bolt/lib/Core/MCInstUtils.cpp +++ b/bolt/lib/Core/MCInstUtils.cpp @@ -55,3 +55,23 @@ raw_ostream &MCInstReference::print(raw_ostream &OS) const { OS << ">"; return OS; } + +std::optional MCInstReference::getSinglePredecessor() { + if (const RefInBB *Ref = tryGetRefInBB()) { +if (Ref->It != Ref->BB->begin()) + return MCInstReference(Ref->BB, &*std::prev(Ref->It)); + +if (Ref->BB->pred_size() != 1) + return std::nullopt; + +BinaryBasicBlock *PredBB = *Ref->BB->pred_begin(); +assert(!PredBB->empty() && "Empty basic blocks are not supported yet"); +return MCInstReference(PredBB, &*PredBB->rbegin()); + } + + const RefInBF &Ref = getRefInBF(); + if (Ref.It == Ref.BF->instrs().begin()) +return std::nullopt; + + return MCInstReference(Ref.BF, std::prev(Ref.It)); +} diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index ee873f7c2c21d..3514c953030a6 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -1363,6 +1363,11 @@ shouldReportUnsafeTailCall(const BinaryContext &BC, const BinaryFunction &BF, return std::nullopt; } + if (BC.MIB->isSafeJumpTableBranchForPtrAuth(Inst)) { +LL
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: detect untrusted LR before tail call (PR #137224)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/137224 >From a0c9617031dd31157686a519743048e12c01ac97 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Tue, 22 Apr 2025 21:43:14 +0300 Subject: [PATCH] [BOLT] Gadget scanner: detect untrusted LR before tail call Implement the detection of tail calls performed with untrusted link register, which violates the assumption made on entry to every function. Unlike other pauth gadgets, this one involves some amount of guessing which branch instructions should be checked as tail calls. --- bolt/lib/Passes/PAuthGadgetScanner.cpp| 80 +++ .../AArch64/gs-pauth-tail-calls.s | 597 ++ 2 files changed, 677 insertions(+) create mode 100644 bolt/test/binary-analysis/AArch64/gs-pauth-tail-calls.s diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index 05309a47aba40..b5b46390d4586 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -1319,6 +1319,83 @@ shouldReportReturnGadget(const BinaryContext &BC, const MCInstReference &Inst, return make_gadget_report(RetKind, Inst, *RetReg); } +/// While BOLT already marks some of the branch instructions as tail calls, +/// this function tries to improve the coverage by including less obvious cases +/// when it is possible to do without introducing too many false positives. +static bool shouldAnalyzeTailCallInst(const BinaryContext &BC, + const BinaryFunction &BF, + const MCInstReference &Inst) { + // Some BC.MIB->isXYZ(Inst) methods simply delegate to MCInstrDesc::isXYZ() + // (such as isBranch at the time of writing this comment), some don't (such + // as isCall). For that reason, call MCInstrDesc's methods explicitly when + // it is important. + const MCInstrDesc &Desc = + BC.MII->get(static_cast(Inst).getOpcode()); + // Tail call should be a branch (but not necessarily an indirect one). + if (!Desc.isBranch()) +return false; + + // Always analyze the branches already marked as tail calls by BOLT. + if (BC.MIB->isTailCall(Inst)) +return true; + + // Try to also check the branches marked as "UNKNOWN CONTROL FLOW" - the + // below is a simplified condition from BinaryContext::printInstruction. + bool IsUnknownControlFlow = + BC.MIB->isIndirectBranch(Inst) && !BC.MIB->getJumpTable(Inst); + + if (BF.hasCFG() && IsUnknownControlFlow) +return true; + + return false; +} + +static std::optional> +shouldReportUnsafeTailCall(const BinaryContext &BC, const BinaryFunction &BF, + const MCInstReference &Inst, const SrcState &S) { + static const GadgetKind UntrustedLRKind( + "untrusted link register found before tail call"); + + if (!shouldAnalyzeTailCallInst(BC, BF, Inst)) +return std::nullopt; + + // Not only the set of registers returned by getTrustedLiveInRegs() can be + // seen as a reasonable target-independent _approximation_ of "the LR", these + // are *exactly* those registers used by SrcSafetyAnalysis to initialize the + // set of trusted registers on function entry. + // Thus, this function basically checks that the precondition expected to be + // imposed by a function call instruction (which is hardcoded into the target- + // specific getTrustedLiveInRegs() function) is also respected on tail calls. + SmallVector RegsToCheck = BC.MIB->getTrustedLiveInRegs(); + LLVM_DEBUG({ +traceInst(BC, "Found tail call inst", Inst); +traceRegMask(BC, "Trusted regs", S.TrustedRegs); + }); + + // In musl on AArch64, the _start function sets LR to zero and calls the next + // stage initialization function at the end, something along these lines: + // + // _start: + // mov x30, #0 + // ; ... other initialization ... + // b _start_c ; performs "exit" system call at some point + // + // As this would produce a false positive for every executable linked with + // such libc, ignore tail calls performed by ELF entry function. + if (BC.StartFunctionAddress && + *BC.StartFunctionAddress == Inst.getFunction()->getAddress()) { +LLVM_DEBUG({ dbgs() << " Skipping tail call in ELF entry function.\n"; }); +return std::nullopt; + } + + // Returns at most one report per instruction - this is probably OK... + for (auto Reg : RegsToCheck) +if (!S.TrustedRegs[Reg]) + return make_gadget_report(UntrustedLRKind, Inst, Reg); + + return std::nullopt; +} + static std::optional> shouldReportCallGadget(const BinaryContext &BC, const MCInstReference &Inst, const SrcState &S) { @@ -1473,6 +1550,9 @@ void FunctionAnalysisContext::findUnsafeUses( if (PacRetGadgetsOnly) return; +if (auto Report = shouldReportUnsafeTailCall(BC, BF, Inst, S)) + Reports.push_back(*Report); + if (auto Report = shouldReportCallGadget(BC, Inst, S))
[llvm-branch-commits] [llvm] [LoopVectorizer] Bundle partial reductions with different extensions (PR #136997)
SamTebbs33 wrote: Superseded by https://github.com/llvm/llvm-project/pull/144908 https://github.com/llvm/llvm-project/pull/136997 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [LoopVectorizer] Bundle partial reductions with different extensions (PR #136997)
https://github.com/SamTebbs33 closed https://github.com/llvm/llvm-project/pull/136997 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [flang] [mlir] [flang][OpenMP][NFC] remove globals with mlir::StateStack (PR #144898)
llvmbot wrote: @llvm/pr-subscribers-flang-fir-hlfir Author: Tom Eccles (tblah) Changes Idea suggested by @skatrak --- Full diff: https://github.com/llvm/llvm-project/pull/144898.diff 4 Files Affected: - (modified) flang/include/flang/Lower/AbstractConverter.h (+3) - (modified) flang/lib/Lower/Bridge.cpp (+6) - (modified) flang/lib/Lower/OpenMP/OpenMP.cpp (+71-31) - (modified) mlir/include/mlir/Support/StateStack.h (+11) ``diff diff --git a/flang/include/flang/Lower/AbstractConverter.h b/flang/include/flang/Lower/AbstractConverter.h index 8ae68e143cd2f..de3e833f60699 100644 --- a/flang/include/flang/Lower/AbstractConverter.h +++ b/flang/include/flang/Lower/AbstractConverter.h @@ -26,6 +26,7 @@ namespace mlir { class SymbolTable; +class StateStack; } namespace fir { @@ -361,6 +362,8 @@ class AbstractConverter { /// functions in order to be in sync). virtual mlir::SymbolTable *getMLIRSymbolTable() = 0; + virtual mlir::StateStack &getStateStack() = 0; + private: /// Options controlling lowering behavior. const Fortran::lower::LoweringOptions &loweringOptions; diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 64b16b3abe991..462ceb8dff736 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -78,6 +78,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Target/TargetMachine.h" +#include "mlir/Support/StateStack.h" #include #define DEBUG_TYPE "flang-lower-bridge" @@ -1237,6 +1238,8 @@ class FirConverter : public Fortran::lower::AbstractConverter { mlir::SymbolTable *getMLIRSymbolTable() override { return &mlirSymbolTable; } + mlir::StateStack &getStateStack() override { return stateStack; } + /// Add the symbol to the local map and return `true`. If the symbol is /// already in the map and \p forced is `false`, the map is not updated. /// Instead the value `false` is returned. @@ -6552,6 +6555,9 @@ class FirConverter : public Fortran::lower::AbstractConverter { /// attribute since mlirSymbolTable must pro-actively be maintained when /// new Symbol operations are created. mlir::SymbolTable mlirSymbolTable; + + /// Used to store context while recursing into regions during lowering. + mlir::StateStack stateStack; }; } // namespace diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 7ad8869597274..bff3321af2814 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -38,6 +38,7 @@ #include "flang/Support/OpenMP-utils.h" #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "mlir/Support/StateStack.h" #include "mlir/Transforms/RegionUtils.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" @@ -200,9 +201,41 @@ class HostEvalInfo { /// the handling of the outer region by keeping a stack of information /// structures, but it will probably still require some further work to support /// reverse offloading. -static llvm::SmallVector hostEvalInfo; -static llvm::SmallVector -sectionsStack; +class HostEvalInfoStackFrame +: public mlir::StateStackFrameBase { +public: + MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(HostEvalInfoStackFrame) + + HostEvalInfo info; +}; + +static HostEvalInfo * +getHostEvalInfoStackTop(lower::AbstractConverter &converter) { + HostEvalInfoStackFrame *frame = + converter.getStateStack().getStackTop(); + return frame ? &frame->info : nullptr; +} + +/// Stack frame for storing the OpenMPSectionsConstruct currently being +/// processed so that it can be refered to when lowering the construct. +class SectionsConstructStackFrame +: public mlir::StateStackFrameBase { +public: + MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(SectionsConstructStackFrame) + + explicit SectionsConstructStackFrame( + const parser::OpenMPSectionsConstruct §ionsConstruct) + : sectionsConstruct{sectionsConstruct} {} + + const parser::OpenMPSectionsConstruct §ionsConstruct; +}; + +static const parser::OpenMPSectionsConstruct * +getSectionsConstructStackTop(lower::AbstractConverter &converter) { + SectionsConstructStackFrame *frame = + converter.getStateStack().getStackTop(); + return frame ? &frame->sectionsConstruct : nullptr; +} /// Bind symbols to their corresponding entry block arguments. /// @@ -537,31 +570,32 @@ static void processHostEvalClauses(lower::AbstractConverter &converter, if (!ompEval) return; -HostEvalInfo &hostInfo = hostEvalInfo.back(); +HostEvalInfo *hostInfo = getHostEvalInfoStackTop(converter); +assert(hostInfo && "expected HOST_EVAL info structure"); switch (extractOmpDirective(*ompEval)) { case OMPD_teams_distribute_parallel_do: case OMPD_teams_distribute_parallel_do_simd: - cp.processThreadLimit(stmtCtx, hostInfo.ops); + cp.processThreadLimit(stmtCtx, hostInfo->ops);
[llvm-branch-commits] [flang] [mlir] [flang][OpenMP][NFC] remove globals with mlir::StateStack (PR #144898)
llvmbot wrote: @llvm/pr-subscribers-mlir-core Author: Tom Eccles (tblah) Changes Idea suggested by @skatrak --- Full diff: https://github.com/llvm/llvm-project/pull/144898.diff 4 Files Affected: - (modified) flang/include/flang/Lower/AbstractConverter.h (+3) - (modified) flang/lib/Lower/Bridge.cpp (+6) - (modified) flang/lib/Lower/OpenMP/OpenMP.cpp (+71-31) - (modified) mlir/include/mlir/Support/StateStack.h (+11) ``diff diff --git a/flang/include/flang/Lower/AbstractConverter.h b/flang/include/flang/Lower/AbstractConverter.h index 8ae68e143cd2f..de3e833f60699 100644 --- a/flang/include/flang/Lower/AbstractConverter.h +++ b/flang/include/flang/Lower/AbstractConverter.h @@ -26,6 +26,7 @@ namespace mlir { class SymbolTable; +class StateStack; } namespace fir { @@ -361,6 +362,8 @@ class AbstractConverter { /// functions in order to be in sync). virtual mlir::SymbolTable *getMLIRSymbolTable() = 0; + virtual mlir::StateStack &getStateStack() = 0; + private: /// Options controlling lowering behavior. const Fortran::lower::LoweringOptions &loweringOptions; diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 64b16b3abe991..462ceb8dff736 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -78,6 +78,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Target/TargetMachine.h" +#include "mlir/Support/StateStack.h" #include #define DEBUG_TYPE "flang-lower-bridge" @@ -1237,6 +1238,8 @@ class FirConverter : public Fortran::lower::AbstractConverter { mlir::SymbolTable *getMLIRSymbolTable() override { return &mlirSymbolTable; } + mlir::StateStack &getStateStack() override { return stateStack; } + /// Add the symbol to the local map and return `true`. If the symbol is /// already in the map and \p forced is `false`, the map is not updated. /// Instead the value `false` is returned. @@ -6552,6 +6555,9 @@ class FirConverter : public Fortran::lower::AbstractConverter { /// attribute since mlirSymbolTable must pro-actively be maintained when /// new Symbol operations are created. mlir::SymbolTable mlirSymbolTable; + + /// Used to store context while recursing into regions during lowering. + mlir::StateStack stateStack; }; } // namespace diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 7ad8869597274..bff3321af2814 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -38,6 +38,7 @@ #include "flang/Support/OpenMP-utils.h" #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "mlir/Support/StateStack.h" #include "mlir/Transforms/RegionUtils.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" @@ -200,9 +201,41 @@ class HostEvalInfo { /// the handling of the outer region by keeping a stack of information /// structures, but it will probably still require some further work to support /// reverse offloading. -static llvm::SmallVector hostEvalInfo; -static llvm::SmallVector -sectionsStack; +class HostEvalInfoStackFrame +: public mlir::StateStackFrameBase { +public: + MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(HostEvalInfoStackFrame) + + HostEvalInfo info; +}; + +static HostEvalInfo * +getHostEvalInfoStackTop(lower::AbstractConverter &converter) { + HostEvalInfoStackFrame *frame = + converter.getStateStack().getStackTop(); + return frame ? &frame->info : nullptr; +} + +/// Stack frame for storing the OpenMPSectionsConstruct currently being +/// processed so that it can be refered to when lowering the construct. +class SectionsConstructStackFrame +: public mlir::StateStackFrameBase { +public: + MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(SectionsConstructStackFrame) + + explicit SectionsConstructStackFrame( + const parser::OpenMPSectionsConstruct §ionsConstruct) + : sectionsConstruct{sectionsConstruct} {} + + const parser::OpenMPSectionsConstruct §ionsConstruct; +}; + +static const parser::OpenMPSectionsConstruct * +getSectionsConstructStackTop(lower::AbstractConverter &converter) { + SectionsConstructStackFrame *frame = + converter.getStateStack().getStackTop(); + return frame ? &frame->sectionsConstruct : nullptr; +} /// Bind symbols to their corresponding entry block arguments. /// @@ -537,31 +570,32 @@ static void processHostEvalClauses(lower::AbstractConverter &converter, if (!ompEval) return; -HostEvalInfo &hostInfo = hostEvalInfo.back(); +HostEvalInfo *hostInfo = getHostEvalInfoStackTop(converter); +assert(hostInfo && "expected HOST_EVAL info structure"); switch (extractOmpDirective(*ompEval)) { case OMPD_teams_distribute_parallel_do: case OMPD_teams_distribute_parallel_do_simd: - cp.processThreadLimit(stmtCtx, hostInfo.ops); + cp.processThreadLimit(stmtCtx, hostInfo->ops); [[fal
[llvm-branch-commits] [flang] [mlir] [flang][OpenMP][NFC] remove globals with mlir::StateStack (PR #144898)
tblah wrote: 1. https://github.com/llvm/llvm-project/pull/144897 2. https://github.com/llvm/llvm-project/pull/144898 https://github.com/llvm/llvm-project/pull/144898 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [flang] [mlir] [flang][OpenMP][NFC] remove globals with mlir::StateStack (PR #144898)
https://github.com/tblah created https://github.com/llvm/llvm-project/pull/144898 Idea suggested by @skatrak >From 280e55d4355f100b7d3066fce3c0515b369fecce Mon Sep 17 00:00:00 2001 From: Tom Eccles Date: Wed, 18 Jun 2025 21:01:13 + Subject: [PATCH] [flang][OpenMP][NFC] remove globals with mlir::StateStack Idea suggested by @skatrak --- flang/include/flang/Lower/AbstractConverter.h | 3 + flang/lib/Lower/Bridge.cpp| 6 ++ flang/lib/Lower/OpenMP/OpenMP.cpp | 102 -- mlir/include/mlir/Support/StateStack.h| 11 ++ 4 files changed, 91 insertions(+), 31 deletions(-) diff --git a/flang/include/flang/Lower/AbstractConverter.h b/flang/include/flang/Lower/AbstractConverter.h index 8ae68e143cd2f..de3e833f60699 100644 --- a/flang/include/flang/Lower/AbstractConverter.h +++ b/flang/include/flang/Lower/AbstractConverter.h @@ -26,6 +26,7 @@ namespace mlir { class SymbolTable; +class StateStack; } namespace fir { @@ -361,6 +362,8 @@ class AbstractConverter { /// functions in order to be in sync). virtual mlir::SymbolTable *getMLIRSymbolTable() = 0; + virtual mlir::StateStack &getStateStack() = 0; + private: /// Options controlling lowering behavior. const Fortran::lower::LoweringOptions &loweringOptions; diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 64b16b3abe991..462ceb8dff736 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -78,6 +78,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Target/TargetMachine.h" +#include "mlir/Support/StateStack.h" #include #define DEBUG_TYPE "flang-lower-bridge" @@ -1237,6 +1238,8 @@ class FirConverter : public Fortran::lower::AbstractConverter { mlir::SymbolTable *getMLIRSymbolTable() override { return &mlirSymbolTable; } + mlir::StateStack &getStateStack() override { return stateStack; } + /// Add the symbol to the local map and return `true`. If the symbol is /// already in the map and \p forced is `false`, the map is not updated. /// Instead the value `false` is returned. @@ -6552,6 +6555,9 @@ class FirConverter : public Fortran::lower::AbstractConverter { /// attribute since mlirSymbolTable must pro-actively be maintained when /// new Symbol operations are created. mlir::SymbolTable mlirSymbolTable; + + /// Used to store context while recursing into regions during lowering. + mlir::StateStack stateStack; }; } // namespace diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 7ad8869597274..bff3321af2814 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -38,6 +38,7 @@ #include "flang/Support/OpenMP-utils.h" #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "mlir/Support/StateStack.h" #include "mlir/Transforms/RegionUtils.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" @@ -200,9 +201,41 @@ class HostEvalInfo { /// the handling of the outer region by keeping a stack of information /// structures, but it will probably still require some further work to support /// reverse offloading. -static llvm::SmallVector hostEvalInfo; -static llvm::SmallVector -sectionsStack; +class HostEvalInfoStackFrame +: public mlir::StateStackFrameBase { +public: + MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(HostEvalInfoStackFrame) + + HostEvalInfo info; +}; + +static HostEvalInfo * +getHostEvalInfoStackTop(lower::AbstractConverter &converter) { + HostEvalInfoStackFrame *frame = + converter.getStateStack().getStackTop(); + return frame ? &frame->info : nullptr; +} + +/// Stack frame for storing the OpenMPSectionsConstruct currently being +/// processed so that it can be refered to when lowering the construct. +class SectionsConstructStackFrame +: public mlir::StateStackFrameBase { +public: + MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(SectionsConstructStackFrame) + + explicit SectionsConstructStackFrame( + const parser::OpenMPSectionsConstruct §ionsConstruct) + : sectionsConstruct{sectionsConstruct} {} + + const parser::OpenMPSectionsConstruct §ionsConstruct; +}; + +static const parser::OpenMPSectionsConstruct * +getSectionsConstructStackTop(lower::AbstractConverter &converter) { + SectionsConstructStackFrame *frame = + converter.getStateStack().getStackTop(); + return frame ? &frame->sectionsConstruct : nullptr; +} /// Bind symbols to their corresponding entry block arguments. /// @@ -537,31 +570,32 @@ static void processHostEvalClauses(lower::AbstractConverter &converter, if (!ompEval) return; -HostEvalInfo &hostInfo = hostEvalInfo.back(); +HostEvalInfo *hostInfo = getHostEvalInfoStackTop(converter); +assert(hostInfo && "expected HOST_EVAL info structure"); switch (extractOmpDirective(*ompEval)) { case OMPD_teams_distr
[llvm-branch-commits] [llvm] [AMDGPU] Improve test coverage for G_INTTOPTR and G_PTRTOINT (PR #142603)
Pierre-vh wrote: ### Merge activity * **Jun 19, 7:48 AM UTC**: A user started a stack merge that includes this pull request via [Graphite](https://app.graphite.dev/github/pr/llvm/llvm-project/142603). https://github.com/llvm/llvm-project/pull/142603 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [AMDGPU] New RegBankSelect: Add Ptr32/Ptr64/Ptr128 (PR #142602)
Pierre-vh wrote: ### Merge activity * **Jun 19, 7:48 AM UTC**: A user started a stack merge that includes this pull request via [Graphite](https://app.graphite.dev/github/pr/llvm/llvm-project/142602). https://github.com/llvm/llvm-project/pull/142602 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [AMDGPU] New RegBanKSelect: Add S128 types (PR #142601)
Pierre-vh wrote: ### Merge activity * **Jun 19, 7:48 AM UTC**: A user started a stack merge that includes this pull request via [Graphite](https://app.graphite.dev/github/pr/llvm/llvm-project/142601). https://github.com/llvm/llvm-project/pull/142601 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [AMDGPU] New RegBankSelect: Add rules for `G_PTRTOINT` and `G_INTTOPTR` (PR #142604)
Pierre-vh wrote: ### Merge activity * **Jun 19, 7:48 AM UTC**: A user started a stack merge that includes this pull request via [Graphite](https://app.graphite.dev/github/pr/llvm/llvm-project/142604). https://github.com/llvm/llvm-project/pull/142604 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: detect untrusted LR before tail call (PR #137224)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/137224 >From a0c9617031dd31157686a519743048e12c01ac97 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Tue, 22 Apr 2025 21:43:14 +0300 Subject: [PATCH] [BOLT] Gadget scanner: detect untrusted LR before tail call Implement the detection of tail calls performed with untrusted link register, which violates the assumption made on entry to every function. Unlike other pauth gadgets, this one involves some amount of guessing which branch instructions should be checked as tail calls. --- bolt/lib/Passes/PAuthGadgetScanner.cpp| 80 +++ .../AArch64/gs-pauth-tail-calls.s | 597 ++ 2 files changed, 677 insertions(+) create mode 100644 bolt/test/binary-analysis/AArch64/gs-pauth-tail-calls.s diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index 05309a47aba40..b5b46390d4586 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -1319,6 +1319,83 @@ shouldReportReturnGadget(const BinaryContext &BC, const MCInstReference &Inst, return make_gadget_report(RetKind, Inst, *RetReg); } +/// While BOLT already marks some of the branch instructions as tail calls, +/// this function tries to improve the coverage by including less obvious cases +/// when it is possible to do without introducing too many false positives. +static bool shouldAnalyzeTailCallInst(const BinaryContext &BC, + const BinaryFunction &BF, + const MCInstReference &Inst) { + // Some BC.MIB->isXYZ(Inst) methods simply delegate to MCInstrDesc::isXYZ() + // (such as isBranch at the time of writing this comment), some don't (such + // as isCall). For that reason, call MCInstrDesc's methods explicitly when + // it is important. + const MCInstrDesc &Desc = + BC.MII->get(static_cast(Inst).getOpcode()); + // Tail call should be a branch (but not necessarily an indirect one). + if (!Desc.isBranch()) +return false; + + // Always analyze the branches already marked as tail calls by BOLT. + if (BC.MIB->isTailCall(Inst)) +return true; + + // Try to also check the branches marked as "UNKNOWN CONTROL FLOW" - the + // below is a simplified condition from BinaryContext::printInstruction. + bool IsUnknownControlFlow = + BC.MIB->isIndirectBranch(Inst) && !BC.MIB->getJumpTable(Inst); + + if (BF.hasCFG() && IsUnknownControlFlow) +return true; + + return false; +} + +static std::optional> +shouldReportUnsafeTailCall(const BinaryContext &BC, const BinaryFunction &BF, + const MCInstReference &Inst, const SrcState &S) { + static const GadgetKind UntrustedLRKind( + "untrusted link register found before tail call"); + + if (!shouldAnalyzeTailCallInst(BC, BF, Inst)) +return std::nullopt; + + // Not only the set of registers returned by getTrustedLiveInRegs() can be + // seen as a reasonable target-independent _approximation_ of "the LR", these + // are *exactly* those registers used by SrcSafetyAnalysis to initialize the + // set of trusted registers on function entry. + // Thus, this function basically checks that the precondition expected to be + // imposed by a function call instruction (which is hardcoded into the target- + // specific getTrustedLiveInRegs() function) is also respected on tail calls. + SmallVector RegsToCheck = BC.MIB->getTrustedLiveInRegs(); + LLVM_DEBUG({ +traceInst(BC, "Found tail call inst", Inst); +traceRegMask(BC, "Trusted regs", S.TrustedRegs); + }); + + // In musl on AArch64, the _start function sets LR to zero and calls the next + // stage initialization function at the end, something along these lines: + // + // _start: + // mov x30, #0 + // ; ... other initialization ... + // b _start_c ; performs "exit" system call at some point + // + // As this would produce a false positive for every executable linked with + // such libc, ignore tail calls performed by ELF entry function. + if (BC.StartFunctionAddress && + *BC.StartFunctionAddress == Inst.getFunction()->getAddress()) { +LLVM_DEBUG({ dbgs() << " Skipping tail call in ELF entry function.\n"; }); +return std::nullopt; + } + + // Returns at most one report per instruction - this is probably OK... + for (auto Reg : RegsToCheck) +if (!S.TrustedRegs[Reg]) + return make_gadget_report(UntrustedLRKind, Inst, Reg); + + return std::nullopt; +} + static std::optional> shouldReportCallGadget(const BinaryContext &BC, const MCInstReference &Inst, const SrcState &S) { @@ -1473,6 +1550,9 @@ void FunctionAnalysisContext::findUnsafeUses( if (PacRetGadgetsOnly) return; +if (auto Report = shouldReportUnsafeTailCall(BC, BF, Inst, S)) + Reports.push_back(*Report); + if (auto Report = shouldReportCallGadget(BC, Inst, S))
[llvm-branch-commits] [llvm] [BOLT] Introduce helpers to match `MCInst`s one at a time (NFC) (PR #138883)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/138883 >From 70eb080d1bc6be69901ef9457b74bef7917327d8 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Wed, 7 May 2025 16:42:00 +0300 Subject: [PATCH] [BOLT] Introduce helpers to match `MCInst`s one at a time (NFC) Introduce matchInst helper function to capture and/or match the operands of MCInst. Unlike the existing `MCPlusBuilder::MCInstMatcher` machinery, matchInst is intended for the use cases when precise control over the instruction order is required. For example, when validating PtrAuth hardening, all registers are usually considered unsafe after a function call, even though callee-saved registers should preserve their old values *under normal operation*. --- bolt/include/bolt/Core/MCInstUtils.h | 128 ++ .../Target/AArch64/AArch64MCPlusBuilder.cpp | 90 +--- 2 files changed, 162 insertions(+), 56 deletions(-) diff --git a/bolt/include/bolt/Core/MCInstUtils.h b/bolt/include/bolt/Core/MCInstUtils.h index 69bf5e6159b74..50b7d56470c99 100644 --- a/bolt/include/bolt/Core/MCInstUtils.h +++ b/bolt/include/bolt/Core/MCInstUtils.h @@ -162,6 +162,134 @@ static inline raw_ostream &operator<<(raw_ostream &OS, return Ref.print(OS); } +/// Instruction-matching helpers operating on a single instruction at a time. +/// +/// Unlike MCPlusBuilder::MCInstMatcher, this matchInst() function focuses on +/// the cases where a precise control over the instruction order is important: +/// +/// // Bring the short names into the local scope: +/// using namespace MCInstMatcher; +/// // Declare the registers to capture: +/// Reg Xn, Xm; +/// // Capture the 0th and 1st operands, match the 2nd operand against the +/// // just captured Xm register, match the 3rd operand against literal 0: +/// if (!matchInst(MaybeAdd, AArch64::ADDXrs, Xm, Xn, Xm, Imm(0)) +/// return AArch64::NoRegister; +/// // Match the 0th operand against Xm: +/// if (!matchInst(MaybeBr, AArch64::BR, Xm)) +/// return AArch64::NoRegister; +/// // Return the matched register: +/// return Xm.get(); +namespace MCInstMatcher { + +// The base class to match an operand of type T. +// +// The subclasses of OpMatcher are intended to be allocated on the stack and +// to only be used by passing them to matchInst() and by calling their get() +// function, thus the peculiar `mutable` specifiers: to make the calling code +// compact and readable, the templated matchInst() function has to accept both +// long-lived Imm/Reg wrappers declared as local variables (intended to capture +// the first operand's value and match the subsequent operands, whether inside +// a single instruction or across multiple instructions), as well as temporary +// wrappers around literal values to match, f.e. Imm(42) or Reg(AArch64::XZR). +template class OpMatcher { + mutable std::optional Value; + mutable std::optional SavedValue; + + // Remember/restore the last Value - to be called by matchInst. + void remember() const { SavedValue = Value; } + void restore() const { Value = SavedValue; } + + template + friend bool matchInst(const MCInst &, unsigned, const OpMatchers &...); + +protected: + OpMatcher(std::optional ValueToMatch) : Value(ValueToMatch) {} + + bool matchValue(T OpValue) const { +// Check that OpValue does not contradict the existing Value. +bool MatchResult = !Value || *Value == OpValue; +// If MatchResult is false, all matchers will be reset before returning from +// matchInst, including this one, thus no need to assign conditionally. +Value = OpValue; + +return MatchResult; + } + +public: + /// Returns the captured value. + T get() const { +assert(Value.has_value()); +return *Value; + } +}; + +class Reg : public OpMatcher { + bool matches(const MCOperand &Op) const { +if (!Op.isReg()) + return false; + +return matchValue(Op.getReg()); + } + + template + friend bool matchInst(const MCInst &, unsigned, const OpMatchers &...); + +public: + Reg(std::optional RegToMatch = std::nullopt) + : OpMatcher(RegToMatch) {} +}; + +class Imm : public OpMatcher { + bool matches(const MCOperand &Op) const { +if (!Op.isImm()) + return false; + +return matchValue(Op.getImm()); + } + + template + friend bool matchInst(const MCInst &, unsigned, const OpMatchers &...); + +public: + Imm(std::optional ImmToMatch = std::nullopt) + : OpMatcher(ImmToMatch) {} +}; + +/// Tries to match Inst and updates Ops on success. +/// +/// If Inst has the specified Opcode and its operand list prefix matches Ops, +/// this function returns true and updates Ops, otherwise false is returned and +/// values of Ops are kept as before matchInst was called. +/// +/// Please note that while Ops are technically passed by a const reference to +/// make invocations like `matchInst(MI, Opcode, Imm(42))` possible, all their +/// fields are marked mut
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: optionally assume auth traps on failure (PR #139778)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/139778 >From 275344a2d8b93e3426214a09cea5f2243c0e2873 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Tue, 13 May 2025 19:50:41 +0300 Subject: [PATCH] [BOLT] Gadget scanner: optionally assume auth traps on failure On AArch64 it is possible for an auth instruction to either return an invalid address value on failure (without FEAT_FPAC) or generate an error (with FEAT_FPAC). It thus may be possible to never emit explicit pointer checks, if the target CPU is known to support FEAT_FPAC. This commit implements an --auth-traps-on-failure command line option, which essentially makes "safe-to-dereference" and "trusted" register properties identical and disables scanning for authentication oracles completely. --- bolt/lib/Passes/PAuthGadgetScanner.cpp| 112 +++ .../binary-analysis/AArch64/cmdline-args.test | 1 + .../AArch64/gs-pauth-authentication-oracles.s | 6 +- .../binary-analysis/AArch64/gs-pauth-calls.s | 5 +- .../AArch64/gs-pauth-debug-output.s | 177 ++--- .../AArch64/gs-pauth-jump-table.s | 6 +- .../AArch64/gs-pauth-signing-oracles.s| 54 ++--- .../AArch64/gs-pauth-tail-calls.s | 184 +- 8 files changed, 318 insertions(+), 227 deletions(-) diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index 3514c953030a6..b4d2fe150d514 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -14,6 +14,7 @@ #include "bolt/Passes/PAuthGadgetScanner.h" #include "bolt/Core/ParallelUtilities.h" #include "bolt/Passes/DataflowAnalysis.h" +#include "bolt/Utils/CommandLineOpts.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallSet.h" #include "llvm/MC/MCInst.h" @@ -26,6 +27,11 @@ namespace llvm { namespace bolt { namespace PAuthGadgetScanner { +static cl::opt AuthTrapsOnFailure( +"auth-traps-on-failure", +cl::desc("Assume authentication instructions always trap on failure"), +cl::cat(opts::BinaryAnalysisCategory)); + [[maybe_unused]] static void traceInst(const BinaryContext &BC, StringRef Label, const MCInst &MI) { dbgs() << " " << Label << ": "; @@ -364,6 +370,34 @@ class SrcSafetyAnalysis { return Clobbered; } + std::optional getRegMadeTrustedByChecking(const MCInst &Inst, + SrcState Cur) const { +// This functions cannot return multiple registers. This is never the case +// on AArch64. +std::optional RegCheckedByInst = +BC.MIB->getAuthCheckedReg(Inst, /*MayOverwrite=*/false); +if (RegCheckedByInst && Cur.SafeToDerefRegs[*RegCheckedByInst]) + return *RegCheckedByInst; + +auto It = CheckerSequenceInfo.find(&Inst); +if (It == CheckerSequenceInfo.end()) + return std::nullopt; + +MCPhysReg RegCheckedBySequence = It->second.first; +const MCInst *FirstCheckerInst = It->second.second; + +// FirstCheckerInst should belong to the same basic block (see the +// assertion in DataflowSrcSafetyAnalysis::run()), meaning it was +// deterministically processed a few steps before this instruction. +const SrcState &StateBeforeChecker = getStateBefore(*FirstCheckerInst); + +// The sequence checks the register, but it should be authenticated before. +if (!StateBeforeChecker.SafeToDerefRegs[RegCheckedBySequence]) + return std::nullopt; + +return RegCheckedBySequence; + } + // Returns all registers that can be treated as if they are written by an // authentication instruction. SmallVector getRegsMadeSafeToDeref(const MCInst &Point, @@ -386,18 +420,38 @@ class SrcSafetyAnalysis { Regs.push_back(DstAndSrc->first); } +// Make sure explicit checker sequence keeps register safe-to-dereference +// when the register would be clobbered according to the regular rules: +// +//; LR is safe to dereference here +//mov x16, x30 ; start of the sequence, LR is s-t-d right before +//xpaclri ; clobbers LR, LR is not safe anymore +//cmp x30, x16 +//b.eq 1f; end of the sequence: LR is marked as trusted +//brk 0x1234 +// 1: +//; at this point LR would be marked as trusted, +//; but not safe-to-dereference +// +// or even just +// +//; X1 is safe to dereference here +//ldr x0, [x1, #8]! +//; X1 is trusted here, but it was clobbered due to address write-back +if (auto CheckedReg = getRegMadeTrustedByChecking(Point, Cur)) + Regs.push_back(*CheckedReg); + return Regs; } // Returns all registers made trusted by this instruction. SmallVector getRegsMadeTrusted(const MCInst &Point, const SrcState &Cur) const { +assert(!AuthTrapsOnFailure &&
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: fix LR to be safe in leaf functions without CFG (PR #141824)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/141824 >From e3bef0621e4b78c8a89302acfca9a1360076f269 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Wed, 14 May 2025 23:12:13 +0300 Subject: [PATCH] [BOLT] Gadget scanner: fix LR to be safe in leaf functions without CFG After a label in a function without CFG information, use a reasonably pessimistic estimation of register state (assume that any register that can be clobbered in this function was actually clobbered) instead of the most pessimistic "all registers are unsafe". This is the same estimation as used by the dataflow variant of the analysis when the preceding instruction is not known for sure. Without this, leaf functions without CFG information are likely to have false positive reports about non-protected return instructions, as 1) LR is unlikely to be signed and authenticated in a leaf function and 2) LR is likely to be used by a return instruction near the end of the function and 3) the register state is likely to be reset at least once during the linear scan through the function --- bolt/lib/Passes/PAuthGadgetScanner.cpp| 14 +++-- .../AArch64/gs-pacret-autiasp.s | 31 +-- .../AArch64/gs-pauth-authentication-oracles.s | 20 .../AArch64/gs-pauth-debug-output.s | 30 ++ .../AArch64/gs-pauth-signing-oracles.s| 27 5 files changed, 29 insertions(+), 93 deletions(-) diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index e5bdade032488..05309a47aba40 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -737,19 +737,14 @@ template class CFGUnawareAnalysis { // // Then, a function can be split into a number of disjoint contiguous sequences // of instructions without labels in between. These sequences can be processed -// the same way basic blocks are processed by data-flow analysis, assuming -// pessimistically that all registers are unsafe at the start of each sequence. +// the same way basic blocks are processed by data-flow analysis, with the same +// pessimistic estimation of the initial state at the start of each sequence +// (except the first instruction of the function). class CFGUnawareSrcSafetyAnalysis : public SrcSafetyAnalysis, public CFGUnawareAnalysis { using SrcSafetyAnalysis::BC; BinaryFunction &BF; - /// Creates a state with all registers marked unsafe (not to be confused - /// with empty state). - SrcState createUnsafeState() const { -return SrcState(NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters()); - } - public: CFGUnawareSrcSafetyAnalysis(BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId, @@ -759,6 +754,7 @@ class CFGUnawareSrcSafetyAnalysis : public SrcSafetyAnalysis, } void run() override { +const SrcState DefaultState = computePessimisticState(BF); SrcState S = createEntryState(); for (auto &I : BF.instrs()) { MCInst &Inst = I.second; @@ -773,7 +769,7 @@ class CFGUnawareSrcSafetyAnalysis : public SrcSafetyAnalysis, LLVM_DEBUG({ traceInst(BC, "Due to label, resetting the state before", Inst); }); -S = createUnsafeState(); +S = DefaultState; } // Attach the state *before* this instruction executes. diff --git a/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s b/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s index df0a83be00986..627f8eb20ab9c 100644 --- a/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s +++ b/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s @@ -224,20 +224,33 @@ f_unreachable_instruction: ret .size f_unreachable_instruction, .-f_unreachable_instruction -// Expected false positive: without CFG, the state is reset to all-unsafe -// after an unconditional branch. - -.globl state_is_reset_after_indirect_branch_nocfg -.type state_is_reset_after_indirect_branch_nocfg,@function -state_is_reset_after_indirect_branch_nocfg: -// CHECK-LABEL: GS-PAUTH: non-protected ret found in function state_is_reset_after_indirect_branch_nocfg, at address -// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret +// Without CFG, the state is reset at labels, assuming every register that can +// be clobbered in the function was actually clobbered. + +.globl lr_untouched_nocfg +.type lr_untouched_nocfg,@function +lr_untouched_nocfg: +// CHECK-NOT: lr_untouched_nocfg +adr x2, 1f +br x2 +1: +ret +.size lr_untouched_nocfg, .-lr_untouched_nocfg + +.globl lr_clobbered_nocfg +.type lr_clobbered_nocfg,@function +lr_clobbered_nocfg: +// CHECK-LABEL: GS-PAUTH: non-protected ret found in function lr_clobbered_nocfg, at address +// CHECK-NEXT: The instruction is
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: account for BRK when searching for auth oracles (PR #137975)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/137975 >From 3e9bfcde8cf45cb7cba3b4b4b03cdff2cfc46e99 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Wed, 30 Apr 2025 16:08:10 +0300 Subject: [PATCH] [BOLT] Gadget scanner: account for BRK when searching for auth oracles An authenticated pointer can be explicitly checked by the compiler via a sequence of instructions that executes BRK on failure. It is important to recognize such BRK instruction as checking every register (as it is expected to immediately trigger an abnormal program termination) to prevent false positive reports about authentication oracles: autia x2, x3 autia x0, x1 ; neither x0 nor x2 are checked at this point eor x16, x0, x0, lsl #1 tbz x16, #62, on_success ; marks x0 as checked ; end of BB: for x2 to be checked here, it must be checked in both ; successor basic blocks on_failure: brk 0xc470 on_success: ; x2 is checked ldr x1, [x2] ; marks x2 as checked --- bolt/include/bolt/Core/MCPlusBuilder.h| 14 ++ bolt/lib/Passes/PAuthGadgetScanner.cpp| 13 +- .../Target/AArch64/AArch64MCPlusBuilder.cpp | 24 -- .../AArch64/gs-pauth-address-checks.s | 44 +-- .../AArch64/gs-pauth-authentication-oracles.s | 9 ++-- .../AArch64/gs-pauth-signing-oracles.s| 6 +-- 6 files changed, 75 insertions(+), 35 deletions(-) diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index 804100db80793..c31c9984ed43e 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -707,6 +707,20 @@ class MCPlusBuilder { return false; } + /// Returns true if Inst is a trap instruction. + /// + /// Tests if Inst is an instruction that immediately causes an abnormal + /// program termination, for example when a security violation is detected + /// by a compiler-inserted check. + /// + /// @note An implementation of this method should likely return false for + /// calls to library functions like abort(), as it is possible that the + /// execution state is partially attacker-controlled at this point. + virtual bool isTrap(const MCInst &Inst) const { +llvm_unreachable("not implemented"); +return false; + } + virtual bool isBreakpoint(const MCInst &Inst) const { llvm_unreachable("not implemented"); return false; diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index b5b46390d4586..98bb84f6f965d 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -1078,6 +1078,15 @@ class DstSafetyAnalysis { dbgs() << ")\n"; }); +// If this instruction terminates the program immediately, no +// authentication oracles are possible past this point. +if (BC.MIB->isTrap(Point)) { + LLVM_DEBUG({ traceInst(BC, "Trap instruction found", Point); }); + DstState Next(NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters()); + Next.CannotEscapeUnchecked.set(); + return Next; +} + // If this instruction is reachable by the analysis, a non-empty state will // be propagated to it sooner or later. Until then, skip computeNext(). if (Cur.empty()) { @@ -1185,8 +1194,8 @@ class DataflowDstSafetyAnalysis // // A basic block without any successors, on the other hand, can be // pessimistically initialized to everything-is-unsafe: this will naturally -// handle both return and tail call instructions and is harmless for -// internal indirect branch instructions (such as computed gotos). +// handle return, trap and tail call instructions. At the same time, it is +// harmless for internal indirect branch instructions, like computed gotos. if (BB.succ_empty()) return createUnsafeState(); diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp index eb1d9d8a19514..ac454a43e8a59 100644 --- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp +++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp @@ -386,10 +386,9 @@ class AArch64MCPlusBuilder : public MCPlusBuilder { // the list of successors of this basic block as appropriate. // Any of the above code sequences assume the fall-through basic block -// is a dead-end BRK instruction (any immediate operand is accepted). +// is a dead-end trap instruction. const BinaryBasicBlock *BreakBB = BB.getFallthrough(); -if (!BreakBB || BreakBB->empty() || -BreakBB->front().getOpcode() != AArch64::BRK) +if (!BreakBB || BreakBB->empty() || !isTrap(BreakBB->front())) return std::nullopt; // Iterate over the instructions of BB in reverse order, matching opcodes @@ -1751,6 +1750,25 @@ class AArch64MCPlusBuilder : public MCPlusBuilder { Inst.addOperand(MCOperand::createImm(0)); }
[llvm-branch-commits] [llvm] [BOLT] Factor out MCInstReference from gadget scanner (NFC) (PR #138655)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/138655 >From c5775ce807ce7ee733a2054169c134a5ddd79fbc Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Thu, 19 Jun 2025 14:03:59 +0300 Subject: [PATCH] [BOLT] Factor out MCInstReference from gadget scanner (NFC) Move MCInstReference representing a constant reference to an instruction inside a parent entity - either inside a basic block (which has a reference to its parent function) or directly to the function (when CFG information is not available). --- bolt/include/bolt/Core/MCInstUtils.h | 168 + bolt/include/bolt/Passes/PAuthGadgetScanner.h | 176 +- bolt/lib/Core/CMakeLists.txt | 1 + bolt/lib/Core/MCInstUtils.cpp | 57 ++ bolt/lib/Passes/PAuthGadgetScanner.cpp| 102 +- 5 files changed, 269 insertions(+), 235 deletions(-) create mode 100644 bolt/include/bolt/Core/MCInstUtils.h create mode 100644 bolt/lib/Core/MCInstUtils.cpp diff --git a/bolt/include/bolt/Core/MCInstUtils.h b/bolt/include/bolt/Core/MCInstUtils.h new file mode 100644 index 0..69bf5e6159b74 --- /dev/null +++ b/bolt/include/bolt/Core/MCInstUtils.h @@ -0,0 +1,168 @@ +//===- bolt/Core/MCInstUtils.h --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef BOLT_CORE_MCINSTUTILS_H +#define BOLT_CORE_MCINSTUTILS_H + +#include "bolt/Core/BinaryBasicBlock.h" + +#include +#include +#include + +namespace llvm { +namespace bolt { + +class BinaryFunction; + +/// MCInstReference represents a reference to a constant MCInst as stored either +/// in a BinaryFunction (i.e. before a CFG is created), or in a BinaryBasicBlock +/// (after a CFG is created). +class MCInstReference { + using nocfg_const_iterator = std::map::const_iterator; + + // Two cases are possible: + // * functions with CFG reconstructed - a function stores a collection of + // basic blocks, each basic block stores a contiguous vector of MCInst + // * functions without CFG - there are no basic blocks created, + // the instructions are directly stored in std::map in BinaryFunction + // + // In both cases, the direct parent of MCInst is stored together with an + // iterator pointing to the instruction. + + // Helper struct: CFG is available, the direct parent is a basic block, + // iterator's type is `MCInst *`. + struct RefInBB { +RefInBB(const BinaryBasicBlock *BB, const MCInst *Inst) +: BB(BB), It(Inst) {} +RefInBB(const RefInBB &Other) = default; +RefInBB &operator=(const RefInBB &Other) = default; + +const BinaryBasicBlock *BB; +BinaryBasicBlock::const_iterator It; + +bool operator<(const RefInBB &Other) const { + return std::tie(BB, It) < std::tie(Other.BB, Other.It); +} + +bool operator==(const RefInBB &Other) const { + return BB == Other.BB && It == Other.It; +} + }; + + // Helper struct: CFG is *not* available, the direct parent is a function, + // iterator's type is std::map::iterator (the mapped value + // is an instruction's offset). + struct RefInBF { +RefInBF(const BinaryFunction *BF, nocfg_const_iterator It) +: BF(BF), It(It) {} +RefInBF(const RefInBF &Other) = default; +RefInBF &operator=(const RefInBF &Other) = default; + +const BinaryFunction *BF; +nocfg_const_iterator It; + +bool operator<(const RefInBF &Other) const { + return std::tie(BF, It->first) < std::tie(Other.BF, Other.It->first); +} + +bool operator==(const RefInBF &Other) const { + return BF == Other.BF && It->first == Other.It->first; +} + }; + + std::variant Reference; + + // Utility methods to be used like this: + // + // if (auto *Ref = tryGetRefInBB()) + // return Ref->doSomething(...); + // return getRefInBF().doSomethingElse(...); + const RefInBB *tryGetRefInBB() const { +assert(std::get_if(&Reference) || + std::get_if(&Reference)); +return std::get_if(&Reference); + } + const RefInBF &getRefInBF() const { +assert(std::get_if(&Reference)); +return *std::get_if(&Reference); + } + +public: + /// Constructs an empty reference. + MCInstReference() : Reference(RefInBB(nullptr, nullptr)) {} + /// Constructs a reference to the instruction inside the basic block. + MCInstReference(const BinaryBasicBlock *BB, const MCInst *Inst) + : Reference(RefInBB(BB, Inst)) { +assert(BB && Inst && "Neither BB nor Inst should be nullptr"); + } + /// Constructs a reference to the instruction inside the basic block. + MCInstReference(const BinaryBasicBlock *BB, unsigned Index) + : Reference(RefInBB(BB, &BB->getInstructionAtIndex(I
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: make use of C++17 features and LLVM helpers (PR #141665)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/141665 >From e880cb42df70af5112e89c16bffc908274ba5910 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Tue, 27 May 2025 21:06:03 +0300 Subject: [PATCH] [BOLT] Gadget scanner: make use of C++17 features and LLVM helpers Perform trivial syntactical cleanups: * make use of structured binding declarations * use LLVM utility functions when appropriate * omit braces around single expression inside single-line LLVM_DEBUG() This patch is NFC aside from minor debug output changes. --- bolt/lib/Passes/PAuthGadgetScanner.cpp| 67 +-- .../AArch64/gs-pauth-debug-output.s | 14 ++-- 2 files changed, 38 insertions(+), 43 deletions(-) diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index b4d2fe150d514..f455229d9ea7a 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -88,8 +88,8 @@ class TrackedRegisters { TrackedRegisters(ArrayRef RegsToTrack) : Registers(RegsToTrack), RegToIndexMapping(getMappingSize(RegsToTrack), NoIndex) { -for (unsigned I = 0; I < RegsToTrack.size(); ++I) - RegToIndexMapping[RegsToTrack[I]] = I; +for (auto [MappedIndex, Reg] : llvm::enumerate(RegsToTrack)) + RegToIndexMapping[Reg] = MappedIndex; } ArrayRef getRegisters() const { return Registers; } @@ -203,9 +203,9 @@ struct SrcState { SafeToDerefRegs &= StateIn.SafeToDerefRegs; TrustedRegs &= StateIn.TrustedRegs; -for (unsigned I = 0; I < LastInstWritingReg.size(); ++I) - for (const MCInst *J : StateIn.LastInstWritingReg[I]) -LastInstWritingReg[I].insert(J); +for (auto [ThisSet, OtherSet] : + llvm::zip_equal(LastInstWritingReg, StateIn.LastInstWritingReg)) + ThisSet.insert_range(OtherSet); return *this; } @@ -224,11 +224,9 @@ struct SrcState { static void printInstsShort(raw_ostream &OS, ArrayRef Insts) { OS << "Insts: "; - for (unsigned I = 0; I < Insts.size(); ++I) { -auto &Set = Insts[I]; + for (auto [I, PtrSet] : llvm::enumerate(Insts)) { OS << "[" << I << "]("; -for (const MCInst *MCInstP : Set) - OS << MCInstP << " "; +interleave(PtrSet, OS, " "); OS << ")"; } } @@ -416,8 +414,9 @@ class SrcSafetyAnalysis { // ... an address can be updated in a safe manner, producing the result // which is as trusted as the input address. if (auto DstAndSrc = BC.MIB->analyzeAddressArithmeticsForPtrAuth(Point)) { - if (Cur.SafeToDerefRegs[DstAndSrc->second]) -Regs.push_back(DstAndSrc->first); + auto [DstReg, SrcReg] = *DstAndSrc; + if (Cur.SafeToDerefRegs[SrcReg]) +Regs.push_back(DstReg); } // Make sure explicit checker sequence keeps register safe-to-dereference @@ -469,8 +468,9 @@ class SrcSafetyAnalysis { // ... an address can be updated in a safe manner, producing the result // which is as trusted as the input address. if (auto DstAndSrc = BC.MIB->analyzeAddressArithmeticsForPtrAuth(Point)) { - if (Cur.TrustedRegs[DstAndSrc->second]) -Regs.push_back(DstAndSrc->first); + auto [DstReg, SrcReg] = *DstAndSrc; + if (Cur.TrustedRegs[SrcReg]) +Regs.push_back(DstReg); } return Regs; @@ -868,9 +868,9 @@ struct DstState { return (*this = StateIn); CannotEscapeUnchecked &= StateIn.CannotEscapeUnchecked; -for (unsigned I = 0; I < FirstInstLeakingReg.size(); ++I) - for (const MCInst *J : StateIn.FirstInstLeakingReg[I]) -FirstInstLeakingReg[I].insert(J); +for (auto [ThisSet, OtherSet] : + llvm::zip_equal(FirstInstLeakingReg, StateIn.FirstInstLeakingReg)) + ThisSet.insert_range(OtherSet); return *this; } @@ -1036,8 +1036,7 @@ class DstSafetyAnalysis { // ... an address can be updated in a safe manner, or if (auto DstAndSrc = BC.MIB->analyzeAddressArithmeticsForPtrAuth(Inst)) { - MCPhysReg DstReg, SrcReg; - std::tie(DstReg, SrcReg) = *DstAndSrc; + auto [DstReg, SrcReg] = *DstAndSrc; // Note that *all* registers containing the derived values must be safe, // both source and destination ones. No temporaries are supported at now. if (Cur.CannotEscapeUnchecked[SrcReg] && @@ -1077,7 +1076,7 @@ class DstSafetyAnalysis { // If this instruction terminates the program immediately, no // authentication oracles are possible past this point. if (BC.MIB->isTrap(Point)) { - LLVM_DEBUG({ traceInst(BC, "Trap instruction found", Point); }); + LLVM_DEBUG(traceInst(BC, "Trap instruction found", Point)); DstState Next(NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters()); Next.CannotEscapeUnchecked.set(); return Next; @@ -1255,7 +1254,7 @@ class CFGUnawareDstSafetyAnalysis : public DstSafetyAnalysis, // starting to analyze Inst.
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: do not crash on debug-printing CFI instructions (PR #136151)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/136151 >From 9c7da2b0632b21cfe8750faa023d8413ad4664fa Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Tue, 15 Apr 2025 21:47:18 +0300 Subject: [PATCH] [BOLT] Gadget scanner: do not crash on debug-printing CFI instructions Some instruction-printing code used under LLVM_DEBUG does not handle CFI instructions well. While CFI instructions seem to be harmless for the correctness of the analysis results, they do not convey any useful information to the analysis either, so skip them early. --- bolt/lib/Passes/PAuthGadgetScanner.cpp| 16 ++ .../AArch64/gs-pauth-debug-output.s | 32 +++ 2 files changed, 48 insertions(+) diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index 7682d7fe2c542..95e831fe9c8ca 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -430,6 +430,9 @@ class SrcSafetyAnalysis { } SrcState computeNext(const MCInst &Point, const SrcState &Cur) { +if (BC.MIB->isCFI(Point)) + return Cur; + SrcStatePrinter P(BC); LLVM_DEBUG({ dbgs() << " SrcSafetyAnalysis::ComputeNext("; @@ -704,6 +707,8 @@ class CFGUnawareSrcSafetyAnalysis : public SrcSafetyAnalysis, SrcState S = createEntryState(); for (auto &I : BF.instrs()) { MCInst &Inst = I.second; + if (BC.MIB->isCFI(Inst)) +continue; // If there is a label before this instruction, it is possible that it // can be jumped-to, thus conservatively resetting S. As an exception, @@ -1010,6 +1015,9 @@ class DstSafetyAnalysis { } DstState computeNext(const MCInst &Point, const DstState &Cur) { +if (BC.MIB->isCFI(Point)) + return Cur; + DstStatePrinter P(BC); LLVM_DEBUG({ dbgs() << " DstSafetyAnalysis::ComputeNext("; @@ -1177,6 +1185,8 @@ class CFGUnawareDstSafetyAnalysis : public DstSafetyAnalysis, DstState S = createUnsafeState(); for (auto &I : llvm::reverse(BF.instrs())) { MCInst &Inst = I.second; + if (BC.MIB->isCFI(Inst)) +continue; // If Inst can change the control flow, we cannot be sure that the next // instruction (to be executed in analyzed program) is the one processed @@ -1366,6 +1376,9 @@ void FunctionAnalysisContext::findUnsafeUses( }); iterateOverInstrs(BF, [&](MCInstReference Inst) { +if (BC.MIB->isCFI(Inst)) + return; + const SrcState &S = Analysis->getStateBefore(Inst); // If non-empty state was never propagated from the entry basic block @@ -1429,6 +1442,9 @@ void FunctionAnalysisContext::findUnsafeDefs( }); iterateOverInstrs(BF, [&](MCInstReference Inst) { +if (BC.MIB->isCFI(Inst)) + return; + const DstState &S = Analysis->getStateAfter(Inst); if (auto Report = shouldReportAuthOracle(BC, Inst, S)) diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s b/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s index 686557eb1e529..fbb96a63d41ed 100644 --- a/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s +++ b/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s @@ -329,6 +329,38 @@ auth_oracle: // PAUTH-EMPTY: // PAUTH-NEXT: Attaching leakage info to: : autia x0, x1 # DataflowDstSafetyAnalysis: dst-state +// Gadget scanner should not crash on CFI instructions, including when debug-printing them. +// Note that the particular debug output is not checked, but BOLT should be +// compiled with assertions enabled to support -debug-only argument. + +.globl cfi_inst_df +.type cfi_inst_df,@function +cfi_inst_df: +.cfi_startproc +sub sp, sp, #16 +.cfi_def_cfa_offset 16 +add sp, sp, #16 +.cfi_def_cfa_offset 0 +ret +.size cfi_inst_df, .-cfi_inst_df +.cfi_endproc + +.globl cfi_inst_nocfg +.type cfi_inst_nocfg,@function +cfi_inst_nocfg: +.cfi_startproc +sub sp, sp, #16 +.cfi_def_cfa_offset 16 + +adr x0, 1f +br x0 +1: +add sp, sp, #16 +.cfi_def_cfa_offset 0 +ret +.size cfi_inst_nocfg, .-cfi_inst_nocfg +.cfi_endproc + // CHECK-LABEL:Analyzing function main, AllocatorId = 1 .globl main .type main,@function ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: fix LR to be safe in leaf functions without CFG (PR #141824)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/141824 >From e3bef0621e4b78c8a89302acfca9a1360076f269 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Wed, 14 May 2025 23:12:13 +0300 Subject: [PATCH] [BOLT] Gadget scanner: fix LR to be safe in leaf functions without CFG After a label in a function without CFG information, use a reasonably pessimistic estimation of register state (assume that any register that can be clobbered in this function was actually clobbered) instead of the most pessimistic "all registers are unsafe". This is the same estimation as used by the dataflow variant of the analysis when the preceding instruction is not known for sure. Without this, leaf functions without CFG information are likely to have false positive reports about non-protected return instructions, as 1) LR is unlikely to be signed and authenticated in a leaf function and 2) LR is likely to be used by a return instruction near the end of the function and 3) the register state is likely to be reset at least once during the linear scan through the function --- bolt/lib/Passes/PAuthGadgetScanner.cpp| 14 +++-- .../AArch64/gs-pacret-autiasp.s | 31 +-- .../AArch64/gs-pauth-authentication-oracles.s | 20 .../AArch64/gs-pauth-debug-output.s | 30 ++ .../AArch64/gs-pauth-signing-oracles.s| 27 5 files changed, 29 insertions(+), 93 deletions(-) diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index e5bdade032488..05309a47aba40 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -737,19 +737,14 @@ template class CFGUnawareAnalysis { // // Then, a function can be split into a number of disjoint contiguous sequences // of instructions without labels in between. These sequences can be processed -// the same way basic blocks are processed by data-flow analysis, assuming -// pessimistically that all registers are unsafe at the start of each sequence. +// the same way basic blocks are processed by data-flow analysis, with the same +// pessimistic estimation of the initial state at the start of each sequence +// (except the first instruction of the function). class CFGUnawareSrcSafetyAnalysis : public SrcSafetyAnalysis, public CFGUnawareAnalysis { using SrcSafetyAnalysis::BC; BinaryFunction &BF; - /// Creates a state with all registers marked unsafe (not to be confused - /// with empty state). - SrcState createUnsafeState() const { -return SrcState(NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters()); - } - public: CFGUnawareSrcSafetyAnalysis(BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId, @@ -759,6 +754,7 @@ class CFGUnawareSrcSafetyAnalysis : public SrcSafetyAnalysis, } void run() override { +const SrcState DefaultState = computePessimisticState(BF); SrcState S = createEntryState(); for (auto &I : BF.instrs()) { MCInst &Inst = I.second; @@ -773,7 +769,7 @@ class CFGUnawareSrcSafetyAnalysis : public SrcSafetyAnalysis, LLVM_DEBUG({ traceInst(BC, "Due to label, resetting the state before", Inst); }); -S = createUnsafeState(); +S = DefaultState; } // Attach the state *before* this instruction executes. diff --git a/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s b/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s index df0a83be00986..627f8eb20ab9c 100644 --- a/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s +++ b/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s @@ -224,20 +224,33 @@ f_unreachable_instruction: ret .size f_unreachable_instruction, .-f_unreachable_instruction -// Expected false positive: without CFG, the state is reset to all-unsafe -// after an unconditional branch. - -.globl state_is_reset_after_indirect_branch_nocfg -.type state_is_reset_after_indirect_branch_nocfg,@function -state_is_reset_after_indirect_branch_nocfg: -// CHECK-LABEL: GS-PAUTH: non-protected ret found in function state_is_reset_after_indirect_branch_nocfg, at address -// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret +// Without CFG, the state is reset at labels, assuming every register that can +// be clobbered in the function was actually clobbered. + +.globl lr_untouched_nocfg +.type lr_untouched_nocfg,@function +lr_untouched_nocfg: +// CHECK-NOT: lr_untouched_nocfg +adr x2, 1f +br x2 +1: +ret +.size lr_untouched_nocfg, .-lr_untouched_nocfg + +.globl lr_clobbered_nocfg +.type lr_clobbered_nocfg,@function +lr_clobbered_nocfg: +// CHECK-LABEL: GS-PAUTH: non-protected ret found in function lr_clobbered_nocfg, at address +// CHECK-NEXT: The instruction is
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: account for BRK when searching for auth oracles (PR #137975)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/137975 >From 3e9bfcde8cf45cb7cba3b4b4b03cdff2cfc46e99 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Wed, 30 Apr 2025 16:08:10 +0300 Subject: [PATCH] [BOLT] Gadget scanner: account for BRK when searching for auth oracles An authenticated pointer can be explicitly checked by the compiler via a sequence of instructions that executes BRK on failure. It is important to recognize such BRK instruction as checking every register (as it is expected to immediately trigger an abnormal program termination) to prevent false positive reports about authentication oracles: autia x2, x3 autia x0, x1 ; neither x0 nor x2 are checked at this point eor x16, x0, x0, lsl #1 tbz x16, #62, on_success ; marks x0 as checked ; end of BB: for x2 to be checked here, it must be checked in both ; successor basic blocks on_failure: brk 0xc470 on_success: ; x2 is checked ldr x1, [x2] ; marks x2 as checked --- bolt/include/bolt/Core/MCPlusBuilder.h| 14 ++ bolt/lib/Passes/PAuthGadgetScanner.cpp| 13 +- .../Target/AArch64/AArch64MCPlusBuilder.cpp | 24 -- .../AArch64/gs-pauth-address-checks.s | 44 +-- .../AArch64/gs-pauth-authentication-oracles.s | 9 ++-- .../AArch64/gs-pauth-signing-oracles.s| 6 +-- 6 files changed, 75 insertions(+), 35 deletions(-) diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index 804100db80793..c31c9984ed43e 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -707,6 +707,20 @@ class MCPlusBuilder { return false; } + /// Returns true if Inst is a trap instruction. + /// + /// Tests if Inst is an instruction that immediately causes an abnormal + /// program termination, for example when a security violation is detected + /// by a compiler-inserted check. + /// + /// @note An implementation of this method should likely return false for + /// calls to library functions like abort(), as it is possible that the + /// execution state is partially attacker-controlled at this point. + virtual bool isTrap(const MCInst &Inst) const { +llvm_unreachable("not implemented"); +return false; + } + virtual bool isBreakpoint(const MCInst &Inst) const { llvm_unreachable("not implemented"); return false; diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index b5b46390d4586..98bb84f6f965d 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -1078,6 +1078,15 @@ class DstSafetyAnalysis { dbgs() << ")\n"; }); +// If this instruction terminates the program immediately, no +// authentication oracles are possible past this point. +if (BC.MIB->isTrap(Point)) { + LLVM_DEBUG({ traceInst(BC, "Trap instruction found", Point); }); + DstState Next(NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters()); + Next.CannotEscapeUnchecked.set(); + return Next; +} + // If this instruction is reachable by the analysis, a non-empty state will // be propagated to it sooner or later. Until then, skip computeNext(). if (Cur.empty()) { @@ -1185,8 +1194,8 @@ class DataflowDstSafetyAnalysis // // A basic block without any successors, on the other hand, can be // pessimistically initialized to everything-is-unsafe: this will naturally -// handle both return and tail call instructions and is harmless for -// internal indirect branch instructions (such as computed gotos). +// handle return, trap and tail call instructions. At the same time, it is +// harmless for internal indirect branch instructions, like computed gotos. if (BB.succ_empty()) return createUnsafeState(); diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp index eb1d9d8a19514..ac454a43e8a59 100644 --- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp +++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp @@ -386,10 +386,9 @@ class AArch64MCPlusBuilder : public MCPlusBuilder { // the list of successors of this basic block as appropriate. // Any of the above code sequences assume the fall-through basic block -// is a dead-end BRK instruction (any immediate operand is accepted). +// is a dead-end trap instruction. const BinaryBasicBlock *BreakBB = BB.getFallthrough(); -if (!BreakBB || BreakBB->empty() || -BreakBB->front().getOpcode() != AArch64::BRK) +if (!BreakBB || BreakBB->empty() || !isTrap(BreakBB->front())) return std::nullopt; // Iterate over the instructions of BB in reverse order, matching opcodes @@ -1751,6 +1750,25 @@ class AArch64MCPlusBuilder : public MCPlusBuilder { Inst.addOperand(MCOperand::createImm(0)); }
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: make use of C++17 features and LLVM helpers (PR #141665)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/141665 >From e880cb42df70af5112e89c16bffc908274ba5910 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Tue, 27 May 2025 21:06:03 +0300 Subject: [PATCH] [BOLT] Gadget scanner: make use of C++17 features and LLVM helpers Perform trivial syntactical cleanups: * make use of structured binding declarations * use LLVM utility functions when appropriate * omit braces around single expression inside single-line LLVM_DEBUG() This patch is NFC aside from minor debug output changes. --- bolt/lib/Passes/PAuthGadgetScanner.cpp| 67 +-- .../AArch64/gs-pauth-debug-output.s | 14 ++-- 2 files changed, 38 insertions(+), 43 deletions(-) diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index b4d2fe150d514..f455229d9ea7a 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -88,8 +88,8 @@ class TrackedRegisters { TrackedRegisters(ArrayRef RegsToTrack) : Registers(RegsToTrack), RegToIndexMapping(getMappingSize(RegsToTrack), NoIndex) { -for (unsigned I = 0; I < RegsToTrack.size(); ++I) - RegToIndexMapping[RegsToTrack[I]] = I; +for (auto [MappedIndex, Reg] : llvm::enumerate(RegsToTrack)) + RegToIndexMapping[Reg] = MappedIndex; } ArrayRef getRegisters() const { return Registers; } @@ -203,9 +203,9 @@ struct SrcState { SafeToDerefRegs &= StateIn.SafeToDerefRegs; TrustedRegs &= StateIn.TrustedRegs; -for (unsigned I = 0; I < LastInstWritingReg.size(); ++I) - for (const MCInst *J : StateIn.LastInstWritingReg[I]) -LastInstWritingReg[I].insert(J); +for (auto [ThisSet, OtherSet] : + llvm::zip_equal(LastInstWritingReg, StateIn.LastInstWritingReg)) + ThisSet.insert_range(OtherSet); return *this; } @@ -224,11 +224,9 @@ struct SrcState { static void printInstsShort(raw_ostream &OS, ArrayRef Insts) { OS << "Insts: "; - for (unsigned I = 0; I < Insts.size(); ++I) { -auto &Set = Insts[I]; + for (auto [I, PtrSet] : llvm::enumerate(Insts)) { OS << "[" << I << "]("; -for (const MCInst *MCInstP : Set) - OS << MCInstP << " "; +interleave(PtrSet, OS, " "); OS << ")"; } } @@ -416,8 +414,9 @@ class SrcSafetyAnalysis { // ... an address can be updated in a safe manner, producing the result // which is as trusted as the input address. if (auto DstAndSrc = BC.MIB->analyzeAddressArithmeticsForPtrAuth(Point)) { - if (Cur.SafeToDerefRegs[DstAndSrc->second]) -Regs.push_back(DstAndSrc->first); + auto [DstReg, SrcReg] = *DstAndSrc; + if (Cur.SafeToDerefRegs[SrcReg]) +Regs.push_back(DstReg); } // Make sure explicit checker sequence keeps register safe-to-dereference @@ -469,8 +468,9 @@ class SrcSafetyAnalysis { // ... an address can be updated in a safe manner, producing the result // which is as trusted as the input address. if (auto DstAndSrc = BC.MIB->analyzeAddressArithmeticsForPtrAuth(Point)) { - if (Cur.TrustedRegs[DstAndSrc->second]) -Regs.push_back(DstAndSrc->first); + auto [DstReg, SrcReg] = *DstAndSrc; + if (Cur.TrustedRegs[SrcReg]) +Regs.push_back(DstReg); } return Regs; @@ -868,9 +868,9 @@ struct DstState { return (*this = StateIn); CannotEscapeUnchecked &= StateIn.CannotEscapeUnchecked; -for (unsigned I = 0; I < FirstInstLeakingReg.size(); ++I) - for (const MCInst *J : StateIn.FirstInstLeakingReg[I]) -FirstInstLeakingReg[I].insert(J); +for (auto [ThisSet, OtherSet] : + llvm::zip_equal(FirstInstLeakingReg, StateIn.FirstInstLeakingReg)) + ThisSet.insert_range(OtherSet); return *this; } @@ -1036,8 +1036,7 @@ class DstSafetyAnalysis { // ... an address can be updated in a safe manner, or if (auto DstAndSrc = BC.MIB->analyzeAddressArithmeticsForPtrAuth(Inst)) { - MCPhysReg DstReg, SrcReg; - std::tie(DstReg, SrcReg) = *DstAndSrc; + auto [DstReg, SrcReg] = *DstAndSrc; // Note that *all* registers containing the derived values must be safe, // both source and destination ones. No temporaries are supported at now. if (Cur.CannotEscapeUnchecked[SrcReg] && @@ -1077,7 +1076,7 @@ class DstSafetyAnalysis { // If this instruction terminates the program immediately, no // authentication oracles are possible past this point. if (BC.MIB->isTrap(Point)) { - LLVM_DEBUG({ traceInst(BC, "Trap instruction found", Point); }); + LLVM_DEBUG(traceInst(BC, "Trap instruction found", Point)); DstState Next(NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters()); Next.CannotEscapeUnchecked.set(); return Next; @@ -1255,7 +1254,7 @@ class CFGUnawareDstSafetyAnalysis : public DstSafetyAnalysis, // starting to analyze Inst.
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: optionally assume auth traps on failure (PR #139778)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/139778 >From 275344a2d8b93e3426214a09cea5f2243c0e2873 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Tue, 13 May 2025 19:50:41 +0300 Subject: [PATCH] [BOLT] Gadget scanner: optionally assume auth traps on failure On AArch64 it is possible for an auth instruction to either return an invalid address value on failure (without FEAT_FPAC) or generate an error (with FEAT_FPAC). It thus may be possible to never emit explicit pointer checks, if the target CPU is known to support FEAT_FPAC. This commit implements an --auth-traps-on-failure command line option, which essentially makes "safe-to-dereference" and "trusted" register properties identical and disables scanning for authentication oracles completely. --- bolt/lib/Passes/PAuthGadgetScanner.cpp| 112 +++ .../binary-analysis/AArch64/cmdline-args.test | 1 + .../AArch64/gs-pauth-authentication-oracles.s | 6 +- .../binary-analysis/AArch64/gs-pauth-calls.s | 5 +- .../AArch64/gs-pauth-debug-output.s | 177 ++--- .../AArch64/gs-pauth-jump-table.s | 6 +- .../AArch64/gs-pauth-signing-oracles.s| 54 ++--- .../AArch64/gs-pauth-tail-calls.s | 184 +- 8 files changed, 318 insertions(+), 227 deletions(-) diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index 3514c953030a6..b4d2fe150d514 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -14,6 +14,7 @@ #include "bolt/Passes/PAuthGadgetScanner.h" #include "bolt/Core/ParallelUtilities.h" #include "bolt/Passes/DataflowAnalysis.h" +#include "bolt/Utils/CommandLineOpts.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallSet.h" #include "llvm/MC/MCInst.h" @@ -26,6 +27,11 @@ namespace llvm { namespace bolt { namespace PAuthGadgetScanner { +static cl::opt AuthTrapsOnFailure( +"auth-traps-on-failure", +cl::desc("Assume authentication instructions always trap on failure"), +cl::cat(opts::BinaryAnalysisCategory)); + [[maybe_unused]] static void traceInst(const BinaryContext &BC, StringRef Label, const MCInst &MI) { dbgs() << " " << Label << ": "; @@ -364,6 +370,34 @@ class SrcSafetyAnalysis { return Clobbered; } + std::optional getRegMadeTrustedByChecking(const MCInst &Inst, + SrcState Cur) const { +// This functions cannot return multiple registers. This is never the case +// on AArch64. +std::optional RegCheckedByInst = +BC.MIB->getAuthCheckedReg(Inst, /*MayOverwrite=*/false); +if (RegCheckedByInst && Cur.SafeToDerefRegs[*RegCheckedByInst]) + return *RegCheckedByInst; + +auto It = CheckerSequenceInfo.find(&Inst); +if (It == CheckerSequenceInfo.end()) + return std::nullopt; + +MCPhysReg RegCheckedBySequence = It->second.first; +const MCInst *FirstCheckerInst = It->second.second; + +// FirstCheckerInst should belong to the same basic block (see the +// assertion in DataflowSrcSafetyAnalysis::run()), meaning it was +// deterministically processed a few steps before this instruction. +const SrcState &StateBeforeChecker = getStateBefore(*FirstCheckerInst); + +// The sequence checks the register, but it should be authenticated before. +if (!StateBeforeChecker.SafeToDerefRegs[RegCheckedBySequence]) + return std::nullopt; + +return RegCheckedBySequence; + } + // Returns all registers that can be treated as if they are written by an // authentication instruction. SmallVector getRegsMadeSafeToDeref(const MCInst &Point, @@ -386,18 +420,38 @@ class SrcSafetyAnalysis { Regs.push_back(DstAndSrc->first); } +// Make sure explicit checker sequence keeps register safe-to-dereference +// when the register would be clobbered according to the regular rules: +// +//; LR is safe to dereference here +//mov x16, x30 ; start of the sequence, LR is s-t-d right before +//xpaclri ; clobbers LR, LR is not safe anymore +//cmp x30, x16 +//b.eq 1f; end of the sequence: LR is marked as trusted +//brk 0x1234 +// 1: +//; at this point LR would be marked as trusted, +//; but not safe-to-dereference +// +// or even just +// +//; X1 is safe to dereference here +//ldr x0, [x1, #8]! +//; X1 is trusted here, but it was clobbered due to address write-back +if (auto CheckedReg = getRegMadeTrustedByChecking(Point, Cur)) + Regs.push_back(*CheckedReg); + return Regs; } // Returns all registers made trusted by this instruction. SmallVector getRegsMadeTrusted(const MCInst &Point, const SrcState &Cur) const { +assert(!AuthTrapsOnFailure &&
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: prevent false positives due to jump tables (PR #138884)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/138884 >From e72572049530d58764cff1ce1081c1765838188a Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Tue, 6 May 2025 11:31:03 +0300 Subject: [PATCH] [BOLT] Gadget scanner: prevent false positives due to jump tables As part of PAuth hardening, AArch64 LLVM backend can use a special BR_JumpTable pseudo (enabled by -faarch64-jump-table-hardening Clang option) which is expanded in the AsmPrinter into a contiguous sequence without unsafe instructions in the middle. This commit adds another target-specific callback to MCPlusBuilder to make it possible to inhibit false positives for known-safe jump table dispatch sequences. Without special handling, the branch instruction is likely to be reported as a non-protected call (as its destination is not produced by an auth instruction, PC-relative address materialization, etc.) and possibly as a tail call being performed with unsafe link register (as the detection whether the branch instruction is a tail call is an heuristic). For now, only the specific instruction sequence used by the AArch64 LLVM backend is matched. --- bolt/include/bolt/Core/MCInstUtils.h | 9 + bolt/include/bolt/Core/MCPlusBuilder.h| 14 + bolt/lib/Core/MCInstUtils.cpp | 20 + bolt/lib/Passes/PAuthGadgetScanner.cpp| 10 + .../Target/AArch64/AArch64MCPlusBuilder.cpp | 73 ++ .../AArch64/gs-pauth-jump-table.s | 703 ++ 6 files changed, 829 insertions(+) create mode 100644 bolt/test/binary-analysis/AArch64/gs-pauth-jump-table.s diff --git a/bolt/include/bolt/Core/MCInstUtils.h b/bolt/include/bolt/Core/MCInstUtils.h index 50b7d56470c99..33d36cccbcfff 100644 --- a/bolt/include/bolt/Core/MCInstUtils.h +++ b/bolt/include/bolt/Core/MCInstUtils.h @@ -154,6 +154,15 @@ class MCInstReference { return nullptr; } + /// Returns the only preceding instruction, or std::nullopt if multiple or no + /// predecessors are possible. + /// + /// If CFG information is available, basic block boundary can be crossed, + /// provided there is exactly one predecessor. If CFG is not available, the + /// preceding instruction in the offset order is returned, unless this is the + /// first instruction of the function. + std::optional getSinglePredecessor(); + raw_ostream &print(raw_ostream &OS) const; }; diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index c31c9984ed43e..b6f70fc831fca 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -14,6 +14,7 @@ #ifndef BOLT_CORE_MCPLUSBUILDER_H #define BOLT_CORE_MCPLUSBUILDER_H +#include "bolt/Core/MCInstUtils.h" #include "bolt/Core/MCPlus.h" #include "bolt/Core/Relocation.h" #include "llvm/ADT/ArrayRef.h" @@ -700,6 +701,19 @@ class MCPlusBuilder { return std::nullopt; } + /// Tests if BranchInst corresponds to an instruction sequence which is known + /// to be a safe dispatch via jump table. + /// + /// The target can decide which instruction sequences to consider "safe" from + /// the Pointer Authentication point of view, such as any jump table dispatch + /// sequence without function calls inside, any sequence which is contiguous, + /// or only some specific well-known sequences. + virtual bool + isSafeJumpTableBranchForPtrAuth(MCInstReference BranchInst) const { +llvm_unreachable("not implemented"); +return false; + } + virtual bool isTerminator(const MCInst &Inst) const; virtual bool isNoop(const MCInst &Inst) const { diff --git a/bolt/lib/Core/MCInstUtils.cpp b/bolt/lib/Core/MCInstUtils.cpp index 40f6edd59135c..b7c6d898988af 100644 --- a/bolt/lib/Core/MCInstUtils.cpp +++ b/bolt/lib/Core/MCInstUtils.cpp @@ -55,3 +55,23 @@ raw_ostream &MCInstReference::print(raw_ostream &OS) const { OS << ">"; return OS; } + +std::optional MCInstReference::getSinglePredecessor() { + if (const RefInBB *Ref = tryGetRefInBB()) { +if (Ref->It != Ref->BB->begin()) + return MCInstReference(Ref->BB, &*std::prev(Ref->It)); + +if (Ref->BB->pred_size() != 1) + return std::nullopt; + +BinaryBasicBlock *PredBB = *Ref->BB->pred_begin(); +assert(!PredBB->empty() && "Empty basic blocks are not supported yet"); +return MCInstReference(PredBB, &*PredBB->rbegin()); + } + + const RefInBF &Ref = getRefInBF(); + if (Ref.It == Ref.BF->instrs().begin()) +return std::nullopt; + + return MCInstReference(Ref.BF, std::prev(Ref.It)); +} diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index ee873f7c2c21d..3514c953030a6 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -1363,6 +1363,11 @@ shouldReportUnsafeTailCall(const BinaryContext &BC, const BinaryFunction &BF, return std::nullopt; } + if (BC.MIB->isSafeJumpTableBranchForPtrAuth(Inst)) { +LL
[llvm-branch-commits] [llvm] [BOLT] Introduce helpers to match `MCInst`s one at a time (NFC) (PR #138883)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/138883 >From 70eb080d1bc6be69901ef9457b74bef7917327d8 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Wed, 7 May 2025 16:42:00 +0300 Subject: [PATCH] [BOLT] Introduce helpers to match `MCInst`s one at a time (NFC) Introduce matchInst helper function to capture and/or match the operands of MCInst. Unlike the existing `MCPlusBuilder::MCInstMatcher` machinery, matchInst is intended for the use cases when precise control over the instruction order is required. For example, when validating PtrAuth hardening, all registers are usually considered unsafe after a function call, even though callee-saved registers should preserve their old values *under normal operation*. --- bolt/include/bolt/Core/MCInstUtils.h | 128 ++ .../Target/AArch64/AArch64MCPlusBuilder.cpp | 90 +--- 2 files changed, 162 insertions(+), 56 deletions(-) diff --git a/bolt/include/bolt/Core/MCInstUtils.h b/bolt/include/bolt/Core/MCInstUtils.h index 69bf5e6159b74..50b7d56470c99 100644 --- a/bolt/include/bolt/Core/MCInstUtils.h +++ b/bolt/include/bolt/Core/MCInstUtils.h @@ -162,6 +162,134 @@ static inline raw_ostream &operator<<(raw_ostream &OS, return Ref.print(OS); } +/// Instruction-matching helpers operating on a single instruction at a time. +/// +/// Unlike MCPlusBuilder::MCInstMatcher, this matchInst() function focuses on +/// the cases where a precise control over the instruction order is important: +/// +/// // Bring the short names into the local scope: +/// using namespace MCInstMatcher; +/// // Declare the registers to capture: +/// Reg Xn, Xm; +/// // Capture the 0th and 1st operands, match the 2nd operand against the +/// // just captured Xm register, match the 3rd operand against literal 0: +/// if (!matchInst(MaybeAdd, AArch64::ADDXrs, Xm, Xn, Xm, Imm(0)) +/// return AArch64::NoRegister; +/// // Match the 0th operand against Xm: +/// if (!matchInst(MaybeBr, AArch64::BR, Xm)) +/// return AArch64::NoRegister; +/// // Return the matched register: +/// return Xm.get(); +namespace MCInstMatcher { + +// The base class to match an operand of type T. +// +// The subclasses of OpMatcher are intended to be allocated on the stack and +// to only be used by passing them to matchInst() and by calling their get() +// function, thus the peculiar `mutable` specifiers: to make the calling code +// compact and readable, the templated matchInst() function has to accept both +// long-lived Imm/Reg wrappers declared as local variables (intended to capture +// the first operand's value and match the subsequent operands, whether inside +// a single instruction or across multiple instructions), as well as temporary +// wrappers around literal values to match, f.e. Imm(42) or Reg(AArch64::XZR). +template class OpMatcher { + mutable std::optional Value; + mutable std::optional SavedValue; + + // Remember/restore the last Value - to be called by matchInst. + void remember() const { SavedValue = Value; } + void restore() const { Value = SavedValue; } + + template + friend bool matchInst(const MCInst &, unsigned, const OpMatchers &...); + +protected: + OpMatcher(std::optional ValueToMatch) : Value(ValueToMatch) {} + + bool matchValue(T OpValue) const { +// Check that OpValue does not contradict the existing Value. +bool MatchResult = !Value || *Value == OpValue; +// If MatchResult is false, all matchers will be reset before returning from +// matchInst, including this one, thus no need to assign conditionally. +Value = OpValue; + +return MatchResult; + } + +public: + /// Returns the captured value. + T get() const { +assert(Value.has_value()); +return *Value; + } +}; + +class Reg : public OpMatcher { + bool matches(const MCOperand &Op) const { +if (!Op.isReg()) + return false; + +return matchValue(Op.getReg()); + } + + template + friend bool matchInst(const MCInst &, unsigned, const OpMatchers &...); + +public: + Reg(std::optional RegToMatch = std::nullopt) + : OpMatcher(RegToMatch) {} +}; + +class Imm : public OpMatcher { + bool matches(const MCOperand &Op) const { +if (!Op.isImm()) + return false; + +return matchValue(Op.getImm()); + } + + template + friend bool matchInst(const MCInst &, unsigned, const OpMatchers &...); + +public: + Imm(std::optional ImmToMatch = std::nullopt) + : OpMatcher(ImmToMatch) {} +}; + +/// Tries to match Inst and updates Ops on success. +/// +/// If Inst has the specified Opcode and its operand list prefix matches Ops, +/// this function returns true and updates Ops, otherwise false is returned and +/// values of Ops are kept as before matchInst was called. +/// +/// Please note that while Ops are technically passed by a const reference to +/// make invocations like `matchInst(MI, Opcode, Imm(42))` possible, all their +/// fields are marked mut
[llvm-branch-commits] [llvm] AMDGPU/GlobalISel: Improve readanylane combines in regbanklegalize (PR #142789)
https://github.com/petar-avramovic updated https://github.com/llvm/llvm-project/pull/142789 >From 28f0f171b27aaf707706db71978d525c12e21491 Mon Sep 17 00:00:00 2001 From: Petar Avramovic Date: Thu, 5 Jun 2025 12:17:13 +0200 Subject: [PATCH] AMDGPU/GlobalISel: Improve readanylane combines in regbanklegalize --- .../Target/AMDGPU/AMDGPURegBankLegalize.cpp | 122 +++--- .../AMDGPU/GlobalISel/readanylane-combines.ll | 25 +--- .../GlobalISel/readanylane-combines.mir | 78 +++ 3 files changed, 125 insertions(+), 100 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalize.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalize.cpp index ba661348ca5b5..6707b641b0d25 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalize.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalize.cpp @@ -23,6 +23,7 @@ #include "GCNSubtarget.h" #include "llvm/CodeGen/GlobalISel/CSEInfo.h" #include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h" +#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineUniformityAnalysis.h" #include "llvm/CodeGen/TargetPassConfig.h" @@ -137,7 +138,109 @@ class AMDGPURegBankLegalizeCombiner { return {MatchMI, MatchMI->getOperand(1).getReg()}; } + std::pair tryMatchRALFromUnmerge(Register Src) { +MachineInstr *ReadAnyLane = MRI.getVRegDef(Src); +if (ReadAnyLane->getOpcode() == AMDGPU::G_AMDGPU_READANYLANE) { + Register RALSrc = ReadAnyLane->getOperand(1).getReg(); + if (auto *UnMerge = getOpcodeDef(RALSrc, MRI)) +return {UnMerge, UnMerge->findRegisterDefOperandIdx(RALSrc, nullptr)}; +} +return {nullptr, -1}; + } + + Register getReadAnyLaneSrc(Register Src) { +// Src = G_AMDGPU_READANYLANE RALSrc +auto [RAL, RALSrc] = tryMatch(Src, AMDGPU::G_AMDGPU_READANYLANE); +if (RAL) + return RALSrc; + +// LoVgpr, HiVgpr = G_UNMERGE_VALUES UnmergeSrc +// LoSgpr = G_AMDGPU_READANYLANE LoVgpr +// HiSgpr = G_AMDGPU_READANYLANE HiVgpr +// Src G_MERGE_VALUES LoSgpr, HiSgpr +auto *Merge = getOpcodeDef(Src, MRI); +if (Merge) { + unsigned NumElts = Merge->getNumSources(); + auto [Unmerge, Idx] = tryMatchRALFromUnmerge(Merge->getSourceReg(0)); + if (!Unmerge || Unmerge->getNumDefs() != NumElts || Idx != 0) +return {}; + + // check if all elements are from same unmerge and there is no shuffling + for (unsigned i = 1; i < NumElts; ++i) { +auto [UnmergeI, IdxI] = tryMatchRALFromUnmerge(Merge->getSourceReg(i)); +if (UnmergeI != Unmerge || (unsigned)IdxI != i) + return {}; + } + return Unmerge->getSourceReg(); +} + +// ..., VgprI, ... = G_UNMERGE_VALUES VgprLarge +// SgprI = G_AMDGPU_READANYLANE VgprI +// SgprLarge G_MERGE_VALUES ..., SgprI, ... +// ..., Src, ... = G_UNMERGE_VALUES SgprLarge +auto *UnMerge = getOpcodeDef(Src, MRI); +if (UnMerge) { + int Idx = UnMerge->findRegisterDefOperandIdx(Src, nullptr); + auto *Merge = getOpcodeDef(UnMerge->getSourceReg(), MRI); + if (Merge) { +auto [RAL, RALSrc] = +tryMatch(Merge->getSourceReg(Idx), AMDGPU::G_AMDGPU_READANYLANE); +if (RAL) + return RALSrc; + } +} + +return {}; + } + + void replaceRegWithOrBuildCopy(Register Dst, Register Src) { +if (Dst.isVirtual()) + MRI.replaceRegWith(Dst, Src); +else + B.buildCopy(Dst, Src); + } + + bool tryEliminateReadAnyLane(MachineInstr &Copy) { +Register Dst = Copy.getOperand(0).getReg(); +Register Src = Copy.getOperand(1).getReg(); +if (!Src.isVirtual()) + return false; + +Register RALDst = Src; +MachineInstr &SrcMI = *MRI.getVRegDef(Src); +if (SrcMI.getOpcode() == AMDGPU::G_BITCAST) + RALDst = SrcMI.getOperand(1).getReg(); + +Register RALSrc = getReadAnyLaneSrc(RALDst); +if (!RALSrc) + return false; + +B.setInstr(Copy); +if (SrcMI.getOpcode() != AMDGPU::G_BITCAST) { + // Src = READANYLANE RALSrc Src = READANYLANE RALSrc + // Dst = Copy Src $Dst = Copy Src + // -> -> + // Dst = RALSrc $Dst = Copy RALSrc + replaceRegWithOrBuildCopy(Dst, RALSrc); +} else { + // RALDst = READANYLANE RALSrc RALDst = READANYLANE RALSrc + // Src = G_BITCAST RALDst Src = G_BITCAST RALDst + // Dst = Copy Src Dst = Copy Src + // -> -> + // NewVgpr = G_BITCAST RALDst NewVgpr = G_BITCAST RALDst + // Dst = NewVgpr$Dst = Copy NewVgpr + auto Bitcast = B.buildBitcast({VgprRB, MRI.getType(Src)}, RALSrc); + replaceRegWithOrBuildCopy(Dst, Bitcast.getReg(0)); +} + +eraseInstr(Copy, MRI, nullptr); +return true; + } + void tryCombineCopy(MachineInstr &MI) { +if (tryEliminateReadAnyLane(MI)) + return; + Register Dst = MI.get
[llvm-branch-commits] [llvm] AMDGPU/GlobalISel: Add waterfall lowering in regbanklegalize (PR #142790)
https://github.com/petar-avramovic updated https://github.com/llvm/llvm-project/pull/142790 >From ec14c19baccfeb87380bf99f728b213db3db05e2 Mon Sep 17 00:00:00 2001 From: Petar Avramovic Date: Thu, 5 Jun 2025 12:43:04 +0200 Subject: [PATCH] AMDGPU/GlobalISel: Add waterfall lowering in regbanklegalize Add rules for G_AMDGPU_BUFFER_LOAD and implement waterfall lowering for divergent operands that must be sgpr. --- .../Target/AMDGPU/AMDGPUGlobalISelUtils.cpp | 53 +++- .../lib/Target/AMDGPU/AMDGPUGlobalISelUtils.h | 2 + .../Target/AMDGPU/AMDGPURegBankLegalize.cpp | 17 +- .../AMDGPU/AMDGPURegBankLegalizeHelper.cpp| 239 +- .../AMDGPU/AMDGPURegBankLegalizeHelper.h | 1 + .../AMDGPU/AMDGPURegBankLegalizeRules.cpp | 22 +- .../AMDGPU/AMDGPURegBankLegalizeRules.h | 6 +- .../AMDGPU/GlobalISel/buffer-schedule.ll | 2 +- .../llvm.amdgcn.make.buffer.rsrc.ll | 2 +- .../regbankselect-amdgcn.raw.buffer.load.ll | 59 ++--- ...egbankselect-amdgcn.raw.ptr.buffer.load.ll | 59 ++--- ...regbankselect-amdgcn.struct.buffer.load.ll | 59 ++--- ...ankselect-amdgcn.struct.ptr.buffer.load.ll | 59 ++--- .../llvm.amdgcn.buffer.load-last-use.ll | 2 +- .../llvm.amdgcn.raw.atomic.buffer.load.ll | 42 +-- .../llvm.amdgcn.raw.ptr.atomic.buffer.load.ll | 42 +-- .../llvm.amdgcn.struct.atomic.buffer.load.ll | 48 ++-- ...vm.amdgcn.struct.ptr.atomic.buffer.load.ll | 48 ++-- .../CodeGen/AMDGPU/swizzle.bit.extract.ll | 4 +- 19 files changed, 523 insertions(+), 243 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.cpp b/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.cpp index 00979f44f9d34..d8be3aee1f410 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.cpp @@ -117,45 +117,72 @@ static LLT getReadAnyLaneSplitTy(LLT Ty) { return LLT::scalar(32); } -static Register buildReadAnyLane(MachineIRBuilder &B, Register VgprSrc, - const RegisterBankInfo &RBI); +using ReadLaneFnTy = +function_ref; + +static Register buildReadLane(MachineIRBuilder &, Register, + const RegisterBankInfo &, ReadLaneFnTy); static void unmergeReadAnyLane(MachineIRBuilder &B, SmallVectorImpl &SgprDstParts, LLT UnmergeTy, Register VgprSrc, - const RegisterBankInfo &RBI) { + const RegisterBankInfo &RBI, + ReadLaneFnTy BuildRL) { const RegisterBank *VgprRB = &RBI.getRegBank(AMDGPU::VGPRRegBankID); auto Unmerge = B.buildUnmerge({VgprRB, UnmergeTy}, VgprSrc); for (unsigned i = 0; i < Unmerge->getNumOperands() - 1; ++i) { -SgprDstParts.push_back(buildReadAnyLane(B, Unmerge.getReg(i), RBI)); +SgprDstParts.push_back(buildReadLane(B, Unmerge.getReg(i), RBI, BuildRL)); } } -static Register buildReadAnyLane(MachineIRBuilder &B, Register VgprSrc, - const RegisterBankInfo &RBI) { +static Register buildReadLane(MachineIRBuilder &B, Register VgprSrc, + const RegisterBankInfo &RBI, + ReadLaneFnTy BuildRL) { LLT Ty = B.getMRI()->getType(VgprSrc); const RegisterBank *SgprRB = &RBI.getRegBank(AMDGPU::SGPRRegBankID); if (Ty.getSizeInBits() == 32) { -return B.buildInstr(AMDGPU::G_AMDGPU_READANYLANE, {{SgprRB, Ty}}, {VgprSrc}) -.getReg(0); +Register SgprDst = B.getMRI()->createVirtualRegister({SgprRB, Ty}); +return BuildRL(B, SgprDst, VgprSrc).getReg(0); } SmallVector SgprDstParts; - unmergeReadAnyLane(B, SgprDstParts, getReadAnyLaneSplitTy(Ty), VgprSrc, RBI); + unmergeReadAnyLane(B, SgprDstParts, getReadAnyLaneSplitTy(Ty), VgprSrc, RBI, + BuildRL); return B.buildMergeLikeInstr({SgprRB, Ty}, SgprDstParts).getReg(0); } -void AMDGPU::buildReadAnyLane(MachineIRBuilder &B, Register SgprDst, - Register VgprSrc, const RegisterBankInfo &RBI) { +static void buildReadLane(MachineIRBuilder &B, Register SgprDst, + Register VgprSrc, const RegisterBankInfo &RBI, + ReadLaneFnTy BuildReadLane) { LLT Ty = B.getMRI()->getType(VgprSrc); if (Ty.getSizeInBits() == 32) { -B.buildInstr(AMDGPU::G_AMDGPU_READANYLANE, {SgprDst}, {VgprSrc}); +BuildReadLane(B, SgprDst, VgprSrc); return; } SmallVector SgprDstParts; - unmergeReadAnyLane(B, SgprDstParts, getReadAnyLaneSplitTy(Ty), VgprSrc, RBI); + unmergeReadAnyLane(B, SgprDstParts, getReadAnyLaneSplitTy(Ty), VgprSrc, RBI, + BuildReadLane); B.buildMergeLikeInstr(SgprDst, SgprDstParts).getReg(0); } + +void AMDGPU::buildReadAnyLane(MachineIRBuilder &B, Register SgprDst, + Register VgprSrc, const RegisterBankInfo &RBI) { + return bu
[llvm-branch-commits] [llvm] AMDGPU/GlobalISel: Add waterfall lowering in regbanklegalize (PR #142790)
https://github.com/petar-avramovic updated https://github.com/llvm/llvm-project/pull/142790 >From ec14c19baccfeb87380bf99f728b213db3db05e2 Mon Sep 17 00:00:00 2001 From: Petar Avramovic Date: Thu, 5 Jun 2025 12:43:04 +0200 Subject: [PATCH] AMDGPU/GlobalISel: Add waterfall lowering in regbanklegalize Add rules for G_AMDGPU_BUFFER_LOAD and implement waterfall lowering for divergent operands that must be sgpr. --- .../Target/AMDGPU/AMDGPUGlobalISelUtils.cpp | 53 +++- .../lib/Target/AMDGPU/AMDGPUGlobalISelUtils.h | 2 + .../Target/AMDGPU/AMDGPURegBankLegalize.cpp | 17 +- .../AMDGPU/AMDGPURegBankLegalizeHelper.cpp| 239 +- .../AMDGPU/AMDGPURegBankLegalizeHelper.h | 1 + .../AMDGPU/AMDGPURegBankLegalizeRules.cpp | 22 +- .../AMDGPU/AMDGPURegBankLegalizeRules.h | 6 +- .../AMDGPU/GlobalISel/buffer-schedule.ll | 2 +- .../llvm.amdgcn.make.buffer.rsrc.ll | 2 +- .../regbankselect-amdgcn.raw.buffer.load.ll | 59 ++--- ...egbankselect-amdgcn.raw.ptr.buffer.load.ll | 59 ++--- ...regbankselect-amdgcn.struct.buffer.load.ll | 59 ++--- ...ankselect-amdgcn.struct.ptr.buffer.load.ll | 59 ++--- .../llvm.amdgcn.buffer.load-last-use.ll | 2 +- .../llvm.amdgcn.raw.atomic.buffer.load.ll | 42 +-- .../llvm.amdgcn.raw.ptr.atomic.buffer.load.ll | 42 +-- .../llvm.amdgcn.struct.atomic.buffer.load.ll | 48 ++-- ...vm.amdgcn.struct.ptr.atomic.buffer.load.ll | 48 ++-- .../CodeGen/AMDGPU/swizzle.bit.extract.ll | 4 +- 19 files changed, 523 insertions(+), 243 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.cpp b/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.cpp index 00979f44f9d34..d8be3aee1f410 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.cpp @@ -117,45 +117,72 @@ static LLT getReadAnyLaneSplitTy(LLT Ty) { return LLT::scalar(32); } -static Register buildReadAnyLane(MachineIRBuilder &B, Register VgprSrc, - const RegisterBankInfo &RBI); +using ReadLaneFnTy = +function_ref; + +static Register buildReadLane(MachineIRBuilder &, Register, + const RegisterBankInfo &, ReadLaneFnTy); static void unmergeReadAnyLane(MachineIRBuilder &B, SmallVectorImpl &SgprDstParts, LLT UnmergeTy, Register VgprSrc, - const RegisterBankInfo &RBI) { + const RegisterBankInfo &RBI, + ReadLaneFnTy BuildRL) { const RegisterBank *VgprRB = &RBI.getRegBank(AMDGPU::VGPRRegBankID); auto Unmerge = B.buildUnmerge({VgprRB, UnmergeTy}, VgprSrc); for (unsigned i = 0; i < Unmerge->getNumOperands() - 1; ++i) { -SgprDstParts.push_back(buildReadAnyLane(B, Unmerge.getReg(i), RBI)); +SgprDstParts.push_back(buildReadLane(B, Unmerge.getReg(i), RBI, BuildRL)); } } -static Register buildReadAnyLane(MachineIRBuilder &B, Register VgprSrc, - const RegisterBankInfo &RBI) { +static Register buildReadLane(MachineIRBuilder &B, Register VgprSrc, + const RegisterBankInfo &RBI, + ReadLaneFnTy BuildRL) { LLT Ty = B.getMRI()->getType(VgprSrc); const RegisterBank *SgprRB = &RBI.getRegBank(AMDGPU::SGPRRegBankID); if (Ty.getSizeInBits() == 32) { -return B.buildInstr(AMDGPU::G_AMDGPU_READANYLANE, {{SgprRB, Ty}}, {VgprSrc}) -.getReg(0); +Register SgprDst = B.getMRI()->createVirtualRegister({SgprRB, Ty}); +return BuildRL(B, SgprDst, VgprSrc).getReg(0); } SmallVector SgprDstParts; - unmergeReadAnyLane(B, SgprDstParts, getReadAnyLaneSplitTy(Ty), VgprSrc, RBI); + unmergeReadAnyLane(B, SgprDstParts, getReadAnyLaneSplitTy(Ty), VgprSrc, RBI, + BuildRL); return B.buildMergeLikeInstr({SgprRB, Ty}, SgprDstParts).getReg(0); } -void AMDGPU::buildReadAnyLane(MachineIRBuilder &B, Register SgprDst, - Register VgprSrc, const RegisterBankInfo &RBI) { +static void buildReadLane(MachineIRBuilder &B, Register SgprDst, + Register VgprSrc, const RegisterBankInfo &RBI, + ReadLaneFnTy BuildReadLane) { LLT Ty = B.getMRI()->getType(VgprSrc); if (Ty.getSizeInBits() == 32) { -B.buildInstr(AMDGPU::G_AMDGPU_READANYLANE, {SgprDst}, {VgprSrc}); +BuildReadLane(B, SgprDst, VgprSrc); return; } SmallVector SgprDstParts; - unmergeReadAnyLane(B, SgprDstParts, getReadAnyLaneSplitTy(Ty), VgprSrc, RBI); + unmergeReadAnyLane(B, SgprDstParts, getReadAnyLaneSplitTy(Ty), VgprSrc, RBI, + BuildReadLane); B.buildMergeLikeInstr(SgprDst, SgprDstParts).getReg(0); } + +void AMDGPU::buildReadAnyLane(MachineIRBuilder &B, Register SgprDst, + Register VgprSrc, const RegisterBankInfo &RBI) { + return bu
[llvm-branch-commits] [llvm] MC: Move ExceptionHandling enum to Support (PR #144692)
arsenm wrote: ### Merge activity * **Jun 19, 9:57 AM UTC**: A user started a stack merge that includes this pull request via [Graphite](https://app.graphite.dev/github/pr/llvm/llvm-project/144692). https://github.com/llvm/llvm-project/pull/144692 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] RuntimeLibcalls: Pass in exception handling type (PR #144696)
https://github.com/nikic approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/144696 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] AMDGPU/GlobalISel: Improve readanylane combines in regbanklegalize (PR #142789)
https://github.com/petar-avramovic updated https://github.com/llvm/llvm-project/pull/142789 >From 28f0f171b27aaf707706db71978d525c12e21491 Mon Sep 17 00:00:00 2001 From: Petar Avramovic Date: Thu, 5 Jun 2025 12:17:13 +0200 Subject: [PATCH] AMDGPU/GlobalISel: Improve readanylane combines in regbanklegalize --- .../Target/AMDGPU/AMDGPURegBankLegalize.cpp | 122 +++--- .../AMDGPU/GlobalISel/readanylane-combines.ll | 25 +--- .../GlobalISel/readanylane-combines.mir | 78 +++ 3 files changed, 125 insertions(+), 100 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalize.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalize.cpp index ba661348ca5b5..6707b641b0d25 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalize.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalize.cpp @@ -23,6 +23,7 @@ #include "GCNSubtarget.h" #include "llvm/CodeGen/GlobalISel/CSEInfo.h" #include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h" +#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineUniformityAnalysis.h" #include "llvm/CodeGen/TargetPassConfig.h" @@ -137,7 +138,109 @@ class AMDGPURegBankLegalizeCombiner { return {MatchMI, MatchMI->getOperand(1).getReg()}; } + std::pair tryMatchRALFromUnmerge(Register Src) { +MachineInstr *ReadAnyLane = MRI.getVRegDef(Src); +if (ReadAnyLane->getOpcode() == AMDGPU::G_AMDGPU_READANYLANE) { + Register RALSrc = ReadAnyLane->getOperand(1).getReg(); + if (auto *UnMerge = getOpcodeDef(RALSrc, MRI)) +return {UnMerge, UnMerge->findRegisterDefOperandIdx(RALSrc, nullptr)}; +} +return {nullptr, -1}; + } + + Register getReadAnyLaneSrc(Register Src) { +// Src = G_AMDGPU_READANYLANE RALSrc +auto [RAL, RALSrc] = tryMatch(Src, AMDGPU::G_AMDGPU_READANYLANE); +if (RAL) + return RALSrc; + +// LoVgpr, HiVgpr = G_UNMERGE_VALUES UnmergeSrc +// LoSgpr = G_AMDGPU_READANYLANE LoVgpr +// HiSgpr = G_AMDGPU_READANYLANE HiVgpr +// Src G_MERGE_VALUES LoSgpr, HiSgpr +auto *Merge = getOpcodeDef(Src, MRI); +if (Merge) { + unsigned NumElts = Merge->getNumSources(); + auto [Unmerge, Idx] = tryMatchRALFromUnmerge(Merge->getSourceReg(0)); + if (!Unmerge || Unmerge->getNumDefs() != NumElts || Idx != 0) +return {}; + + // check if all elements are from same unmerge and there is no shuffling + for (unsigned i = 1; i < NumElts; ++i) { +auto [UnmergeI, IdxI] = tryMatchRALFromUnmerge(Merge->getSourceReg(i)); +if (UnmergeI != Unmerge || (unsigned)IdxI != i) + return {}; + } + return Unmerge->getSourceReg(); +} + +// ..., VgprI, ... = G_UNMERGE_VALUES VgprLarge +// SgprI = G_AMDGPU_READANYLANE VgprI +// SgprLarge G_MERGE_VALUES ..., SgprI, ... +// ..., Src, ... = G_UNMERGE_VALUES SgprLarge +auto *UnMerge = getOpcodeDef(Src, MRI); +if (UnMerge) { + int Idx = UnMerge->findRegisterDefOperandIdx(Src, nullptr); + auto *Merge = getOpcodeDef(UnMerge->getSourceReg(), MRI); + if (Merge) { +auto [RAL, RALSrc] = +tryMatch(Merge->getSourceReg(Idx), AMDGPU::G_AMDGPU_READANYLANE); +if (RAL) + return RALSrc; + } +} + +return {}; + } + + void replaceRegWithOrBuildCopy(Register Dst, Register Src) { +if (Dst.isVirtual()) + MRI.replaceRegWith(Dst, Src); +else + B.buildCopy(Dst, Src); + } + + bool tryEliminateReadAnyLane(MachineInstr &Copy) { +Register Dst = Copy.getOperand(0).getReg(); +Register Src = Copy.getOperand(1).getReg(); +if (!Src.isVirtual()) + return false; + +Register RALDst = Src; +MachineInstr &SrcMI = *MRI.getVRegDef(Src); +if (SrcMI.getOpcode() == AMDGPU::G_BITCAST) + RALDst = SrcMI.getOperand(1).getReg(); + +Register RALSrc = getReadAnyLaneSrc(RALDst); +if (!RALSrc) + return false; + +B.setInstr(Copy); +if (SrcMI.getOpcode() != AMDGPU::G_BITCAST) { + // Src = READANYLANE RALSrc Src = READANYLANE RALSrc + // Dst = Copy Src $Dst = Copy Src + // -> -> + // Dst = RALSrc $Dst = Copy RALSrc + replaceRegWithOrBuildCopy(Dst, RALSrc); +} else { + // RALDst = READANYLANE RALSrc RALDst = READANYLANE RALSrc + // Src = G_BITCAST RALDst Src = G_BITCAST RALDst + // Dst = Copy Src Dst = Copy Src + // -> -> + // NewVgpr = G_BITCAST RALDst NewVgpr = G_BITCAST RALDst + // Dst = NewVgpr$Dst = Copy NewVgpr + auto Bitcast = B.buildBitcast({VgprRB, MRI.getType(Src)}, RALSrc); + replaceRegWithOrBuildCopy(Dst, Bitcast.getReg(0)); +} + +eraseInstr(Copy, MRI, nullptr); +return true; + } + void tryCombineCopy(MachineInstr &MI) { +if (tryEliminateReadAnyLane(MI)) + return; + Register Dst = MI.get
[llvm-branch-commits] [clang] 366be49 - Revert "[CUDA][HIP] Add a __device__ version of std::__glibcxx_assert_fail() …"
Author: Juan Manuel Martinez Caamaño Date: 2025-06-19T09:11:36+02:00 New Revision: 366be49837a1fa669d836cc167b1b6dbf2725110 URL: https://github.com/llvm/llvm-project/commit/366be49837a1fa669d836cc167b1b6dbf2725110 DIFF: https://github.com/llvm/llvm-project/commit/366be49837a1fa669d836cc167b1b6dbf2725110.diff LOG: Revert "[CUDA][HIP] Add a __device__ version of std::__glibcxx_assert_fail() …" This reverts commit cb011d3199e1160ad2706cb5b1d43692fa4784d8. Added: Modified: clang/lib/Headers/CMakeLists.txt Removed: clang/lib/Headers/cuda_wrappers/bits/c++config.h diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index c96d209c1fc0c..c1c9d2e8c7b79 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -341,7 +341,6 @@ set(cuda_wrapper_files ) set(cuda_wrapper_bits_files - cuda_wrappers/bits/c++config.h cuda_wrappers/bits/shared_ptr_base.h cuda_wrappers/bits/basic_string.h cuda_wrappers/bits/basic_string.tcc diff --git a/clang/lib/Headers/cuda_wrappers/bits/c++config.h b/clang/lib/Headers/cuda_wrappers/bits/c++config.h deleted file mode 100644 index eafa13a9cc640..0 --- a/clang/lib/Headers/cuda_wrappers/bits/c++config.h +++ /dev/null @@ -1,51 +0,0 @@ -// libstdc++ uses the non-constexpr function std::__glibcxx_assert_fail() -// to trigger compilation errors when the __glibcxx_assert(cond) macro -// is used in a constexpr context. -// Compilation fails when using code from the libstdc++ (such as std::array) on -// device code, since these assertions invoke a non-constexpr host function from -// device code. -// -// To work around this issue, we declare our own device version of the function - -#ifndef __CLANG_CUDA_WRAPPERS_BITS_CPP_CONFIG -#define __CLANG_CUDA_WRAPPERS_BITS_CPP_CONFIG - -#include_next - -#ifdef _LIBCPP_BEGIN_NAMESPACE_STD -_LIBCPP_BEGIN_NAMESPACE_STD -#else -namespace std { -#ifdef _GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_BEGIN_NAMESPACE_VERSION -#endif - -#ifdef _GLIBCXX_VERBOSE_ASSERT -__attribute__((device, noreturn)) inline void -__glibcxx_assert_fail(const char *file, int line, const char *function, - const char *condition) noexcept { - if (file && function && condition) -__builtin_printf("%s:%d: %s: Assertion '%s' failed.\n", file, line, - function, condition); - else if (function) -__builtin_printf("%s: Undefined behavior detected.\n", function); - __builtin_abort(); -} -#endif - -#endif -__attribute__((device, noreturn, __always_inline__, - __visibility__("default"))) inline void -__glibcxx_assert_fail(...) noexcept { - __builtin_abort(); -} -#ifdef _LIBCPP_END_NAMESPACE_STD -_LIBCPP_END_NAMESPACE_STD -#else -#ifdef _GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_END_NAMESPACE_VERSION -#endif -} // namespace std -#endif - -#endif ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] MC: Move ExceptionHandling enum to Support (PR #144692)
https://github.com/nikic approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/144692 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits