[flang-commits] [clang] [flang] [llvm] [mlir] [polly] [IR] Use persistent metadata IDs for printing (PR #216838)
Yaxun Liu via flang-commits
flang-commits at lists.llvm.org
Sat Aug 29 14:10:57 PDT 2026
https://github.com/yxsamliu updated https://github.com/llvm/llvm-project/pull/216838
>From a08fffee118c3991aba48027a9447848c7214c84 Mon Sep 17 00:00:00 2001
From: "Yaxun (Sam) Liu" <yaxun.liu at amd.com>
Date: Fri, 28 Aug 2026 15:51:01 -0400
Subject: [PATCH 1/2] [MIR] Round-trip all machine metadata nodes
MIR only emitted definitions for a subset of metadata referenced by machine
functions. Other nodes were printed as pointer values and could not be parsed
back.
Collect metadata referenced by machine instructions, memory operands, and
variable debug information. Keep debug locations inline so the output remains
readable.
Parse each machine metadata item with LLVM IR's metadata parser while
preserving the YAML item boundaries. This supports specialized nodes, cycles,
and forward references without accepting definitions split across list items,
and removes the old tuple-only parser.
---
llvm/include/llvm/AsmParser/LLLexer.h | 1 +
llvm/include/llvm/AsmParser/LLParser.h | 3 +
llvm/include/llvm/AsmParser/Parser.h | 10 ++
.../include/llvm/CodeGen/MIRParser/MIParser.h | 5 -
llvm/lib/AsmParser/LLParser.cpp | 83 ++++++++++
llvm/lib/AsmParser/Parser.cpp | 49 ++++++
llvm/lib/CodeGen/MIRParser/MIParser.cpp | 153 ------------------
llvm/lib/CodeGen/MIRParser/MIRParser.cpp | 38 ++---
llvm/lib/CodeGen/MachineModuleSlotTracker.cpp | 28 +++-
.../GlobalISel/irtranslator-metadata.ll | 2 +-
.../AMDGPU/dbg-value-ends-sched-region.mir | 2 +-
...ip-processing-stack-arg-dbg-value-list.mir | 5 +-
...ip-processing-stack-arg-dbg-value-list.mir | 5 +-
.../MIR/Generic/machine-metadata-err0.mir | 2 +-
.../MIR/Generic/machine-metadata-err1.mir | 2 +-
.../MIR/Generic/machine-metadata-err10.mir | 15 ++
.../MIR/Generic/machine-metadata-err11.mir | 16 ++
.../MIR/Generic/machine-metadata-err12.mir | 19 +++
.../MIR/Generic/machine-metadata-err2.mir | 2 +-
.../MIR/Generic/machine-metadata-err6.mir | 2 +-
.../MIR/Generic/machine-metadata-err7.mir | 2 +-
.../MIR/Generic/machine-metadata-err8.mir | 2 +-
.../MIR/Generic/machine-metadata-err9.mir | 16 ++
.../MIR/X86/machine-metadata-round-trip.mir | 35 ++++
.../MIR/X86/machine-metadata-specialized.mir | 38 +++++
25 files changed, 348 insertions(+), 187 deletions(-)
create mode 100644 llvm/test/CodeGen/MIR/Generic/machine-metadata-err10.mir
create mode 100644 llvm/test/CodeGen/MIR/Generic/machine-metadata-err11.mir
create mode 100644 llvm/test/CodeGen/MIR/Generic/machine-metadata-err12.mir
create mode 100644 llvm/test/CodeGen/MIR/Generic/machine-metadata-err9.mir
create mode 100644 llvm/test/CodeGen/MIR/X86/machine-metadata-round-trip.mir
create mode 100644 llvm/test/CodeGen/MIR/X86/machine-metadata-specialized.mir
diff --git a/llvm/include/llvm/AsmParser/LLLexer.h b/llvm/include/llvm/AsmParser/LLLexer.h
index a33e7828fb2fc..c1010e0485c55 100644
--- a/llvm/include/llvm/AsmParser/LLLexer.h
+++ b/llvm/include/llvm/AsmParser/LLLexer.h
@@ -69,6 +69,7 @@ namespace llvm {
typedef SMLoc LocTy;
LocTy getLoc() const { return SMLoc::getFromPointer(TokStart); }
+ LocTy getPrevTokEndLoc() const { return SMLoc::getFromPointer(PrevTokEnd); }
lltok::Kind getKind() const { return CurKind; }
const std::string &getStrVal() const { return StrVal; }
Type *getTyVal() const { return TyVal; }
diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index 788b56cb78f08..7cc8e9877bbd0 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -235,6 +235,9 @@ namespace llvm {
unsigned &Read,
const SlotMapping *Slots);
+ LLVM_ABI bool parseMetadataDefinitions(SlotMapping &Slots,
+ ArrayRef<SMLoc> DefinitionEnds);
+
LLVMContext &getContext() { return Context; }
private:
diff --git a/llvm/include/llvm/AsmParser/Parser.h b/llvm/include/llvm/AsmParser/Parser.h
index 22b0881d92b53..2ceb63bd29cd5 100644
--- a/llvm/include/llvm/AsmParser/Parser.h
+++ b/llvm/include/llvm/AsmParser/Parser.h
@@ -13,6 +13,7 @@
#ifndef LLVM_ASMPARSER_PARSER_H
#define LLVM_ASMPARSER_PARSER_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/AsmParser/AsmParserContext.h"
@@ -211,6 +212,15 @@ parseDIExpressionBodyAtBeginning(StringRef Asm, unsigned &Read,
SMDiagnostic &Err, const Module &M,
const SlotMapping *Slots);
+/// Parse standalone metadata definitions using and updating the supplied slot
+/// mapping. Each string must contain exactly one complete definition.
+/// \param ErrorDefinitionIndex The index of the definition containing an error.
+/// \return true on error.
+LLVM_ABI bool parseMetadataDefinitions(ArrayRef<StringRef> Definitions,
+ SMDiagnostic &Err, const Module &M,
+ SlotMapping &Slots,
+ unsigned &ErrorDefinitionIndex);
+
} // End llvm namespace
#endif
diff --git a/llvm/include/llvm/CodeGen/MIRParser/MIParser.h b/llvm/include/llvm/CodeGen/MIRParser/MIParser.h
index 622862279cfdd..1c30ad02e1705 100644
--- a/llvm/include/llvm/CodeGen/MIRParser/MIParser.h
+++ b/llvm/include/llvm/CodeGen/MIRParser/MIParser.h
@@ -173,7 +173,6 @@ struct PerFunctionMIParsingState {
PerTargetMIParsingState &Target;
std::map<unsigned, TrackingMDNodeRef> MachineMetadataNodes;
- std::map<unsigned, std::pair<TempMDTuple, SMLoc>> MachineForwardRefMDNodes;
DenseMap<unsigned, MachineBasicBlock *> MBBSlots;
DenseMap<Register, VRegInfo *> VRegInfos;
@@ -249,10 +248,6 @@ LLVM_ABI bool parsePrefetchTarget(PerFunctionMIParsingState &PFS,
LLVM_ABI bool parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node,
StringRef Src, SMDiagnostic &Error);
-LLVM_ABI bool parseMachineMetadata(PerFunctionMIParsingState &PFS,
- StringRef Src, SMRange SourceRange,
- SMDiagnostic &Error);
-
} // end namespace llvm
#endif // LLVM_CODEGEN_MIRPARSER_MIPARSER_H
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index fa7f2af27cc91..4afca993adf0b 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -72,6 +72,52 @@ static std::string getTypeString(Type *T) {
return Tmp.str();
}
+/// Return whether skipped trivia contains a block comment that crosses the
+/// boundary between two metadata definitions.
+static bool blockCommentCrossesBoundary(SMLoc BeginLoc, SMLoc EndLoc,
+ SMLoc BoundaryLoc) {
+ const char *Begin = BeginLoc.getPointer();
+ const char *End = EndLoc.getPointer();
+ const char *Boundary = BoundaryLoc.getPointer();
+ const char *BlockCommentStart = nullptr;
+ bool InLineComment = false;
+
+ for (const char *Ptr = Begin; Ptr < End;) {
+ if (BlockCommentStart) {
+ if (Ptr + 1 < End && Ptr[0] == '*' && Ptr[1] == '/') {
+ Ptr += 2;
+ if (BlockCommentStart < Boundary && Ptr > Boundary)
+ return true;
+ BlockCommentStart = nullptr;
+ continue;
+ }
+ ++Ptr;
+ continue;
+ }
+
+ if (InLineComment) {
+ if (*Ptr == '\n' || *Ptr == '\r')
+ InLineComment = false;
+ ++Ptr;
+ continue;
+ }
+
+ if (*Ptr == ';') {
+ InLineComment = true;
+ ++Ptr;
+ continue;
+ }
+ if (Ptr + 1 < End && Ptr[0] == '/' && Ptr[1] == '*') {
+ BlockCommentStart = Ptr;
+ Ptr += 2;
+ continue;
+ }
+ ++Ptr;
+ }
+
+ return BlockCommentStart && BlockCommentStart < Boundary && End > Boundary;
+}
+
/// Run: module ::= toplevelentity*
bool LLParser::Run(bool UpgradeDebugInfo,
DataLayoutCallbackTy DataLayoutCallback) {
@@ -136,6 +182,43 @@ bool LLParser::parseDIExpressionBodyAtBeginning(MDNode *&Result, unsigned &Read,
return Status;
}
+bool LLParser::parseMetadataDefinitions(SlotMapping &Slots,
+ ArrayRef<SMLoc> DefinitionEnds) {
+ restoreParsingState(&Slots);
+ Lex.Lex();
+
+ for (SMLoc End : DefinitionEnds) {
+ if (Lex.getLoc().getPointer() >= End.getPointer())
+ return error(End, "expected end of metadata definition");
+ if (Lex.getKind() != lltok::exclaim)
+ return tokError("expected a metadata definition");
+ if (parseStandaloneMetadata())
+ return true;
+ if (Lex.getPrevTokEndLoc().getPointer() > End.getPointer() ||
+ (Lex.getKind() != lltok::Eof &&
+ Lex.getLoc().getPointer() < End.getPointer()) ||
+ blockCommentCrossesBoundary(Lex.getPrevTokEndLoc(), Lex.getLoc(), End))
+ return error(End, "expected end of metadata definition");
+ }
+
+ if (Lex.getKind() != lltok::Eof)
+ return tokError("expected end of metadata definitions");
+
+ if (!ForwardRefMDNodes.empty())
+ return error(ForwardRefMDNodes.begin()->second.second,
+ "use of undefined metadata '!" +
+ Twine(ForwardRefMDNodes.begin()->first) + "'");
+
+ for (auto &[_, MD] : NumberedMetadata)
+ if (MD && !MD->isResolved())
+ MD->resolveCycles();
+ DISubprogram::cleanupRetainedNodes(NewDistinctSPs);
+ NewDistinctSPs.clear();
+
+ Slots.MetadataNodes = std::move(NumberedMetadata);
+ return false;
+}
+
void LLParser::restoreParsingState(const SlotMapping *Slots) {
if (!Slots)
return;
diff --git a/llvm/lib/AsmParser/Parser.cpp b/llvm/lib/AsmParser/Parser.cpp
index f33a9dad2bb06..d52141d158122 100644
--- a/llvm/lib/AsmParser/Parser.cpp
+++ b/llvm/lib/AsmParser/Parser.cpp
@@ -11,12 +11,14 @@
//===----------------------------------------------------------------------===//
#include "llvm/AsmParser/Parser.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/AsmParser/LLParser.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
+#include <algorithm>
#include <system_error>
using namespace llvm;
@@ -247,3 +249,50 @@ DIExpression *llvm::parseDIExpressionBodyAtBeginning(StringRef Asm,
return nullptr;
return dyn_cast<DIExpression>(MD);
}
+
+bool llvm::parseMetadataDefinitions(ArrayRef<StringRef> Definitions,
+ SMDiagnostic &Err, const Module &M,
+ SlotMapping &Slots,
+ unsigned &ErrorDefinitionIndex) {
+ std::string Asm;
+ SmallVector<std::pair<size_t, size_t>> DefinitionRanges;
+ for (StringRef Definition : Definitions) {
+ size_t Start = Asm.size();
+ Asm.append(Definition);
+ DefinitionRanges.emplace_back(Start, Asm.size());
+ Asm.push_back('\n');
+ }
+
+ SourceMgr SM;
+ std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Asm);
+ SM.AddNewSourceBuffer(std::move(Buf), SMLoc());
+ SmallVector<SMLoc> DefinitionEnds;
+ for (auto [_, End] : DefinitionRanges)
+ DefinitionEnds.push_back(SMLoc::getFromPointer(Asm.data() + End));
+ if (!LLParser(Asm, SM, Err, const_cast<Module *>(&M), nullptr, M.getContext())
+ .parseMetadataDefinitions(Slots, DefinitionEnds))
+ return false;
+
+ const char *ErrorPtr = Err.getLoc().getPointer();
+ size_t ErrorOffset =
+ ErrorPtr ? std::min<size_t>(ErrorPtr - Asm.data(), Asm.size()) : 0;
+ ErrorDefinitionIndex = DefinitionRanges.size() - 1;
+ for (unsigned I = 0; I != DefinitionRanges.size(); ++I) {
+ if (ErrorOffset <= DefinitionRanges[I].second) {
+ ErrorDefinitionIndex = I;
+ break;
+ }
+ }
+
+ auto [Start, End] = DefinitionRanges[ErrorDefinitionIndex];
+ size_t DefinitionOffset = std::clamp(ErrorOffset, Start, End) - Start;
+ SourceMgr DefinitionSM;
+ std::unique_ptr<MemoryBuffer> DefinitionBuf = MemoryBuffer::getMemBuffer(
+ Definitions[ErrorDefinitionIndex], "", /*RequiresNullTerminator=*/false);
+ StringRef Definition = DefinitionBuf->getBuffer();
+ DefinitionSM.AddNewSourceBuffer(std::move(DefinitionBuf), SMLoc());
+ Err = DefinitionSM.GetMessage(
+ SMLoc::getFromPointer(Definition.data() + DefinitionOffset),
+ Err.getKind(), Err.getMessage());
+ return true;
+}
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index bb0b87cc042d0..a9caf95a32ef9 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -401,7 +401,6 @@ class MIParser {
MachineFunction &MF;
SMDiagnostic &Error;
StringRef Source, CurrentSource;
- SMRange SourceRange;
MIToken Token;
PerFunctionMIParsingState &PFS;
/// Maps from slot numbers to function's unnamed basic blocks.
@@ -410,8 +409,6 @@ class MIParser {
public:
MIParser(PerFunctionMIParsingState &PFS, SMDiagnostic &Error,
StringRef Source);
- MIParser(PerFunctionMIParsingState &PFS, SMDiagnostic &Error,
- StringRef Source, SMRange SourceRange);
/// \p SkipChar gives the number of characters to skip before looking
/// for the next token.
@@ -437,10 +434,6 @@ class MIParser {
bool parseStandaloneRegister(Register &Reg);
bool parseStandaloneStackObject(int &FI);
bool parseStandaloneMDNode(MDNode *&Node);
- bool parseMachineMetadata();
- bool parseMDTuple(MDNode *&MD, bool IsDistinct);
- bool parseMDNodeVector(SmallVectorImpl<Metadata *> &Elts);
- bool parseMetadata(Metadata *&MD);
bool
parseBasicBlockDefinition(DenseMap<unsigned, MachineBasicBlock *> &MBBSlots);
@@ -574,10 +567,6 @@ class MIParser {
/// parseStringConstant
/// ::= StringConstant
bool parseStringConstant(std::string &Result);
-
- /// Map the location in the MI string to the corresponding location specified
- /// in `SourceRange`.
- SMLoc mapSMLoc(StringRef::iterator Loc);
};
} // end anonymous namespace
@@ -587,11 +576,6 @@ MIParser::MIParser(PerFunctionMIParsingState &PFS, SMDiagnostic &Error,
: MF(PFS.MF), Error(Error), Source(Source), CurrentSource(Source), PFS(PFS)
{}
-MIParser::MIParser(PerFunctionMIParsingState &PFS, SMDiagnostic &Error,
- StringRef Source, SMRange SourceRange)
- : MF(PFS.MF), Error(Error), Source(Source), CurrentSource(Source),
- SourceRange(SourceRange), PFS(PFS) {}
-
void MIParser::lex(unsigned SkipChar) {
CurrentSource = lexMIToken(
CurrentSource.substr(SkipChar), Token,
@@ -617,13 +601,6 @@ bool MIParser::error(StringRef::iterator Loc, const Twine &Msg) {
return true;
}
-SMLoc MIParser::mapSMLoc(StringRef::iterator Loc) {
- assert(SourceRange.isValid() && "Invalid source range");
- assert(Loc >= Source.data() && Loc <= (Source.data() + Source.size()));
- return SMLoc::getFromPointer(SourceRange.Start.getPointer() +
- (Loc - Source.data()));
-}
-
typedef function_ref<bool(StringRef::iterator Loc, const Twine &)>
ErrorCallbackType;
@@ -1341,131 +1318,6 @@ bool MIParser::parseStandaloneMDNode(MDNode *&Node) {
return false;
}
-bool MIParser::parseMachineMetadata() {
- lex();
- if (Token.isNot(MIToken::exclaim))
- return error("expected a metadata node");
-
- lex();
- if (Token.isNot(MIToken::IntegerLiteral) || Token.integerValue().isSigned())
- return error("expected metadata id after '!'");
- unsigned ID = 0;
- if (getUnsigned(ID))
- return true;
- lex();
- if (expectAndConsume(MIToken::equal))
- return true;
- bool IsDistinct = Token.is(MIToken::kw_distinct);
- if (IsDistinct)
- lex();
- if (Token.isNot(MIToken::exclaim))
- return error("expected a metadata node");
- lex();
-
- MDNode *MD;
- if (parseMDTuple(MD, IsDistinct))
- return true;
-
- auto FI = PFS.MachineForwardRefMDNodes.find(ID);
- if (FI != PFS.MachineForwardRefMDNodes.end()) {
- FI->second.first->replaceAllUsesWith(MD);
- PFS.MachineForwardRefMDNodes.erase(FI);
-
- assert(PFS.MachineMetadataNodes[ID] == MD && "Tracking VH didn't work");
- } else {
- auto [It, Inserted] = PFS.MachineMetadataNodes.try_emplace(ID);
- if (!Inserted)
- return error("Metadata id is already used");
- It->second.reset(MD);
- }
-
- return false;
-}
-
-bool MIParser::parseMDTuple(MDNode *&MD, bool IsDistinct) {
- SmallVector<Metadata *, 16> Elts;
- if (parseMDNodeVector(Elts))
- return true;
- MD = (IsDistinct ? MDTuple::getDistinct
- : MDTuple::get)(MF.getFunction().getContext(), Elts);
- return false;
-}
-
-bool MIParser::parseMDNodeVector(SmallVectorImpl<Metadata *> &Elts) {
- if (Token.isNot(MIToken::lbrace))
- return error("expected '{' here");
- lex();
-
- if (Token.is(MIToken::rbrace)) {
- lex();
- return false;
- }
-
- do {
- Metadata *MD;
- if (parseMetadata(MD))
- return true;
-
- Elts.push_back(MD);
-
- if (Token.isNot(MIToken::comma))
- break;
- lex();
- } while (true);
-
- if (Token.isNot(MIToken::rbrace))
- return error("expected end of metadata node");
- lex();
-
- return false;
-}
-
-// ::= !42
-// ::= !"string"
-bool MIParser::parseMetadata(Metadata *&MD) {
- if (Token.isNot(MIToken::exclaim))
- return error("expected '!' here");
- lex();
-
- if (Token.is(MIToken::StringConstant)) {
- std::string Str;
- if (parseStringConstant(Str))
- return true;
- MD = MDString::get(MF.getFunction().getContext(), Str);
- return false;
- }
-
- if (Token.isNot(MIToken::IntegerLiteral) || Token.integerValue().isSigned())
- return error("expected metadata id after '!'");
-
- SMLoc Loc = mapSMLoc(Token.location());
-
- unsigned ID = 0;
- if (getUnsigned(ID))
- return true;
- lex();
-
- auto NodeInfo = PFS.IRSlots.MetadataNodes.find(ID);
- if (NodeInfo != PFS.IRSlots.MetadataNodes.end()) {
- MD = NodeInfo->second.get();
- return false;
- }
- // Check machine metadata.
- NodeInfo = PFS.MachineMetadataNodes.find(ID);
- if (NodeInfo != PFS.MachineMetadataNodes.end()) {
- MD = NodeInfo->second.get();
- return false;
- }
- // Forward reference.
- auto &FwdRef = PFS.MachineForwardRefMDNodes[ID];
- FwdRef = std::make_pair(
- MDTuple::getTemporary(MF.getFunction().getContext(), {}), Loc);
- PFS.MachineMetadataNodes[ID].reset(FwdRef.first.get());
- MD = FwdRef.first.get();
-
- return false;
-}
-
static const char *printImplicitRegisterFlag(const MachineOperand &MO) {
assert(MO.isImplicit());
return MO.isDef() ? "implicit-def" : "implicit";
@@ -4060,11 +3912,6 @@ bool llvm::parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node,
return MIParser(PFS, Error, Src).parseStandaloneMDNode(Node);
}
-bool llvm::parseMachineMetadata(PerFunctionMIParsingState &PFS, StringRef Src,
- SMRange SrcRange, SMDiagnostic &Error) {
- return MIParser(PFS, Error, Src, SrcRange).parseMachineMetadata();
-}
-
bool MIRFormatter::parseIRValue(StringRef Src, MachineFunction &MF,
PerFunctionMIParsingState &PFS, const Value *&V,
ErrorCallbackType ErrorCallback) {
diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
index 6f1e7594f34da..0a9ebf28876a7 100644
--- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
@@ -178,9 +178,6 @@ class MIRParserImpl {
MachineBasicBlock *&MBB,
const yaml::StringValue &Source);
- bool parseMachineMetadata(PerFunctionMIParsingState &PFS,
- const yaml::StringValue &Source);
-
/// Return a MIR diagnostic converted from an MI string diagnostic.
SMDiagnostic diagFromMIStringDiag(const SMDiagnostic &Error,
SMRange SourceRange);
@@ -1226,26 +1223,31 @@ bool MIRParserImpl::parseMBBReference(PerFunctionMIParsingState &PFS,
return false;
}
-bool MIRParserImpl::parseMachineMetadata(PerFunctionMIParsingState &PFS,
- const yaml::StringValue &Source) {
- SMDiagnostic Error;
- if (llvm::parseMachineMetadata(PFS, Source.Value, Source.SourceRange, Error))
- return error(Error, Source.SourceRange);
- return false;
-}
-
bool MIRParserImpl::parseMachineMetadataNodes(
PerFunctionMIParsingState &PFS, MachineFunction &MF,
const yaml::MachineFunction &YMF) {
- for (const auto &MDS : YMF.MachineMetadataNodes) {
- if (parseMachineMetadata(PFS, MDS))
+ SmallVector<StringRef> Definitions;
+ for (const auto &MDS : YMF.MachineMetadataNodes)
+ Definitions.push_back(MDS.Value);
+
+ SlotMapping Slots = PFS.IRSlots;
+ SMDiagnostic Error;
+ unsigned ErrorDefinitionIndex = 0;
+ if (parseMetadataDefinitions(Definitions, Error,
+ *MF.getFunction().getParent(), Slots,
+ ErrorDefinitionIndex)) {
+ const yaml::StringValue &Source =
+ YMF.MachineMetadataNodes[ErrorDefinitionIndex];
+ if (StringRef(Source.Value).contains('\n')) {
+ reportDiagnostic(diagFromBlockStringDiag(Error, Source.SourceRange));
return true;
+ }
+ return error(Error, Source.SourceRange);
}
- // Report missing definitions from forward referenced nodes.
- if (!PFS.MachineForwardRefMDNodes.empty())
- return error(PFS.MachineForwardRefMDNodes.begin()->second.second,
- "use of undefined metadata '!" +
- Twine(PFS.MachineForwardRefMDNodes.begin()->first) + "'");
+
+ for (auto &[ID, MD] : Slots.MetadataNodes)
+ if (PFS.IRSlots.MetadataNodes.find(ID) == PFS.IRSlots.MetadataNodes.end())
+ PFS.MachineMetadataNodes.try_emplace(ID, MD);
return false;
}
diff --git a/llvm/lib/CodeGen/MachineModuleSlotTracker.cpp b/llvm/lib/CodeGen/MachineModuleSlotTracker.cpp
index 5250330e170c2..e08b03eb4d70c 100644
--- a/llvm/lib/CodeGen/MachineModuleSlotTracker.cpp
+++ b/llvm/lib/CodeGen/MachineModuleSlotTracker.cpp
@@ -8,7 +8,10 @@
#include "llvm/CodeGen/MachineModuleSlotTracker.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/Module.h"
using namespace llvm;
@@ -17,7 +20,18 @@ void MachineModuleSlotTracker::processMachineFunctionMetadata(
AbstractSlotTrackerStorage *AST, const MachineFunction &MF) {
// Create metadata created within the backend.
for (const MachineBasicBlock &MBB : MF)
- for (const MachineInstr &MI : MBB.instrs())
+ for (const MachineInstr &MI : MBB.instrs()) {
+ if (MDNode *N = MI.getHeapAllocMarker())
+ AST->createMetadataSlot(N);
+ if (MDNode *N = MI.getPCSections())
+ AST->createMetadataSlot(N);
+ if (MDNode *N = MI.getMMRAMetadata())
+ AST->createMetadataSlot(N);
+
+ for (const MachineOperand &MO : MI.operands())
+ if (MO.isMetadata())
+ AST->createMetadataSlot(MO.getMetadata());
+
for (const MachineMemOperand *MMO : MI.memoperands()) {
AAMDNodes AAInfo = MMO->getAAInfo();
if (AAInfo.TBAA)
@@ -28,7 +42,19 @@ void MachineModuleSlotTracker::processMachineFunctionMetadata(
AST->createMetadataSlot(AAInfo.Scope);
if (AAInfo.NoAlias)
AST->createMetadataSlot(AAInfo.NoAlias);
+ if (AAInfo.NoAliasAddrSpace)
+ AST->createMetadataSlot(AAInfo.NoAliasAddrSpace);
+ if (const MDNode *N = MMO->getRanges())
+ AST->createMetadataSlot(N);
+ if (const MDNode *N = MMO->getMemCacheHint())
+ AST->createMetadataSlot(N);
}
+ }
+
+ for (const MachineFunction::VariableDbgInfo &DebugVar :
+ MF.getVariableDbgInfo()) {
+ AST->createMetadataSlot(DebugVar.Var);
+ }
}
void MachineModuleSlotTracker::processMachineModule(
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-metadata.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-metadata.ll
index f8b1a3879421d..1c6c52e0be081 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-metadata.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-metadata.ll
@@ -7,7 +7,7 @@ define i32 @reloc_constant() {
; CHECK-LABEL: name: reloc_constant
; CHECK: bb.1 (%ir-block.0):
; CHECK-NEXT: [[INT:%[0-9]+]]:_(i32) = G_INTRINSIC intrinsic(@llvm.amdgcn.reloc.constant), !0
- ; CHECK-NEXT: [[INT1:%[0-9]+]]:_(i32) = G_INTRINSIC intrinsic(@llvm.amdgcn.reloc.constant), <{{0x[0-9a-f]+}}>
+ ; CHECK-NEXT: [[INT1:%[0-9]+]]:_(i32) = G_INTRINSIC intrinsic(@llvm.amdgcn.reloc.constant), !1
; CHECK-NEXT: [[ADD:%[0-9]+]]:_(i32) = G_ADD [[INT]], [[INT1]]
; CHECK-NEXT: $vgpr0 = COPY [[ADD]](i32)
; CHECK-NEXT: SI_RETURN implicit $vgpr0
diff --git a/llvm/test/CodeGen/AMDGPU/dbg-value-ends-sched-region.mir b/llvm/test/CodeGen/AMDGPU/dbg-value-ends-sched-region.mir
index de68534fdfedc..2fc650842563d 100644
--- a/llvm/test/CodeGen/AMDGPU/dbg-value-ends-sched-region.mir
+++ b/llvm/test/CodeGen/AMDGPU/dbg-value-ends-sched-region.mir
@@ -90,7 +90,7 @@ body: |
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: dead [[COPY7:%[0-9]+]]:sreg_64 = COPY $exec
; CHECK-NEXT: dead [[GLOBAL_LOAD_DWORDX4_:%[0-9]+]]:vreg_128 = GLOBAL_LOAD_DWORDX4 [[COPY1]], 0, 0, implicit $exec :: (load (s128), addrspace 1)
- ; CHECK-NEXT: DBG_VALUE [[GLOBAL_LOAD_DWORDX4_]], $noreg, <0x{{[0-9a-f]+}}>, !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef), debug-location !DILocation(line: 0, scope: <0x{{[0-9a-f]+}}>)
+ ; CHECK-NEXT: DBG_VALUE [[GLOBAL_LOAD_DWORDX4_]], $noreg, !5, !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef), debug-location !DILocation(line: 0, scope: !6)
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.5:
; CHECK-NEXT: successors: %bb.3(0x40000000), %bb.1(0x40000000)
diff --git a/llvm/test/CodeGen/AMDGPU/sgpr-spill-fi-skip-processing-stack-arg-dbg-value-list.mir b/llvm/test/CodeGen/AMDGPU/sgpr-spill-fi-skip-processing-stack-arg-dbg-value-list.mir
index 2af4e95b17cad..04ae8f11f3143 100644
--- a/llvm/test/CodeGen/AMDGPU/sgpr-spill-fi-skip-processing-stack-arg-dbg-value-list.mir
+++ b/llvm/test/CodeGen/AMDGPU/sgpr-spill-fi-skip-processing-stack-arg-dbg-value-list.mir
@@ -40,8 +40,11 @@ machineFunctionInfo:
privateSegmentWaveByteOffset: { reg: '$sgpr9' }
body: |
; CHECK-LABEL: name: test
+ ; CHECK: machineMetadataNodes:
+ ; CHECK-DAG: '![[SP:[0-9]+]] = distinct !DISubprogram
+ ; CHECK-DAG: '![[VAR:[0-9]+]] = !DILocalVariable(name: "a", scope: ![[SP]],
; CHECK: bb.0:
- ; CHECK: DBG_VALUE_LIST <{{.*}}>, !DIExpression(), $noreg, 0, debug-location !DILocation(line: 10, column: 9, scope: <{{.*}}>)
+ ; CHECK: DBG_VALUE_LIST ![[VAR]], !DIExpression(), $noreg, 0, debug-location !DILocation(line: 10, column: 9, scope: ![[SP]])
bb.0:
renamable $sgpr10 = IMPLICIT_DEF
diff --git a/llvm/test/CodeGen/AMDGPU/vgpr-spill-fi-skip-processing-stack-arg-dbg-value-list.mir b/llvm/test/CodeGen/AMDGPU/vgpr-spill-fi-skip-processing-stack-arg-dbg-value-list.mir
index 4a77dd204fa38..9cb9c143b66d8 100644
--- a/llvm/test/CodeGen/AMDGPU/vgpr-spill-fi-skip-processing-stack-arg-dbg-value-list.mir
+++ b/llvm/test/CodeGen/AMDGPU/vgpr-spill-fi-skip-processing-stack-arg-dbg-value-list.mir
@@ -40,8 +40,11 @@ machineFunctionInfo:
privateSegmentWaveByteOffset: { reg: '$sgpr9' }
body: |
; CHECK-LABEL: name: test
+ ; CHECK: machineMetadataNodes:
+ ; CHECK-DAG: '![[SP:[0-9]+]] = distinct !DISubprogram
+ ; CHECK-DAG: '![[VAR:[0-9]+]] = !DILocalVariable(name: "a", scope: ![[SP]],
; CHECK: bb.0:
- ; CHECK: DBG_VALUE_LIST <{{.*}}>, !DIExpression(), $noreg, 0, debug-location !DILocation(line: 10, column: 9, scope: <{{.*}}>)
+ ; CHECK: DBG_VALUE_LIST ![[VAR]], !DIExpression(), $noreg, 0, debug-location !DILocation(line: 10, column: 9, scope: ![[SP]])
bb.0:
$vgpr2 = IMPLICIT_DEF
SI_SPILL_V32_SAVE $vgpr2, %stack.0, $sgpr32, 0, implicit $exec :: (store (s32) into %stack.0, align 4, addrspace 5)
diff --git a/llvm/test/CodeGen/MIR/Generic/machine-metadata-err0.mir b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err0.mir
index 0502ac90e51eb..9d5848b80e0c5 100644
--- a/llvm/test/CodeGen/MIR/Generic/machine-metadata-err0.mir
+++ b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err0.mir
@@ -12,4 +12,4 @@ name: t0
machineMetadataNodes:
- '9 = distinct !{!9, !7, !"Dst"}'
...
-# CHECK: [[@LINE-2]]:6: expected a metadata node
+# CHECK: [[@LINE-2]]:6: expected a metadata definition
diff --git a/llvm/test/CodeGen/MIR/Generic/machine-metadata-err1.mir b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err1.mir
index 4ac5202527d2f..dd77caccb0cf1 100644
--- a/llvm/test/CodeGen/MIR/Generic/machine-metadata-err1.mir
+++ b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err1.mir
@@ -12,4 +12,4 @@ name: t0
machineMetadataNodes:
- '! = distinct !{!9, !7, !"Dst"}'
...
-# CHECK: [[@LINE-2]]:8: expected metadata id after '!'
+# CHECK: [[@LINE-2]]:8: expected integer
diff --git a/llvm/test/CodeGen/MIR/Generic/machine-metadata-err10.mir b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err10.mir
new file mode 100644
index 0000000000000..bc2c536bf2c44
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err10.mir
@@ -0,0 +1,15 @@
+# RUN: not llc -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
+# This test ensures that each machine metadata list item contains exactly one
+# definition.
+
+--- |
+ define i32 @t0() {
+ ret i32 0
+ }
+...
+---
+name: t0
+machineMetadataNodes:
+ - '!9 = !{} !10 = !{}'
+...
+# CHECK: [[@LINE-2]]:{{[0-9]+}}: expected end of metadata definition
diff --git a/llvm/test/CodeGen/MIR/Generic/machine-metadata-err11.mir b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err11.mir
new file mode 100644
index 0000000000000..d02b88c5680b2
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err11.mir
@@ -0,0 +1,16 @@
+# RUN: not llc -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
+# This test ensures that comments cannot cross machine metadata list item
+# boundaries.
+
+--- |
+ define i32 @t0() {
+ ret i32 0
+ }
+...
+---
+name: t0
+machineMetadataNodes:
+ - '!9 = !{} /*'
+ - '*/ !10 = !{}'
+...
+# CHECK: [[@LINE-3]]:{{[0-9]+}}: expected end of metadata definition
diff --git a/llvm/test/CodeGen/MIR/Generic/machine-metadata-err12.mir b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err12.mir
new file mode 100644
index 0000000000000..4a708dc932c31
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err12.mir
@@ -0,0 +1,19 @@
+# RUN: not llc -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
+# This test ensures that diagnostics for multiline machine metadata definitions
+# point into the correct list item.
+
+--- |
+ define i32 @t0() {
+ ret i32 0
+ }
+...
+---
+name: t0
+machineMetadataNodes:
+ - |
+ !9 = !{
+ invalid
+ }
+ - '!10 = !{}'
+...
+# CHECK: [[@LINE-4]]:{{[0-9]+}}: expected metadata operand
diff --git a/llvm/test/CodeGen/MIR/Generic/machine-metadata-err2.mir b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err2.mir
index 0e731b12c6456..8bb00b0aa6333 100644
--- a/llvm/test/CodeGen/MIR/Generic/machine-metadata-err2.mir
+++ b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err2.mir
@@ -12,4 +12,4 @@ name: t0
machineMetadataNodes:
- '!9 = distinct {!9, !7, !"Dst"}'
...
-# CHECK: [[@LINE-2]]:20: expected a metadata node
+# CHECK: [[@LINE-2]]:20: Expected '!' here
diff --git a/llvm/test/CodeGen/MIR/Generic/machine-metadata-err6.mir b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err6.mir
index 51cca1b259cd0..21dce2f8c4d97 100644
--- a/llvm/test/CodeGen/MIR/Generic/machine-metadata-err6.mir
+++ b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err6.mir
@@ -12,4 +12,4 @@ name: t0
machineMetadataNodes:
- '!9 = distinct !{9, !7, !"Dst"}'
...
-# CHECK: [[@LINE-2]]:22: expected '!' here
+# CHECK: [[@LINE-2]]:22: expected metadata operand
diff --git a/llvm/test/CodeGen/MIR/Generic/machine-metadata-err7.mir b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err7.mir
index 0cc5ef1b8af83..eaf78448f1245 100644
--- a/llvm/test/CodeGen/MIR/Generic/machine-metadata-err7.mir
+++ b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err7.mir
@@ -12,4 +12,4 @@ name: t0
machineMetadataNodes:
- '!9 = distinct !{!, !7, !"Dst"}'
...
-# CHECK: [[@LINE-2]]:23: expected metadata id after '!'
+# CHECK: [[@LINE-2]]:23: expected integer
diff --git a/llvm/test/CodeGen/MIR/Generic/machine-metadata-err8.mir b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err8.mir
index 1d51dbc5d659d..ade425348782e 100644
--- a/llvm/test/CodeGen/MIR/Generic/machine-metadata-err8.mir
+++ b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err8.mir
@@ -12,4 +12,4 @@ name: t0
machineMetadataNodes:
- '!9 = distinct !{!9, !7, !"Dst"}'
...
-# CHECK: [[@LINE-2]]:26: use of undefined metadata '!7'
+# CHECK: [[@LINE-2]]:27: use of undefined metadata '!7'
diff --git a/llvm/test/CodeGen/MIR/Generic/machine-metadata-err9.mir b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err9.mir
new file mode 100644
index 0000000000000..3113309ef99e6
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/Generic/machine-metadata-err9.mir
@@ -0,0 +1,16 @@
+# RUN: not llc -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
+# This test ensures that the MIR parser detects errors when parsing machine
+# metadata.
+
+--- |
+ define i32 @t0() {
+ ret i32 0
+ }
+...
+---
+name: t0
+machineMetadataNodes:
+ - '!9 = distinct !{!9, !7,'
+ - '!"Dst"}'
+...
+# CHECK: [[@LINE-3]]:{{[0-9]+}}: expected end of metadata definition
diff --git a/llvm/test/CodeGen/MIR/X86/machine-metadata-round-trip.mir b/llvm/test/CodeGen/MIR/X86/machine-metadata-round-trip.mir
new file mode 100644
index 0000000000000..c1bcfd9794ece
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/X86/machine-metadata-round-trip.mir
@@ -0,0 +1,35 @@
+# RUN: llc -mtriple=x86_64 -run-pass=none -o - %s | FileCheck %s
+# RUN: llc -mtriple=x86_64 -run-pass=none -o - %s | llc -mtriple=x86_64 -x mir -run-pass=none -filetype=null
+
+--- |
+ define i8 @test(ptr %p) {
+ %value = load i8, ptr %p
+ ret i8 %value
+ }
+...
+---
+name: test
+machineMetadataNodes:
+ - '!0 = !{!"heap"}'
+ - '!1 = !{!"pcsections"}'
+ - '!2 = !{!"tag", !"value"}'
+ - '!3 = !{i32 1}'
+ - '!4 = !{i8 0, i8 10}'
+ - '!5 = !{i32 0, !6}'
+ - '!6 = !{!"cache", !"streaming"}'
+body: |
+ bb.0:
+ liveins: $rdi
+
+ ; CHECK: machineMetadataNodes:
+ ; CHECK-DAG: - '![[HEAP:[0-9]+]] = !{!"heap"}'
+ ; CHECK-DAG: - '![[PCSECTIONS:[0-9]+]] = !{!"pcsections"}'
+ ; CHECK-DAG: - '![[MMRA:[0-9]+]] = !{!"tag", !"value"}'
+ ; CHECK-DAG: - '![[NOALIAS:[0-9]+]] = !{i32 1}'
+ ; CHECK-DAG: - '![[RANGE:[0-9]+]] = !{i8 0, i8 10}'
+ ; CHECK-DAG: - '![[CACHE:[0-9]+]] = !{i32 0, ![[CACHE_HINT:[0-9]+]]}'
+ ; CHECK-DAG: - '![[CACHE_HINT]] = !{!"cache", !"streaming"}'
+ ; CHECK: renamable $al = MOV8rm killed renamable $rdi, 1, $noreg, 0, $noreg, heap-alloc-marker ![[HEAP]], pcsections ![[PCSECTIONS]], mmra ![[MMRA]] :: (load (s8) from %ir.p, !noalias.addrspace ![[NOALIAS]], !range ![[RANGE]], !mem.cache_hint ![[CACHE]])
+ renamable $al = MOV8rm killed renamable $rdi, 1, $noreg, 0, $noreg, heap-alloc-marker !0, pcsections !1, mmra !2 :: (load (s8) from %ir.p, !noalias.addrspace !3, !range !4, !mem.cache_hint !5)
+ RET64 implicit killed $al
+...
diff --git a/llvm/test/CodeGen/MIR/X86/machine-metadata-specialized.mir b/llvm/test/CodeGen/MIR/X86/machine-metadata-specialized.mir
new file mode 100644
index 0000000000000..6f475db767fcd
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/X86/machine-metadata-specialized.mir
@@ -0,0 +1,38 @@
+# RUN: llc -mtriple=x86_64 -run-pass=none -o - %s | FileCheck %s
+# RUN: llc -mtriple=x86_64 -run-pass=none -o - %s | llc -mtriple=x86_64 -x mir -run-pass=none -filetype=null
+
+--- |
+ define void @test() {
+ ret void
+ }
+...
+---
+name: test
+machineMetadataNodes:
+ - '!0 = !DILocation(line: 1, scope: !1)'
+ - '!1 = distinct !DISubprogram(name: "test", scope: !2, file: !2, line: 1, type: !3, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !7)'
+ - '!2 = !DIFile(filename: "test.c", directory: "/tmp")'
+ - '!3 = !DISubroutineType(types: !4)'
+ - '!4 = !{null}'
+ - '!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)'
+ - '!6 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)'
+ - '!7 = !{}'
+ - '!8 = !DILocalVariable(name: "x", scope: !1, file: !2, line: 1, type: !5)'
+ - '!9 = !DILocalVariable(name: "y", scope: !1, file: !2, line: 2, type: !5)'
+ - '!10 = !DILocation(line: 2, scope: !1)'
+entry_values:
+ - { entry-value-register: '$rax', debug-info-variable: '!9', debug-info-expression: '!DIExpression(DW_OP_LLVM_entry_value, 1)',
+ debug-info-location: '!10' }
+# CHECK: entry_values:
+# CHECK: - { entry-value-register: '$rax', debug-info-variable: '![[ENTRY_VAR:[0-9]+]]', debug-info-expression: '!DIExpression(DW_OP_LLVM_entry_value, 1)',
+# CHECK: debug-info-location: '!DILocation(line: 2, scope: ![[SP:[0-9]+]])' }
+body: |
+ bb.0:
+ ; CHECK: machineMetadataNodes:
+ ; CHECK-DAG: - '![[SP]] = distinct !DISubprogram(name: "test"
+ ; CHECK-DAG: - '![[VAR:[0-9]+]] = !DILocalVariable(name: "x", scope: ![[SP]]
+ ; CHECK-DAG: - '![[ENTRY_VAR]] = !DILocalVariable(name: "y", scope: ![[SP]]
+ ; CHECK: DBG_VALUE $rax, $noreg, ![[VAR]], !DIExpression(), debug-location !DILocation(line: 1, scope: ![[SP]])
+ DBG_VALUE $rax, $noreg, !8, !DIExpression(), debug-location !0
+ RET 0
+...
>From 287e376ad2ac50d52374efe1e6ff97be54fa38f8 Mon Sep 17 00:00:00 2001
From: "Yaxun (Sam) Liu" <yaxun.liu at amd.com>
Date: Fri, 28 Aug 2026 16:05:47 -0400
Subject: [PATCH 2/2] [IR] Use persistent metadata IDs for printing
---
clang/lib/CodeGen/BackendUtil.cpp | 7 +-
clang/tools/cir-translate/cir-translate.cpp | 1 +
.../clang-fuzzer/handle-llvm/handle_llvm.cpp | 5 +-
.../clang-import-test/clang-import-test.cpp | 4 +-
.../include/flang/Optimizer/CodeGen/CodeGen.h | 8 +-
flang/lib/Frontend/FrontendActions.cpp | 6 +-
.../llvm/CodeGen/MachineModuleSlotTracker.h | 25 +-
llvm/include/llvm/IR/IRPrintingPasses.h | 5 +
llvm/include/llvm/IR/Metadata.h | 10 +-
llvm/include/llvm/IR/Module.h | 5 +
llvm/include/llvm/IR/ModuleSlotTracker.h | 52 ++-
.../include/llvm/IRPrinter/IRPrintingPasses.h | 7 +-
llvm/lib/CodeGen/MIRParser/MIParser.cpp | 4 +-
llvm/lib/CodeGen/MIRPrintingPass.cpp | 16 +
llvm/lib/CodeGen/MachineBasicBlock.cpp | 2 +-
llvm/lib/CodeGen/MachineModuleSlotTracker.cpp | 109 +++--
llvm/lib/CodeGen/MachineOperand.cpp | 2 +-
llvm/lib/IR/AsmWriter.cpp | 417 ++++++++++--------
llvm/lib/IR/Core.cpp | 2 +
llvm/lib/IR/IRPrintingPasses.cpp | 71 +--
llvm/lib/IR/LLVMContextImpl.cpp | 9 +
llvm/lib/IR/LLVMContextImpl.h | 18 +
llvm/lib/IR/Metadata.cpp | 17 +
llvm/lib/IR/MetadataImpl.h | 2 +
llvm/lib/IR/SSAContext.cpp | 2 +-
llvm/lib/IRPrinter/IRPrintingPasses.cpp | 20 +-
llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp | 106 ++++-
.../DirectX/DebugInfo/di-globalvariable.ll | 7 +
llvm/test/CodeGen/Hexagon/swp-no-alias.mir | 8 +-
llvm/test/CodeGen/MIR/AMDGPU/instr-mmra.mir | 2 +-
.../CodeGen/MIR/AMDGPU/machine-metadata.mir | 12 +-
.../MIR/X86/instr-heap-alloc-operands.mir | 2 +-
.../test/CodeGen/MIR/X86/instr-pcsections.mir | 2 +-
.../MIR/X86/instructions-debug-location.mir | 14 +-
.../test/CodeGen/MIR/X86/machine-metadata.mir | 36 +-
llvm/test/CodeGen/MIR/X86/mem-cache-hint.mir | 4 +-
llvm/test/CodeGen/MIR/X86/memory-operands.mir | 10 +-
.../CodeGen/MIR/X86/metadata-operands.mir | 2 +-
llvm/test/CodeGen/MIR/X86/pr38773.mir | 4 +-
.../MIR/X86/stack-object-debug-info.mir | 4 +-
.../AArch64/no-dbg-value-after-terminator.mir | 2 +-
.../legacy-callgraph-scc-pass-printer.ll | 13 +-
.../print-changed-persistent-metadata-ids.ll | 77 ++++
.../Other/print-persistent-metadata-ids.ll | 94 ++++
.../Inputs/loop-distribute.ll.expected | 6 +-
.../IR/01-ir-print-basic-details.test | 22 +-
.../IR/01-ir-select-logical-elements.test | 16 +-
.../IR/02-ir-logical-lines.test | 4 +-
.../IR/06-ir-full-logical-view.test | 22 +-
llvm/tools/llvm-dis/llvm-dis.cpp | 1 +
llvm/tools/llvm-extract/llvm-extract.cpp | 6 +-
llvm/tools/llvm-link/llvm-link.cpp | 1 +
llvm/tools/llvm-reduce/ReducerWorkItem.cpp | 9 +-
llvm/tools/llvm-split/llvm-split.cpp | 7 +-
llvm/tools/llvm-stress/llvm-stress.cpp | 1 +
llvm/tools/opt/NewPMDriver.cpp | 3 +-
llvm/tools/opt/optdriver.cpp | 7 +-
.../verify-uselistorder.cpp | 9 +-
llvm/unittests/AsmParser/AsmParserTest.cpp | 33 ++
llvm/unittests/IR/AsmWriterTest.cpp | 124 ++++++
llvm/unittests/IR/MetadataTest.cpp | 18 +-
llvm/unittests/IR/ModuleTest.cpp | 55 +++
llvm/unittests/MIR/MachineMetadata.cpp | 118 +++--
mlir/lib/Target/LLVMIR/ConvertToLLVMIR.cpp | 1 +
.../Target/LLVMIR/Import/import-failure.ll | 24 +-
polly/test/ForwardOpTree/atax.ll | 16 +-
polly/test/ForwardOpTree/jacobi-1d.ll | 8 +-
...eserve-equiv-class-order-in-basic_block.ll | 4 +-
.../stmt_split_exit_of_region_stmt.ll | 2 +-
.../ScopInfo/stmt_split_no_after_split.ll | 2 +-
.../test/ScopInfo/stmt_split_no_dependence.ll | 2 +-
.../stmt_split_phi_in_beginning_bb.ll | 2 +-
polly/test/ScopInfo/stmt_split_phi_in_stmt.ll | 2 +-
.../ScopInfo/stmt_split_scalar_dependence.ll | 2 +-
polly/test/ScopInfo/stmt_split_within_loop.ll | 2 +-
75 files changed, 1242 insertions(+), 512 deletions(-)
create mode 100644 llvm/test/Other/print-changed-persistent-metadata-ids.ll
create mode 100644 llvm/test/Other/print-persistent-metadata-ids.ll
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 6aa6bc1bd41e8..086f886be4390 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1166,7 +1166,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
*OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr));
} else if (Action == Backend_EmitLL) {
MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists,
- /*EmitLTOSummary=*/true));
+ /*EmitLTOSummary=*/true,
+ /*ShouldRenumberMetadata=*/true));
}
} else {
// Emit a module summary by default for Regular LTO except for ld64
@@ -1184,7 +1185,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
EmitLTOSummary));
} else if (Action == Backend_EmitLL) {
MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists,
- EmitLTOSummary));
+ EmitLTOSummary,
+ /*ShouldRenumberMetadata=*/true));
}
}
@@ -1456,6 +1458,7 @@ runThinLTOBackend(CompilerInstance &CI, ModuleSummaryIndex *CombinedIndex,
break;
case Backend_EmitLL:
Conf.PreCodeGenModuleHook = [&](size_t Task, const llvm::Module &Mod) {
+ M->renumberMetadataForAssembly();
M->print(*OS, nullptr, CGOpts.EmitLLVMUseLists);
return false;
};
diff --git a/clang/tools/cir-translate/cir-translate.cpp b/clang/tools/cir-translate/cir-translate.cpp
index 4452741d7433e..a58512e3fca22 100644
--- a/clang/tools/cir-translate/cir-translate.cpp
+++ b/clang/tools/cir-translate/cir-translate.cpp
@@ -165,6 +165,7 @@ void registerToLLVMTranslation() {
enableOpenMP);
if (!llvmModule)
return mlir::failure();
+ llvmModule->renumberMetadataForAssembly();
llvmModule->print(output, nullptr);
return mlir::success();
},
diff --git a/clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp b/clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
index 942e35c30e19f..1c745bffe00c0 100644
--- a/clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
+++ b/clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
@@ -103,7 +103,10 @@ static void RunOptimizationPasses(raw_ostream &OS, Module &M,
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
ModulePassManager MPM = PB.buildPerModuleDefaultPipeline(OL);
- MPM.addPass(PrintModulePass(OS));
+ MPM.addPass(PrintModulePass(OS, /*Banner=*/"",
+ /*ShouldPreserveUseListOrder=*/false,
+ /*EmitSummaryIndex=*/false,
+ /*ShouldRenumberMetadata=*/true));
MPM.run(M, MAM);
}
diff --git a/clang/tools/clang-import-test/clang-import-test.cpp b/clang/tools/clang-import-test/clang-import-test.cpp
index 8e83687d3e96a..bcb5d2bdb8952 100644
--- a/clang/tools/clang-import-test/clang-import-test.cpp
+++ b/clang/tools/clang-import-test/clang-import-test.cpp
@@ -338,8 +338,10 @@ llvm::Expected<CIAndOrigins> Parse(const std::string &Path,
if (llvm::Error PE = ParseSource(Path, CI.getCompilerInstance(), Consumers))
return std::move(PE);
CI.getDiagnosticClient().EndSourceFile();
- if (ShouldDumpIR)
+ if (ShouldDumpIR) {
+ CG.GetModule()->renumberMetadataForAssembly();
CG.GetModule()->print(llvm::outs(), nullptr);
+ }
if (CI.getDiagnosticClient().getNumErrors())
return llvm::make_error<llvm::StringError>(
"Errors occurred while parsing the expression.", std::error_code());
diff --git a/flang/include/flang/Optimizer/CodeGen/CodeGen.h b/flang/include/flang/Optimizer/CodeGen/CodeGen.h
index 1d36788fb84f9..6ef575f5391d9 100644
--- a/flang/include/flang/Optimizer/CodeGen/CodeGen.h
+++ b/flang/include/flang/Optimizer/CodeGen/CodeGen.h
@@ -90,9 +90,11 @@ using LLVMIRLoweringPrinter =
/// Convert the LLVM IR dialect to LLVM-IR proper
std::unique_ptr<mlir::Pass> createLLVMDialectToLLVMPass(
- llvm::raw_ostream &output,
- LLVMIRLoweringPrinter printer =
- [](llvm::Module &m, llvm::raw_ostream &out) { m.print(out, nullptr); });
+ llvm::raw_ostream &output, LLVMIRLoweringPrinter printer =
+ [](llvm::Module &m, llvm::raw_ostream &out) {
+ m.renumberMetadataForAssembly();
+ m.print(out, nullptr);
+ });
/// Populate the given list with patterns that convert from FIR to LLVM.
void populateFIRToLLVMConversionPatterns(
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 8a2d1a6c2e2a2..a5b15cc3e334f 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -1092,9 +1092,9 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
os, /*ShouldPreserveUseListOrder=*/false, emitSummary));
}
} else if (action == BackendActionTy::Backend_EmitLL) {
- mpm.addPass(llvm::PrintModulePass(os, /*Banner=*/"",
- /*ShouldPreserveUseListOrder=*/false,
- emitSummary));
+ mpm.addPass(llvm::PrintModulePass(
+ os, /*Banner=*/"", /*ShouldPreserveUseListOrder=*/false, emitSummary,
+ /*ShouldRenumberMetadata=*/true));
}
}
diff --git a/llvm/include/llvm/CodeGen/MachineModuleSlotTracker.h b/llvm/include/llvm/CodeGen/MachineModuleSlotTracker.h
index 666b3caf67e27..1cb15f9cc172d 100644
--- a/llvm/include/llvm/CodeGen/MachineModuleSlotTracker.h
+++ b/llvm/include/llvm/CodeGen/MachineModuleSlotTracker.h
@@ -10,12 +10,13 @@
#define LLVM_CODEGEN_MACHINEMODULESLOTTRACKER_H
#include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/ModuleSlotTracker.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
-class AbstractSlotTrackerStorage;
class Function;
class MachineModuleInfo;
class MachineFunction;
@@ -24,24 +25,24 @@ class Module;
using MFGetterFnT = function_ref<MachineFunction *(const Function &)>;
class LLVM_ABI MachineModuleSlotTracker : public ModuleSlotTracker {
- const Function &TheFunction;
const MachineFunction *TheMF;
- unsigned MDNStartSlot = 0, MDNEndSlot = 0;
+ MachineMDNodeListType MachineMDNodes;
+ SmallPtrSet<const DILocation *, 4> InlineDebugLocations;
- void processMachineFunctionMetadata(AbstractSlotTrackerStorage *AST,
- const MachineFunction &MF);
- void processMachineModule(AbstractSlotTrackerStorage *AST, const Module *M,
- bool ShouldInitializeAllMetadata);
- void processMachineFunction(AbstractSlotTrackerStorage *AST,
- const Function *F,
- bool ShouldInitializeAllMetadata);
+ void collectMachineFunctionMetadata(
+ SmallVectorImpl<const MDNode *> &Metadata, const MachineFunction &MF,
+ SmallVectorImpl<const MDNode *> *DebugLocations = nullptr) const;
public:
- MachineModuleSlotTracker(MFGetterFnT Fn, const MachineFunction *MF,
- bool ShouldInitializeAllMetadata = true);
+ MachineModuleSlotTracker(MFGetterFnT Fn, const MachineFunction *MF);
~MachineModuleSlotTracker() override;
+ /// Renumber module and machine metadata for canonical MIR output.
+ void renumberMetadataForAssembly();
void collectMachineMDNodes(MachineMDNodeListType &L) const;
+ bool shouldPrintDebugLocationInline(const DILocation *DL) const override {
+ return InlineDebugLocations.contains(DL);
+ }
};
} // namespace llvm
diff --git a/llvm/include/llvm/IR/IRPrintingPasses.h b/llvm/include/llvm/IR/IRPrintingPasses.h
index 1b2d38d6190e9..0eb60f55f74c3 100644
--- a/llvm/include/llvm/IR/IRPrintingPasses.h
+++ b/llvm/include/llvm/IR/IRPrintingPasses.h
@@ -31,6 +31,11 @@ LLVM_ABI ModulePass *
createPrintModulePass(raw_ostream &OS, const std::string &Banner = "",
bool ShouldPreserveUseListOrder = false);
+LLVM_ABI ModulePass *createPrintModulePass(raw_ostream &OS,
+ const std::string &Banner,
+ bool ShouldPreserveUseListOrder,
+ bool ShouldRenumberMetadata);
+
/// Create and return a pass that prints functions to the specified
/// \c raw_ostream as they are processed.
LLVM_ABI FunctionPass *createPrintFunctionPass(raw_ostream &OS,
diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h
index 5b458fa14f0b1..a53cb63ed59cf 100644
--- a/llvm/include/llvm/IR/Metadata.h
+++ b/llvm/include/llvm/IR/Metadata.h
@@ -1079,11 +1079,11 @@ class MDNode : public Metadata {
/// Explicity set alignment because bitfields by default have an
/// alignment of 1 on z/OS.
struct alignas(alignof(size_t)) Header {
- size_t IsResizable : 1;
- size_t IsLarge : 1;
- size_t SmallSize : 4;
- size_t SmallNumOps : 4;
- size_t : sizeof(size_t) * CHAR_BIT - 10;
+ uint32_t IsResizable : 1;
+ uint32_t IsLarge : 1;
+ uint32_t SmallSize : 4;
+ uint32_t SmallNumOps : 4;
+ uint32_t MetadataPrintID;
unsigned NumUnresolved = 0;
using LargeStorageVector = SmallVector<MDOperand, 0>;
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index 6090644f7a12f..1b22ac79f2d51 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -987,6 +987,11 @@ class LLVM_ABI Module {
bool ShouldPreserveUseListOrder = false,
bool IsForDebug = false) const;
+ /// Renumber the IDs stored in metadata nodes into canonical assembly order.
+ /// This mutates the IDs and should only be used immediately before final
+ /// assembly output.
+ void renumberMetadataForAssembly();
+
/// Dump the module to stderr (for debugging).
void dump() const;
diff --git a/llvm/include/llvm/IR/ModuleSlotTracker.h b/llvm/include/llvm/IR/ModuleSlotTracker.h
index a3882a81e1177..b92bd16084b06 100644
--- a/llvm/include/llvm/IR/ModuleSlotTracker.h
+++ b/llvm/include/llvm/IR/ModuleSlotTracker.h
@@ -9,11 +9,12 @@
#ifndef LLVM_IR_MODULESLOTTRACKER_H
#define LLVM_IR_MODULESLOTTRACKER_H
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
#include <functional>
#include <memory>
#include <utility>
-#include <vector>
namespace llvm {
@@ -21,6 +22,7 @@ class Module;
class Function;
class SlotTracker;
class Value;
+class DILocation;
class MDNode;
/// Abstract interface of slot tracker storage.
@@ -28,8 +30,6 @@ class LLVM_ABI AbstractSlotTrackerStorage {
public:
virtual ~AbstractSlotTrackerStorage();
- virtual unsigned getNextMetadataSlot() = 0;
-
virtual void createMetadataSlot(const MDNode *) = 0;
virtual int getMetadataSlot(const MDNode *) = 0;
};
@@ -43,20 +43,37 @@ class LLVM_ABI AbstractSlotTrackerStorage {
/// If the IR changes from underneath \a ModuleSlotTracker, strings like
/// "<badref>" will be printed, or, worse, the wrong slots entirely.
class LLVM_ABI ModuleSlotTracker {
+public:
+ using MachineMDNodeListType =
+ SmallVector<std::pair<unsigned, const MDNode *>, 0>;
+
+private:
/// Storage for a slot tracker.
std::unique_ptr<SlotTracker> MachineStorage;
bool ShouldCreateStorage = false;
- bool ShouldInitializeAllMetadata = false;
const Module *M = nullptr;
const Function *F = nullptr;
SlotTracker *Machine = nullptr;
- std::function<void(AbstractSlotTrackerStorage *, const Module *, bool)>
+ std::function<void(AbstractSlotTrackerStorage *, const Module *)>
ProcessModuleHookFn;
- std::function<void(AbstractSlotTrackerStorage *, const Function *, bool)>
+ std::function<void(AbstractSlotTrackerStorage *, const Function *)>
ProcessFunctionHookFn;
+protected:
+ /// Renumber module metadata and then additional metadata for canonical
+ /// assembly output.
+ void renumberMetadataForAssembly(
+ ArrayRef<const MDNode *> AdditionalMetadata,
+ MachineMDNodeListType *AdditionalMetadataNodes = nullptr) const;
+
+ /// Collect metadata reachable from \p AdditionalMetadata but not from the
+ /// module.
+ void collectAdditionalMetadata(
+ ArrayRef<const MDNode *> AdditionalMetadata,
+ MachineMDNodeListType &AdditionalMetadataNodes) const;
+
public:
/// Wrap a preinitialized SlotTracker.
ModuleSlotTracker(SlotTracker &Machine, const Module *M,
@@ -64,13 +81,8 @@ class LLVM_ABI ModuleSlotTracker {
/// Construct a slot tracker from a module.
///
- /// If \a M is \c nullptr, uses a null slot tracker. Otherwise, initializes
- /// a slot tracker, and initializes all metadata slots. \c
- /// ShouldInitializeAllMetadata defaults to true because this is expected to
- /// be shared between multiple callers, and otherwise MDNode references will
- /// not match up.
- explicit ModuleSlotTracker(const Module *M,
- bool ShouldInitializeAllMetadata = true);
+ /// If \a M is \c nullptr, uses a null slot tracker.
+ explicit ModuleSlotTracker(const Module *M);
/// Destructor to clean up storage.
virtual ~ModuleSlotTracker();
@@ -95,14 +107,16 @@ class LLVM_ABI ModuleSlotTracker {
int getLocalSlot(const Value *V);
void setProcessHook(
- std::function<void(AbstractSlotTrackerStorage *, const Module *, bool)>);
- void setProcessHook(std::function<void(AbstractSlotTrackerStorage *,
- const Function *, bool)>);
+ std::function<void(AbstractSlotTrackerStorage *, const Module *)>);
+ void setProcessHook(
+ std::function<void(AbstractSlotTrackerStorage *, const Function *)>);
- using MachineMDNodeListType =
- std::vector<std::pair<unsigned, const MDNode *>>;
+ void collectMDNodes(MachineMDNodeListType &L) const;
- void collectMDNodes(MachineMDNodeListType &L, unsigned LB, unsigned UB) const;
+ /// Return whether a debug location should be printed inline instead of by ID.
+ virtual bool shouldPrintDebugLocationInline(const DILocation *) const {
+ return false;
+ }
};
} // end namespace llvm
diff --git a/llvm/include/llvm/IRPrinter/IRPrintingPasses.h b/llvm/include/llvm/IRPrinter/IRPrintingPasses.h
index e574d94ca2f22..56fdd94187dd3 100644
--- a/llvm/include/llvm/IRPrinter/IRPrintingPasses.h
+++ b/llvm/include/llvm/IRPrinter/IRPrintingPasses.h
@@ -35,13 +35,16 @@ class PrintModulePass : public RequiredPassInfoMixin<PrintModulePass> {
std::string Banner;
bool ShouldPreserveUseListOrder;
bool EmitSummaryIndex;
+ bool ShouldRenumberMetadata;
public:
LLVM_ABI PrintModulePass();
+ /// If \p ShouldRenumberMetadata, renumber metadata for canonical assembly
+ /// output before printing.
LLVM_ABI PrintModulePass(raw_ostream &OS, const std::string &Banner = "",
bool ShouldPreserveUseListOrder = false,
- bool EmitSummaryIndex = false);
-
+ bool EmitSummaryIndex = false,
+ bool ShouldRenumberMetadata = false);
LLVM_ABI PreservedAnalyses run(Module &M, AnalysisManager<Module> &);
};
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index a9caf95a32ef9..ef4927e2c4ee3 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -360,7 +360,7 @@ static void mapValueToSlot(const Value *V, ModuleSlotTracker &MST,
/// Creates the mapping from slot numbers to function's unnamed IR values.
static void initSlots2Values(const Function &F,
DenseMap<unsigned, const Value *> &Slots2Values) {
- ModuleSlotTracker MST(F.getParent(), /*ShouldInitializeAllMetadata=*/false);
+ ModuleSlotTracker MST(F.getParent());
MST.incorporateFunction(F);
for (const auto &Arg : F.args())
mapValueToSlot(&Arg, MST, Slots2Values);
@@ -3813,7 +3813,7 @@ bool MIParser::parseMMRA(MDNode *&Node) {
static void initSlots2BasicBlocks(
const Function &F,
DenseMap<unsigned, const BasicBlock *> &Slots2BasicBlocks) {
- ModuleSlotTracker MST(F.getParent(), /*ShouldInitializeAllMetadata=*/false);
+ ModuleSlotTracker MST(F.getParent());
MST.incorporateFunction(F);
for (const auto &BB : F) {
if (BB.hasName())
diff --git a/llvm/lib/CodeGen/MIRPrintingPass.cpp b/llvm/lib/CodeGen/MIRPrintingPass.cpp
index f5e455a520151..5f6537cdd8c13 100644
--- a/llvm/lib/CodeGen/MIRPrintingPass.cpp
+++ b/llvm/lib/CodeGen/MIRPrintingPass.cpp
@@ -12,16 +12,20 @@
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/MIRPrinter.h"
+#include "llvm/CodeGen/MachineFunctionAnalysis.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineModuleSlotTracker.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/VirtRegMap.h"
#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
#include "llvm/InitializePasses.h"
using namespace llvm;
PreservedAnalyses PrintMIRPreparePass::run(Module &M, ModuleAnalysisManager &) {
+ M.renumberMetadataForAssembly();
printMIR(OS, M);
return PreservedAnalyses::all();
}
@@ -32,6 +36,14 @@ PreservedAnalyses PrintMIRPass::run(MachineFunction &MF,
.getManager();
const VirtRegMap *VRM = MFAM.getCachedResult<VirtRegMapAnalysis>(MF);
+ MachineModuleSlotTracker MST(
+ [&](const Function &F) {
+ return &FAM.getResult<MachineFunctionAnalysis>(
+ const_cast<Function &>(F))
+ .getMF();
+ },
+ &MF);
+ MST.renumberMetadataForAssembly();
printMIR(OS, FAM, MF, VRM);
return PreservedAnalyses::all();
}
@@ -67,12 +79,16 @@ struct MIRPrintingPass : public MachineFunctionPass {
if (auto *W = getAnalysisIfAvailable<VirtRegMapWrapperLegacy>())
VRM = &W->getVRM();
+ MachineModuleSlotTracker MST(
+ [&](const Function &F) { return MMI->getMachineFunction(F); }, &MF);
+ MST.renumberMetadataForAssembly();
printMIR(StrOS, *MMI, MF, VRM);
MachineFunctions.append(Str);
return false;
}
bool doFinalization(Module &M) override {
+ M.renumberMetadataForAssembly();
printMIR(OS, M);
OS << MachineFunctions;
return false;
diff --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp
index 08a67935b52f5..b58a11efd103c 100644
--- a/llvm/lib/CodeGen/MachineBasicBlock.cpp
+++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp
@@ -503,7 +503,7 @@ void MachineBasicBlock::printName(raw_ostream &os, unsigned printNameFlags,
if (moduleSlotTracker) {
slot = moduleSlotTracker->getLocalSlot(bb);
} else if (bb->getParent()) {
- ModuleSlotTracker tmpTracker(bb->getModule(), false);
+ ModuleSlotTracker tmpTracker(bb->getModule());
tmpTracker.incorporateFunction(*bb->getParent());
slot = tmpTracker.getLocalSlot(bb);
}
diff --git a/llvm/lib/CodeGen/MachineModuleSlotTracker.cpp b/llvm/lib/CodeGen/MachineModuleSlotTracker.cpp
index e08b03eb4d70c..fbe16cebee868 100644
--- a/llvm/lib/CodeGen/MachineModuleSlotTracker.cpp
+++ b/llvm/lib/CodeGen/MachineModuleSlotTracker.cpp
@@ -16,92 +16,91 @@
using namespace llvm;
-void MachineModuleSlotTracker::processMachineFunctionMetadata(
- AbstractSlotTrackerStorage *AST, const MachineFunction &MF) {
- // Create metadata created within the backend.
+void MachineModuleSlotTracker::collectMachineFunctionMetadata(
+ SmallVectorImpl<const MDNode *> &Metadata, const MachineFunction &MF,
+ SmallVectorImpl<const MDNode *> *DebugLocations) const {
for (const MachineBasicBlock &MBB : MF)
for (const MachineInstr &MI : MBB.instrs()) {
+ if (DebugLocations)
+ if (DebugLoc DL = MI.getDebugLoc())
+ DebugLocations->push_back(DL.getAsMDNode());
+
if (MDNode *N = MI.getHeapAllocMarker())
- AST->createMetadataSlot(N);
+ Metadata.push_back(N);
if (MDNode *N = MI.getPCSections())
- AST->createMetadataSlot(N);
+ Metadata.push_back(N);
if (MDNode *N = MI.getMMRAMetadata())
- AST->createMetadataSlot(N);
+ Metadata.push_back(N);
for (const MachineOperand &MO : MI.operands())
if (MO.isMetadata())
- AST->createMetadataSlot(MO.getMetadata());
+ Metadata.push_back(MO.getMetadata());
for (const MachineMemOperand *MMO : MI.memoperands()) {
AAMDNodes AAInfo = MMO->getAAInfo();
if (AAInfo.TBAA)
- AST->createMetadataSlot(AAInfo.TBAA);
+ Metadata.push_back(AAInfo.TBAA);
if (AAInfo.TBAAStruct)
- AST->createMetadataSlot(AAInfo.TBAAStruct);
+ Metadata.push_back(AAInfo.TBAAStruct);
if (AAInfo.Scope)
- AST->createMetadataSlot(AAInfo.Scope);
+ Metadata.push_back(AAInfo.Scope);
if (AAInfo.NoAlias)
- AST->createMetadataSlot(AAInfo.NoAlias);
+ Metadata.push_back(AAInfo.NoAlias);
if (AAInfo.NoAliasAddrSpace)
- AST->createMetadataSlot(AAInfo.NoAliasAddrSpace);
+ Metadata.push_back(AAInfo.NoAliasAddrSpace);
if (const MDNode *N = MMO->getRanges())
- AST->createMetadataSlot(N);
+ Metadata.push_back(N);
if (const MDNode *N = MMO->getMemCacheHint())
- AST->createMetadataSlot(N);
+ Metadata.push_back(N);
}
}
for (const MachineFunction::VariableDbgInfo &DebugVar :
MF.getVariableDbgInfo()) {
- AST->createMetadataSlot(DebugVar.Var);
+ Metadata.push_back(DebugVar.Var);
}
}
-void MachineModuleSlotTracker::processMachineModule(
- AbstractSlotTrackerStorage *AST, const Module *M,
- bool ShouldInitializeAllMetadata) {
- if (ShouldInitializeAllMetadata) {
- for (const Function &F : *M) {
- if (&F != &TheFunction)
- continue;
- MDNStartSlot = AST->getNextMetadataSlot();
- if (TheMF)
- processMachineFunctionMetadata(AST, *TheMF);
- MDNEndSlot = AST->getNextMetadataSlot();
- break;
- }
- }
+void MachineModuleSlotTracker::collectMachineMDNodes(
+ MachineMDNodeListType &L) const {
+ L.insert(L.end(), MachineMDNodes.begin(), MachineMDNodes.end());
}
-void MachineModuleSlotTracker::processMachineFunction(
- AbstractSlotTrackerStorage *AST, const Function *F,
- bool ShouldInitializeAllMetadata) {
- if (!ShouldInitializeAllMetadata && F == &TheFunction) {
- MDNStartSlot = AST->getNextMetadataSlot();
- if (TheMF)
- processMachineFunctionMetadata(AST, *TheMF);
- MDNEndSlot = AST->getNextMetadataSlot();
- }
-}
+void MachineModuleSlotTracker::renumberMetadataForAssembly() {
+ if (!TheMF)
+ return;
-void MachineModuleSlotTracker::collectMachineMDNodes(
- MachineMDNodeListType &L) const {
- collectMDNodes(L, MDNStartSlot, MDNEndSlot);
+ SmallVector<const MDNode *, 16> Metadata;
+ collectMachineFunctionMetadata(Metadata, *TheMF);
+ MachineMDNodes.clear();
+ ModuleSlotTracker::renumberMetadataForAssembly(Metadata, &MachineMDNodes);
}
-MachineModuleSlotTracker::MachineModuleSlotTracker(
- MFGetterFnT Fn, const MachineFunction *MF, bool ShouldInitializeAllMetadata)
- : ModuleSlotTracker(MF->getFunction().getParent(),
- ShouldInitializeAllMetadata),
- TheFunction(MF->getFunction()), TheMF(Fn(MF->getFunction())) {
- setProcessHook([this](AbstractSlotTrackerStorage *AST, const Module *M,
- bool ShouldInitializeAllMetadata) {
- this->processMachineModule(AST, M, ShouldInitializeAllMetadata);
- });
- setProcessHook([this](AbstractSlotTrackerStorage *AST, const Function *F,
- bool ShouldInitializeAllMetadata) {
- this->processMachineFunction(AST, F, ShouldInitializeAllMetadata);
- });
+MachineModuleSlotTracker::MachineModuleSlotTracker(MFGetterFnT Fn,
+ const MachineFunction *MF)
+ : ModuleSlotTracker(MF->getFunction().getParent()),
+ TheMF(Fn(MF->getFunction())) {
+ if (!TheMF)
+ return;
+
+ SmallVector<const MDNode *, 16> Metadata;
+ SmallVector<const MDNode *, 16> DebugLocations;
+ collectMachineFunctionMetadata(Metadata, *TheMF, &DebugLocations);
+ collectAdditionalMetadata(Metadata, MachineMDNodes);
+
+ if (DebugLocations.empty())
+ return;
+
+ MachineMDNodeListType DebugMetadataNodes;
+ collectAdditionalMetadata(DebugLocations, DebugMetadataNodes);
+ SmallPtrSet<const MDNode *, 16> MachineMetadata;
+ for (const auto &Entry : MachineMDNodes)
+ MachineMetadata.insert(Entry.second);
+
+ for (const auto &Entry : DebugMetadataNodes)
+ if (isa<DILocation>(Entry.second) &&
+ !MachineMetadata.contains(Entry.second))
+ InlineDebugLocations.insert(cast<DILocation>(Entry.second));
}
MachineModuleSlotTracker::~MachineModuleSlotTracker() = default;
diff --git a/llvm/lib/CodeGen/MachineOperand.cpp b/llvm/lib/CodeGen/MachineOperand.cpp
index 3067f6e636130..af1487038de59 100644
--- a/llvm/lib/CodeGen/MachineOperand.cpp
+++ b/llvm/lib/CodeGen/MachineOperand.cpp
@@ -529,7 +529,7 @@ static void printIRBlockReference(raw_ostream &OS, const BasicBlock &BB,
if (F == MST.getCurrentFunction()) {
Slot = MST.getLocalSlot(&BB);
} else if (const Module *M = F->getParent()) {
- ModuleSlotTracker CustomMST(M, /*ShouldInitializeAllMetadata=*/false);
+ ModuleSlotTracker CustomMST(M);
CustomMST.incorporateFunction(*F);
Slot = CustomMST.getLocalSlot(&BB);
}
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 77b302c24fe31..dcb183b37c301 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -15,11 +15,13 @@
//
//===----------------------------------------------------------------------===//
+#include "LLVMContextImpl.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
@@ -799,11 +801,11 @@ class llvm::SlotTracker : public AbstractSlotTrackerStorage {
/// TheFunction - The function for which we are holding slot numbers.
const Function* TheFunction = nullptr;
bool FunctionProcessed = false;
- bool ShouldInitializeAllMetadata;
+ bool ShouldTrackMetadataDefinitions;
- std::function<void(AbstractSlotTrackerStorage *, const Module *, bool)>
+ std::function<void(AbstractSlotTrackerStorage *, const Module *)>
ProcessModuleHookFn;
- std::function<void(AbstractSlotTrackerStorage *, const Function *, bool)>
+ std::function<void(AbstractSlotTrackerStorage *, const Function *)>
ProcessFunctionHookFn;
/// The summary index for which we are holding slot numbers.
@@ -818,9 +820,7 @@ class llvm::SlotTracker : public AbstractSlotTrackerStorage {
unsigned fNext = 0;
/// mdnMap - Map for MDNodes.
- DenseMap<const MDNode*, unsigned> mdnMap;
- unsigned mdnNext = 0;
-
+ DenseMap<const MDNode *, unsigned> mdnMap;
/// asMap - The slot map for attribute sets.
DenseMap<AttributeSet, unsigned> asMap;
unsigned asNext = 0;
@@ -845,19 +845,12 @@ class llvm::SlotTracker : public AbstractSlotTrackerStorage {
public:
/// Construct from a module.
///
- /// If \c ShouldInitializeAllMetadata, initializes all metadata in all
- /// functions, giving correct numbering for metadata referenced only from
- /// within a function (even if no functions have been initialized).
explicit SlotTracker(const Module *M,
- bool ShouldInitializeAllMetadata = false);
+ bool ShouldTrackMetadataDefinitions = false);
/// Construct from a function, starting out in incorp state.
///
- /// If \c ShouldInitializeAllMetadata, initializes all metadata in all
- /// functions, giving correct numbering for metadata referenced only from
- /// within a function (even if no functions have been initialized).
- explicit SlotTracker(const Function *F,
- bool ShouldInitializeAllMetadata = false);
+ explicit SlotTracker(const Function *F);
/// Construct from a module summary index.
explicit SlotTracker(const ModuleSummaryIndex *Index);
@@ -868,11 +861,9 @@ class llvm::SlotTracker : public AbstractSlotTrackerStorage {
~SlotTracker() override = default;
void setProcessHook(
- std::function<void(AbstractSlotTrackerStorage *, const Module *, bool)>);
- void setProcessHook(std::function<void(AbstractSlotTrackerStorage *,
- const Function *, bool)>);
-
- unsigned getNextMetadataSlot() override { return mdnNext; }
+ std::function<void(AbstractSlotTrackerStorage *, const Module *)>);
+ void setProcessHook(
+ std::function<void(AbstractSlotTrackerStorage *, const Function *)>);
void createMetadataSlot(const MDNode *N) override;
@@ -929,7 +920,7 @@ class llvm::SlotTracker : public AbstractSlotTrackerStorage {
/// CreateModuleSlot - Insert the specified GlobalValue* into the slot table.
void CreateModuleSlot(const GlobalValue *V);
- /// CreateMetadataSlot - Insert the specified MDNode* into the slot table.
+ /// Record a metadata definition and the metadata nodes referenced by it.
void CreateMetadataSlot(const MDNode *N);
/// CreateFunctionSlot - Insert the specified Value* into the slot table.
@@ -951,28 +942,14 @@ class llvm::SlotTracker : public AbstractSlotTrackerStorage {
/// Add all of the functions arguments, basic blocks, and instructions.
void processFunction();
-
- /// Add the metadata directly attached to a GlobalObject.
- void processGlobalObjectMetadata(const GlobalObject &GO);
-
- /// Add all of the metadata from a function.
- void processFunctionMetadata(const Function &F);
-
- /// Add all of the metadata from an instruction.
- void processInstructionMetadata(const Instruction &I);
-
- /// Add all of the metadata from a DbgRecord.
- void processDbgRecordMetadata(const DbgRecord &DVR);
};
ModuleSlotTracker::ModuleSlotTracker(SlotTracker &Machine, const Module *M,
const Function *F)
: M(M), F(F), Machine(&Machine) {}
-ModuleSlotTracker::ModuleSlotTracker(const Module *M,
- bool ShouldInitializeAllMetadata)
- : ShouldCreateStorage(M),
- ShouldInitializeAllMetadata(ShouldInitializeAllMetadata), M(M) {}
+ModuleSlotTracker::ModuleSlotTracker(const Module *M)
+ : ShouldCreateStorage(M), M(M) {}
ModuleSlotTracker::~ModuleSlotTracker() = default;
@@ -981,8 +958,7 @@ SlotTracker *ModuleSlotTracker::getMachine() {
return Machine;
ShouldCreateStorage = false;
- MachineStorage =
- std::make_unique<SlotTracker>(M, ShouldInitializeAllMetadata);
+ MachineStorage = std::make_unique<SlotTracker>(M);
Machine = MachineStorage.get();
if (ProcessModuleHookFn)
Machine->setProcessHook(ProcessModuleHookFn);
@@ -1011,14 +987,12 @@ int ModuleSlotTracker::getLocalSlot(const Value *V) {
}
void ModuleSlotTracker::setProcessHook(
- std::function<void(AbstractSlotTrackerStorage *, const Module *, bool)>
- Fn) {
+ std::function<void(AbstractSlotTrackerStorage *, const Module *)> Fn) {
ProcessModuleHookFn = std::move(Fn);
}
void ModuleSlotTracker::setProcessHook(
- std::function<void(AbstractSlotTrackerStorage *, const Function *, bool)>
- Fn) {
+ std::function<void(AbstractSlotTrackerStorage *, const Function *)> Fn) {
ProcessFunctionHookFn = std::move(Fn);
}
@@ -1056,17 +1030,19 @@ static SlotTracker *createSlotTracker(const Value *V) {
// Module level constructor. Causes the contents of the Module (sans functions)
// to be added to the slot table.
-SlotTracker::SlotTracker(const Module *M, bool ShouldInitializeAllMetadata)
- : TheModule(M), ShouldInitializeAllMetadata(ShouldInitializeAllMetadata) {}
+SlotTracker::SlotTracker(const Module *M, bool ShouldTrackMetadataDefinitions)
+ : TheModule(M),
+ ShouldTrackMetadataDefinitions(ShouldTrackMetadataDefinitions) {}
// Function level constructor. Causes the contents of the Module and the one
// function provided to be added to the slot table.
-SlotTracker::SlotTracker(const Function *F, bool ShouldInitializeAllMetadata)
+SlotTracker::SlotTracker(const Function *F)
: TheModule(F ? F->getParent() : nullptr), TheFunction(F),
- ShouldInitializeAllMetadata(ShouldInitializeAllMetadata) {}
+ ShouldTrackMetadataDefinitions(false) {}
SlotTracker::SlotTracker(const ModuleSummaryIndex *Index)
- : TheModule(nullptr), ShouldInitializeAllMetadata(false), TheIndex(Index) {}
+ : TheModule(nullptr), ShouldTrackMetadataDefinitions(false),
+ TheIndex(Index) {}
inline void SlotTracker::initializeIfNeeded() {
if (TheModule) {
@@ -1095,7 +1071,6 @@ void SlotTracker::processModule() {
for (const GlobalVariable &Var : TheModule->globals()) {
if (!Var.hasName())
CreateModuleSlot(&Var);
- processGlobalObjectMetadata(Var);
auto Attrs = Var.getAttributes();
if (Attrs.hasAttributes())
CreateAttributeSetSlot(Attrs);
@@ -1109,13 +1084,6 @@ void SlotTracker::processModule() {
for (const GlobalIFunc &I : TheModule->ifuncs()) {
if (!I.hasName())
CreateModuleSlot(&I);
- processGlobalObjectMetadata(I);
- }
-
- // Add metadata used by named metadata.
- for (const NamedMDNode &NMD : TheModule->named_metadata()) {
- for (const MDNode *N : NMD.operands())
- CreateMetadataSlot(N);
}
for (const Function &F : *TheModule) {
@@ -1123,9 +1091,6 @@ void SlotTracker::processModule() {
// Add all the unnamed functions to the table.
CreateModuleSlot(&F);
- if (ShouldInitializeAllMetadata)
- processFunctionMetadata(F);
-
// Add all the function attributes to the table.
// FIXME: Add attributes of other objects?
AttributeSet FnAttrs = F.getAttributes().getFnAttrs();
@@ -1134,7 +1099,7 @@ void SlotTracker::processModule() {
}
if (ProcessModuleHookFn)
- ProcessModuleHookFn(this, TheModule, ShouldInitializeAllMetadata);
+ ProcessModuleHookFn(this, TheModule);
ST_DEBUG("end processModule!\n");
}
@@ -1144,10 +1109,6 @@ void SlotTracker::processFunction() {
ST_DEBUG("begin processFunction!\n");
fNext = 0;
- // Process function metadata if it wasn't hit at the module-level.
- if (!ShouldInitializeAllMetadata)
- processFunctionMetadata(*TheFunction);
-
// Add all the function arguments with no names.
for(Function::const_arg_iterator AI = TheFunction->arg_begin(),
AE = TheFunction->arg_end(); AI != AE; ++AI)
@@ -1177,7 +1138,7 @@ void SlotTracker::processFunction() {
}
if (ProcessFunctionHookFn)
- ProcessFunctionHookFn(this, TheFunction, ShouldInitializeAllMetadata);
+ ProcessFunctionHookFn(this, TheFunction);
FunctionProcessed = true;
@@ -1220,68 +1181,168 @@ int SlotTracker::processIndex() {
return TypeIdNext;
}
-void SlotTracker::processGlobalObjectMetadata(const GlobalObject &GO) {
- SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
- GO.getAllMetadata(MDs);
- for (auto &MD : MDs)
- CreateMetadataSlot(MD.second);
-}
+namespace {
+class MetadataNodeVisitor {
+ /// Visited MDNodes.
+ SmallPtrSet<const MDNode *, 32> VisitedMDNodes;
+ function_ref<void(const MDNode *)> Visit;
-void SlotTracker::processFunctionMetadata(const Function &F) {
- processGlobalObjectMetadata(F);
- for (auto &BB : F) {
- for (auto &I : BB) {
- for (const DbgRecord &DR : I.getDbgRecordRange())
- processDbgRecordMetadata(DR);
- processInstructionMetadata(I);
- }
+ void visit(const MDNode *N) {
+ if (isa<DIExpression>(N) || !VisitedMDNodes.insert(N).second)
+ return;
+
+ Visit(N);
+ for (const MDOperand &Op : N->operands())
+ if (const auto *OpNode = dyn_cast_or_null<MDNode>(Op.get()))
+ visit(OpNode);
}
-}
-void SlotTracker::processDbgRecordMetadata(const DbgRecord &DR) {
- // Tolerate null metadata pointers: it's a completely illegal debug record,
- // but we can have faulty metadata from debug-intrinsic days being
- // autoupgraded into debug records. This gets caught by the verifier, which
- // then will print the faulty IR, hitting this code path.
- if (const auto *DVR = dyn_cast<const DbgVariableRecord>(&DR)) {
- // Process metadata used by DbgRecords; we only specifically care about the
- // DILocalVariable, DILocation, and DIAssignID fields, as the Value and
- // Expression fields should only be printed inline and so do not use a slot.
- // Note: The above doesn't apply for empty-metadata operands.
- if (auto *Empty = dyn_cast_if_present<MDNode>(DVR->getRawLocation()))
- CreateMetadataSlot(Empty);
- if (DVR->getRawVariable())
- CreateMetadataSlot(DVR->getRawVariable());
- if (DVR->isDbgAssign()) {
- if (auto *AssignID = DVR->getRawAssignID())
- CreateMetadataSlot(cast<MDNode>(AssignID));
- if (auto *Empty = dyn_cast_if_present<MDNode>(DVR->getRawAddress()))
- CreateMetadataSlot(Empty);
+ void visitGlobalObjectMetadata(const GlobalObject &GO) {
+ SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
+ GO.getAllMetadata(MDs);
+ for (auto &MD : MDs)
+ visit(MD.second);
+ }
+
+ void visitDbgRecordMetadata(const DbgRecord &DR) {
+ if (const auto *DVR = dyn_cast<const DbgVariableRecord>(&DR)) {
+ if (auto *Empty = dyn_cast_if_present<MDNode>(DVR->getRawLocation()))
+ visit(Empty);
+ if (DVR->getRawVariable())
+ visit(DVR->getRawVariable());
+ if (DVR->isDbgAssign()) {
+ if (auto *AssignID = DVR->getRawAssignID())
+ visit(cast<MDNode>(AssignID));
+ if (auto *Empty = dyn_cast_if_present<MDNode>(DVR->getRawAddress()))
+ visit(Empty);
+ }
+ } else if (const auto *DLR = dyn_cast<const DbgLabelRecord>(&DR)) {
+ visit(DLR->getRawLabel());
+ } else {
+ llvm_unreachable("unsupported DbgRecord kind");
}
- } else if (const auto *DLR = dyn_cast<const DbgLabelRecord>(&DR)) {
- CreateMetadataSlot(DLR->getRawLabel());
- } else {
- llvm_unreachable("unsupported DbgRecord kind");
+ if (DR.getDebugLoc())
+ visit(DR.getDebugLoc().getAsMDNode());
+ }
+
+ void visitInstructionMetadata(const Instruction &I) {
+ if (const auto *CI = dyn_cast<CallInst>(&I))
+ if (Function *F = CI->getCalledFunction())
+ if (F->isIntrinsic())
+ for (auto &Op : I.operands())
+ if (auto *V = dyn_cast_or_null<MetadataAsValue>(Op))
+ if (auto *N = dyn_cast<MDNode>(V->getMetadata()))
+ visit(N);
+
+ SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
+ I.getAllMetadata(MDs);
+ for (auto &MD : MDs)
+ visit(MD.second);
+ }
+
+ void visitFunctionMetadata(const Function &F) {
+ visitGlobalObjectMetadata(F);
+ for (const BasicBlock &BB : F)
+ for (const Instruction &I : BB) {
+ for (const DbgRecord &DR : I.getDbgRecordRange())
+ visitDbgRecordMetadata(DR);
+ visitInstructionMetadata(I);
+ }
+ }
+
+public:
+ MetadataNodeVisitor(function_ref<void(const MDNode *)> Visit)
+ : Visit(Visit) {}
+
+ void visitModuleMetadata(const Module &M) {
+ for (const GlobalVariable &Var : M.globals())
+ visitGlobalObjectMetadata(Var);
+ for (const GlobalIFunc &I : M.ifuncs())
+ visitGlobalObjectMetadata(I);
+ for (const NamedMDNode &NMD : M.named_metadata())
+ for (const MDNode *N : NMD.operands())
+ visit(N);
+ for (const Function &F : M)
+ visitFunctionMetadata(F);
+ }
+
+ void visitMetadata(ArrayRef<const MDNode *> Metadata) {
+ for (const MDNode *N : Metadata)
+ visit(N);
+ }
+
+ bool contains(const MDNode *N) const { return VisitedMDNodes.contains(N); }
+};
+
+class MetadataIDRenumberer {
+ uint32_t NextID = 0;
+
+public:
+ void run(const Module &M, ArrayRef<const MDNode *> AdditionalMetadata,
+ ModuleSlotTracker::MachineMDNodeListType *AdditionalMetadataNodes =
+ nullptr) {
+ bool IsAdditionalMetadata = false;
+ auto Renumber = [&](const MDNode *N) {
+ N->getContext().pImpl->setMetadataPrintID(const_cast<MDNode *>(N),
+ NextID++);
+ if (IsAdditionalMetadata && AdditionalMetadataNodes)
+ AdditionalMetadataNodes->emplace_back(
+ N->getContext().pImpl->getMetadataPrintID(N), N);
+ };
+ MetadataNodeVisitor Visitor(Renumber);
+
+ Visitor.visitModuleMetadata(M);
+
+ IsAdditionalMetadata = true;
+ Visitor.visitMetadata(AdditionalMetadata);
+
+ // Keep IDs unique for nodes outside the canonical output.
+ SmallVector<MDNode *, 32> RemainingNodes;
+ M.getContext().pImpl->getAllMetadataNodes(RemainingNodes);
+ llvm::erase_if(RemainingNodes, [&](const MDNode *N) {
+ return Visitor.contains(N) ||
+ M.getContext().pImpl->getMetadataPrintID(N) >= NextID;
+ });
+ llvm::sort(RemainingNodes, [&](const MDNode *LHS, const MDNode *RHS) {
+ return M.getContext().pImpl->getMetadataPrintID(LHS) <
+ M.getContext().pImpl->getMetadataPrintID(RHS);
+ });
+ for (MDNode *N : RemainingNodes)
+ M.getContext().pImpl->setMetadataPrintID(
+ N, M.getContext().pImpl->allocateMetadataPrintID());
+
+ if (AdditionalMetadataNodes)
+ llvm::sort(*AdditionalMetadataNodes);
}
- if (DR.getDebugLoc())
- CreateMetadataSlot(DR.getDebugLoc().getAsMDNode());
+};
+} // namespace
+
+void Module::renumberMetadataForAssembly() {
+ MetadataIDRenumberer().run(*this, {});
}
-void SlotTracker::processInstructionMetadata(const Instruction &I) {
- // Process metadata used directly by intrinsics.
- if (const auto *CI = dyn_cast<CallInst>(&I))
- if (Function *F = CI->getCalledFunction())
- if (F->isIntrinsic())
- for (auto &Op : I.operands())
- if (auto *V = dyn_cast_or_null<MetadataAsValue>(Op))
- if (auto *N = dyn_cast<MDNode>(V->getMetadata()))
- CreateMetadataSlot(N);
+void ModuleSlotTracker::renumberMetadataForAssembly(
+ ArrayRef<const MDNode *> AdditionalMetadata,
+ MachineMDNodeListType *AdditionalMetadataNodes) const {
+ assert(M && "metadata renumbering requires a module");
+ MetadataIDRenumberer().run(*M, AdditionalMetadata, AdditionalMetadataNodes);
+}
- // Process metadata attached to this instruction.
- SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
- I.getAllMetadata(MDs);
- for (auto &MD : MDs)
- CreateMetadataSlot(MD.second);
+void ModuleSlotTracker::collectAdditionalMetadata(
+ ArrayRef<const MDNode *> AdditionalMetadata,
+ MachineMDNodeListType &AdditionalMetadataNodes) const {
+ assert(M && "metadata collection requires a module");
+ bool IsAdditionalMetadata = false;
+ auto Collect = [&](const MDNode *N) {
+ if (IsAdditionalMetadata)
+ AdditionalMetadataNodes.emplace_back(
+ N->getContext().pImpl->getMetadataPrintID(N), N);
+ };
+ MetadataNodeVisitor Visitor(Collect);
+ Visitor.visitModuleMetadata(*M);
+ IsAdditionalMetadata = true;
+ Visitor.visitMetadata(AdditionalMetadata);
+ llvm::sort(AdditionalMetadataNodes);
}
/// Clean up after incorporating a function. This is the only way to get out of
@@ -1306,14 +1367,12 @@ int SlotTracker::getGlobalSlot(const GlobalValue *V) {
}
void SlotTracker::setProcessHook(
- std::function<void(AbstractSlotTrackerStorage *, const Module *, bool)>
- Fn) {
+ std::function<void(AbstractSlotTrackerStorage *, const Module *)> Fn) {
ProcessModuleHookFn = std::move(Fn);
}
void SlotTracker::setProcessHook(
- std::function<void(AbstractSlotTrackerStorage *, const Function *, bool)>
- Fn) {
+ std::function<void(AbstractSlotTrackerStorage *, const Function *)> Fn) {
ProcessFunctionHookFn = std::move(Fn);
}
@@ -1325,9 +1384,11 @@ int SlotTracker::getMetadataSlot(const MDNode *N) {
// Check for uninitialized state and do lazy initialization.
initializeIfNeeded();
- // Find the MDNode in the module map
- mdn_iterator MI = mdnMap.find(N);
- return MI == mdnMap.end() ? -1 : (int)MI->second;
+ if (isa<DIExpression>(N))
+ return -1;
+ if (ShouldTrackMetadataDefinitions)
+ CreateMetadataSlot(N);
+ return N->getContext().pImpl->getMetadataPrintID(N);
}
/// getLocalSlot - Get the slot number for a value that is local to a function.
@@ -1420,19 +1481,16 @@ void SlotTracker::CreateFunctionSlot(const Value *V) {
void SlotTracker::CreateMetadataSlot(const MDNode *N) {
assert(N && "Can't insert a null Value into SlotTracker!");
- // Don't make slots for DIExpressions. We just print them inline everywhere.
if (isa<DIExpression>(N))
return;
- unsigned DestSlot = mdnNext;
- if (!mdnMap.insert(std::make_pair(N, DestSlot)).second)
+ unsigned ID = N->getContext().pImpl->getMetadataPrintID(N);
+ if (!mdnMap.try_emplace(N, ID).second)
return;
- ++mdnNext;
- // Recursively add any MDNodes referenced by operands.
- for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
- if (const auto *Op = dyn_cast_or_null<MDNode>(N->getOperand(i)))
- CreateMetadataSlot(Op);
+ for (const MDOperand &Op : N->operands())
+ if (const auto *OpNode = dyn_cast_or_null<MDNode>(Op.get()))
+ CreateMetadataSlot(OpNode);
}
void SlotTracker::CreateAttributeSetSlot(AttributeSet AS) {
@@ -1468,9 +1526,11 @@ struct AsmWriterContext {
TypePrinting *TypePrinter = nullptr;
SlotTracker *Machine = nullptr;
const Module *Context = nullptr;
+ const ModuleSlotTracker *MST = nullptr;
- AsmWriterContext(TypePrinting *TP, SlotTracker *ST, const Module *M = nullptr)
- : TypePrinter(TP), Machine(ST), Context(M) {}
+ AsmWriterContext(TypePrinting *TP, SlotTracker *ST, const Module *M = nullptr,
+ const ModuleSlotTracker *MST = nullptr)
+ : TypePrinter(TP), Machine(ST), Context(M), MST(MST) {}
static AsmWriterContext &getEmpty() {
static AsmWriterContext EmptyCtx(nullptr, nullptr);
@@ -2846,6 +2906,13 @@ static void writeAsOperandInternal(raw_ostream &Out, const Metadata *MD,
}
if (const auto *N = dyn_cast<MDNode>(MD)) {
+ if (const auto *Loc = dyn_cast<DILocation>(N);
+ Loc && WriterCtx.MST &&
+ WriterCtx.MST->shouldPrintDebugLocationInline(Loc)) {
+ writeDILocation(Out, Loc, WriterCtx);
+ return;
+ }
+
std::unique_ptr<SlotTracker> MachineStorage;
SaveAndRestore SARMachine(WriterCtx.Machine);
if (!WriterCtx.Machine) {
@@ -5033,14 +5100,14 @@ void AssemblyWriter::writeMDNode(unsigned Slot, const MDNode *Node) {
}
void AssemblyWriter::writeAllMDNodes() {
- SmallVector<const MDNode *, 16> Nodes;
- Nodes.resize(Machine.mdn_size());
+ SmallVector<std::pair<unsigned, const MDNode *>, 16> Nodes;
+ Nodes.reserve(Machine.mdn_size());
for (auto &I : llvm::make_range(Machine.mdn_begin(), Machine.mdn_end()))
- Nodes[I.second] = cast<MDNode>(I.first);
+ Nodes.emplace_back(I.second, cast<MDNode>(I.first));
+ llvm::sort(Nodes);
- for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
- writeMDNode(i, Nodes[i]);
- }
+ for (auto [Slot, Node] : Nodes)
+ writeMDNode(Slot, Node);
}
void AssemblyWriter::printMDNodeBody(const MDNode *Node) {
@@ -5111,7 +5178,7 @@ void AssemblyWriter::printUseLists(const Function *F) {
void Function::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW,
bool ShouldPreserveUseListOrder, bool IsForDebug) const {
- SlotTracker SlotTable(this->getParent());
+ SlotTracker SlotTable(this);
formatted_raw_ostream OS(ROS);
AssemblyWriter W(OS, SlotTable, this->getParent(), AAW, IsForDebug,
ShouldPreserveUseListOrder);
@@ -5123,15 +5190,14 @@ void BasicBlock::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW,
bool IsForDebug) const {
SlotTracker SlotTable(this->getParent());
formatted_raw_ostream OS(ROS);
- AssemblyWriter W(OS, SlotTable, this->getModule(), AAW,
- IsForDebug,
+ AssemblyWriter W(OS, SlotTable, this->getModule(), AAW, IsForDebug,
ShouldPreserveUseListOrder);
W.printBasicBlock(this);
}
void Module::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW,
bool ShouldPreserveUseListOrder, bool IsForDebug) const {
- SlotTracker SlotTable(this);
+ SlotTracker SlotTable(this, /*ShouldTrackMetadataDefinitions=*/true);
formatted_raw_ostream OS(ROS);
AssemblyWriter W(OS, SlotTable, this, AAW, IsForDebug,
ShouldPreserveUseListOrder);
@@ -5201,26 +5267,15 @@ void Type::print(raw_ostream &OS, bool /*IsForDebug*/, bool NoDetails) const {
}
}
-static bool isReferencingMDNode(const Instruction &I) {
- if (const auto *CI = dyn_cast<CallInst>(&I))
- if (Function *F = CI->getCalledFunction())
- if (F->isIntrinsic())
- for (auto &Op : I.operands())
- if (auto *V = dyn_cast_or_null<MetadataAsValue>(Op))
- if (isa<MDNode>(V->getMetadata()))
- return true;
- return false;
-}
-
void DbgMarker::print(raw_ostream &ROS, bool IsForDebug) const {
- ModuleSlotTracker MST(getModuleFromDPI(this), true);
+ ModuleSlotTracker MST(getModuleFromDPI(this));
print(ROS, MST, IsForDebug);
}
void DbgVariableRecord::print(raw_ostream &ROS, bool IsForDebug) const {
- ModuleSlotTracker MST(getModuleFromDPI(this), true);
+ ModuleSlotTracker MST(getModuleFromDPI(this));
print(ROS, MST, IsForDebug);
}
@@ -5239,7 +5294,7 @@ void DbgMarker::print(raw_ostream &ROS, ModuleSlotTracker &MST,
void DbgLabelRecord::print(raw_ostream &ROS, bool IsForDebug) const {
- ModuleSlotTracker MST(getModuleFromDPI(this), true);
+ ModuleSlotTracker MST(getModuleFromDPI(this));
print(ROS, MST, IsForDebug);
}
@@ -5274,13 +5329,16 @@ void DbgLabelRecord::print(raw_ostream &ROS, ModuleSlotTracker &MST,
}
void Value::print(raw_ostream &ROS, bool IsForDebug) const {
- bool ShouldInitializeAllMetadata = false;
- if (auto *I = dyn_cast<Instruction>(this))
- ShouldInitializeAllMetadata = isReferencingMDNode(*I);
- else if (isa<Function>(this) || isa<MetadataAsValue>(this))
- ShouldInitializeAllMetadata = true;
+ if (const auto *F = dyn_cast<Function>(this)) {
+ F->print(ROS, nullptr, /*ShouldPreserveUseListOrder=*/false, IsForDebug);
+ return;
+ }
+ if (const auto *BB = dyn_cast<BasicBlock>(this)) {
+ BB->print(ROS, nullptr, /*ShouldPreserveUseListOrder=*/false, IsForDebug);
+ return;
+ }
- ModuleSlotTracker MST(getModuleFromVal(this), ShouldInitializeAllMetadata);
+ ModuleSlotTracker MST(getModuleFromVal(this));
print(ROS, MST, IsForDebug);
}
@@ -5360,8 +5418,7 @@ void Value::printAsOperand(raw_ostream &O, bool PrintType,
if (printWithoutType(*this, O, nullptr, M))
return;
- SlotTracker Machine(
- M, /* ShouldInitializeAllMetadata */ isa<MetadataAsValue>(this));
+ SlotTracker Machine(M);
ModuleSlotTracker MST(Machine, M);
printAsOperandImpl(*this, O, PrintType, MST);
}
@@ -5402,8 +5459,10 @@ struct MDTreeAsmWriterContext : public AsmWriterContext {
raw_ostream &MainOS;
MDTreeAsmWriterContext(TypePrinting *TP, SlotTracker *ST, const Module *M,
- raw_ostream &OS, const Metadata *InitMD)
- : AsmWriterContext(TP, ST, M), Level(0U), Visited({InitMD}), MainOS(OS) {}
+ const ModuleSlotTracker *MST, raw_ostream &OS,
+ const Metadata *InitMD)
+ : AsmWriterContext(TP, ST, M, MST), Level(0U), Visited({InitMD}),
+ MainOS(OS) {}
void onWriteMetadataAsOperand(const Metadata *MD) override {
if (!Visited.insert(MD).second)
@@ -5442,10 +5501,10 @@ static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD,
std::unique_ptr<AsmWriterContext> WriterCtx;
if (PrintAsTree && !OnlyAsOperand)
WriterCtx = std::make_unique<MDTreeAsmWriterContext>(
- &TypePrinter, MST.getMachine(), M, OS, &MD);
+ &TypePrinter, MST.getMachine(), M, &MST, OS, &MD);
else
- WriterCtx =
- std::make_unique<AsmWriterContext>(&TypePrinter, MST.getMachine(), M);
+ WriterCtx = std::make_unique<AsmWriterContext>(&TypePrinter,
+ MST.getMachine(), M, &MST);
writeAsOperandInternal(OS, &MD, *WriterCtx, /* FromValue */ true);
@@ -5458,7 +5517,7 @@ static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD,
}
void Metadata::printAsOperand(raw_ostream &OS, const Module *M) const {
- ModuleSlotTracker MST(M, isa<MDNode>(this));
+ ModuleSlotTracker MST(M);
printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ true);
}
@@ -5469,7 +5528,7 @@ void Metadata::printAsOperand(raw_ostream &OS, ModuleSlotTracker &MST,
void Metadata::print(raw_ostream &OS, const Module *M,
bool /*IsForDebug*/) const {
- ModuleSlotTracker MST(M, isa<MDNode>(this));
+ ModuleSlotTracker MST(M);
printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ false);
}
@@ -5479,7 +5538,7 @@ void Metadata::print(raw_ostream &OS, ModuleSlotTracker &MST,
}
void MDNode::printTree(raw_ostream &OS, const Module *M) const {
- ModuleSlotTracker MST(M, true);
+ ModuleSlotTracker MST(M);
printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ false,
/*PrintAsTree=*/true);
}
@@ -5497,15 +5556,13 @@ void ModuleSummaryIndex::print(raw_ostream &ROS, bool IsForDebug) const {
W.printModuleSummaryIndex();
}
-void ModuleSlotTracker::collectMDNodes(MachineMDNodeListType &L, unsigned LB,
- unsigned UB) const {
+void ModuleSlotTracker::collectMDNodes(MachineMDNodeListType &L) const {
SlotTracker *ST = MachineStorage.get();
if (!ST)
return;
for (auto &I : llvm::make_range(ST->mdn_begin(), ST->mdn_end()))
- if (I.second >= LB && I.second < UB)
- L.push_back(std::make_pair(I.second, I.first));
+ L.push_back(std::make_pair(I.second, I.first));
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index a7abd3eed31c3..d1ee8411e392c 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -474,6 +474,7 @@ LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename,
return true;
}
+ unwrap(M)->renumberMetadataForAssembly();
unwrap(M)->print(dest, nullptr);
dest.close();
@@ -491,6 +492,7 @@ char *LLVMPrintModuleToString(LLVMModuleRef M) {
std::string buf;
raw_string_ostream os(buf);
+ unwrap(M)->renumberMetadataForAssembly();
unwrap(M)->print(os, nullptr);
return strdup(buf.c_str());
diff --git a/llvm/lib/IR/IRPrintingPasses.cpp b/llvm/lib/IR/IRPrintingPasses.cpp
index 43671b0b9a1a3..a84f8db98bee4 100644
--- a/llvm/lib/IR/IRPrintingPasses.cpp
+++ b/llvm/lib/IR/IRPrintingPasses.cpp
@@ -26,37 +26,49 @@ using namespace llvm;
namespace {
+static void printModule(raw_ostream &OS, StringRef Banner,
+ bool ShouldPreserveUseListOrder, Module &M) {
+ if (llvm::isFunctionInPrintList("*")) {
+ if (!Banner.empty())
+ OS << Banner << "\n";
+ M.print(OS, nullptr, ShouldPreserveUseListOrder);
+ return;
+ }
+
+ bool BannerPrinted = false;
+ for (const auto &F : M.functions()) {
+ if (!llvm::isFunctionInPrintList(F.getName()))
+ continue;
+ if (!BannerPrinted && !Banner.empty()) {
+ OS << Banner << "\n";
+ BannerPrinted = true;
+ }
+ F.print(OS);
+ }
+}
+
class PrintModulePassWrapper : public ModulePass {
raw_ostream &OS;
std::string Banner;
bool ShouldPreserveUseListOrder;
+ bool ShouldRenumberMetadata;
public:
static char ID;
- PrintModulePassWrapper() : ModulePass(ID), OS(dbgs()) {}
+ PrintModulePassWrapper()
+ : ModulePass(ID), OS(dbgs()), ShouldPreserveUseListOrder(false),
+ ShouldRenumberMetadata(false) {}
PrintModulePassWrapper(raw_ostream &OS, const std::string &Banner,
- bool ShouldPreserveUseListOrder)
+ bool ShouldPreserveUseListOrder,
+ bool ShouldRenumberMetadata)
: ModulePass(ID), OS(OS), Banner(Banner),
- ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {}
+ ShouldPreserveUseListOrder(ShouldPreserveUseListOrder),
+ ShouldRenumberMetadata(ShouldRenumberMetadata) {}
bool runOnModule(Module &M) override {
- if (llvm::isFunctionInPrintList("*")) {
- if (!Banner.empty())
- OS << Banner << "\n";
- M.print(OS, nullptr, ShouldPreserveUseListOrder);
- } else {
- bool BannerPrinted = false;
- for (const auto &F : M.functions()) {
- if (llvm::isFunctionInPrintList(F.getName())) {
- if (!BannerPrinted && !Banner.empty()) {
- OS << Banner << "\n";
- BannerPrinted = true;
- }
- F.print(OS);
- }
- }
- }
-
+ if (ShouldRenumberMetadata)
+ M.renumberMetadataForAssembly();
+ printModule(OS, Banner, ShouldPreserveUseListOrder, M);
return false;
}
@@ -80,10 +92,10 @@ class PrintFunctionPassWrapper : public FunctionPass {
// This pass just prints a banner followed by the function as it's processed.
bool runOnFunction(Function &F) override {
if (isFunctionInPrintList(F.getName())) {
- if (forcePrintModuleIR())
- OS << Banner << " (function: " << F.getName() << ")\n"
- << *F.getParent();
- else
+ if (forcePrintModuleIR()) {
+ OS << Banner << " (function: " << F.getName() << ")\n";
+ F.getParent()->print(OS, nullptr);
+ } else
OS << Banner << '\n' << static_cast<Value &>(F);
}
@@ -109,7 +121,16 @@ INITIALIZE_PASS(PrintFunctionPassWrapper, "print-function",
ModulePass *llvm::createPrintModulePass(llvm::raw_ostream &OS,
const std::string &Banner,
bool ShouldPreserveUseListOrder) {
- return new PrintModulePassWrapper(OS, Banner, ShouldPreserveUseListOrder);
+ return createPrintModulePass(OS, Banner, ShouldPreserveUseListOrder,
+ /*ShouldRenumberMetadata=*/false);
+}
+
+ModulePass *llvm::createPrintModulePass(llvm::raw_ostream &OS,
+ const std::string &Banner,
+ bool ShouldPreserveUseListOrder,
+ bool ShouldRenumberMetadata) {
+ return new PrintModulePassWrapper(OS, Banner, ShouldPreserveUseListOrder,
+ ShouldRenumberMetadata);
}
FunctionPass *llvm::createPrintFunctionPass(llvm::raw_ostream &OS,
diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp
index 90afa09f73abe..83baaf16b7c8c 100644
--- a/llvm/lib/IR/LLVMContextImpl.cpp
+++ b/llvm/lib/IR/LLVMContextImpl.cpp
@@ -40,6 +40,15 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
Int64Ty(C, 64), Int128Ty(C, 128), Byte1Ty(C, 1), Byte8Ty(C, 8),
Byte16Ty(C, 16), Byte32Ty(C, 32), Byte64Ty(C, 64), Byte128Ty(C, 128) {}
+void LLVMContextImpl::getAllMetadataNodes(
+ SmallVectorImpl<MDNode *> &Nodes) const {
+ Nodes.append(DistinctMDNodes.begin(), DistinctMDNodes.end());
+#define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) \
+ Nodes.append(CLASS##s.begin(), CLASS##s.end());
+#include "llvm/IR/Metadata.def"
+ Nodes.append(TemporaryMDNodes.begin(), TemporaryMDNodes.end());
+}
+
LLVMContextImpl::~LLVMContextImpl() {
#ifndef NDEBUG
// Check that any variable location records that fell off the end of a block
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 2d22484d2ffb7..a6342389d8543 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -1637,6 +1637,20 @@ class LLVMContextImpl {
DenseMap<Metadata *, MetadataAsValue *> MetadataAsValues;
DenseSet<DIArgList *, DIArgListInfo> DIArgLists;
+ uint32_t NextMetadataPrintID = 0;
+
+ uint32_t allocateMetadataPrintID() { return NextMetadataPrintID++; }
+
+ void getAllMetadataNodes(SmallVectorImpl<MDNode *> &Nodes) const;
+
+ uint32_t getMetadataPrintID(const MDNode *N) const {
+ return N->getHeader().MetadataPrintID;
+ }
+
+ void setMetadataPrintID(MDNode *N, uint32_t ID) {
+ N->getHeader().MetadataPrintID = ID;
+ }
+
#define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) \
DenseSet<CLASS *, CLASS##Info> CLASS##s;
#include "llvm/IR/Metadata.def"
@@ -1650,6 +1664,10 @@ class LLVMContextImpl {
// them on context teardown.
std::vector<MDNode *> DistinctMDNodes;
+ // Temporary nodes are caller-owned, but track live ones for persistent
+ // metadata print IDs.
+ DenseSet<MDNode *> TemporaryMDNodes;
+
// ConstantRangeListAttributeImpl is a TrailingObjects/ArrayRef of
// ConstantRange. Since this is a dynamically sized class, it's not
// possible to use SpecificBumpPtrAllocator. Instead, we use normal Alloc
diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index 0a4141ee2362e..2b1a7bb117308 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -650,6 +650,8 @@ StringRef MDString::getString() const {
void *MDNode::operator new(size_t Size, size_t NumOps, StorageType Storage) {
// uint64_t is the most aligned type we need support (ensured by static_assert
// above)
+ static_assert(sizeof(Header) == sizeof(size_t) + 2 * sizeof(uint32_t),
+ "MDNode header fields poorly packed");
size_t AllocSize =
alignTo(Header::getAllocSize(Storage, NumOps), alignof(uint64_t));
char *Mem = reinterpret_cast<char *>(::operator new(AllocSize + Size));
@@ -667,6 +669,8 @@ void MDNode::operator delete(void *N) {
MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2)
: Metadata(ID, Storage), Context(Context) {
+ getHeader().MetadataPrintID = Context.pImpl->allocateMetadataPrintID();
+
unsigned Op = 0;
for (Metadata *MD : Ops1)
setOperand(Op++, MD);
@@ -781,6 +785,9 @@ void MDNode::countUnresolvedOperands() {
void MDNode::makeUniqued() {
assert(isTemporary() && "Expected this to be temporary");
assert(!isResolved() && "Expected this to be unresolved");
+ bool WasTracked = getContext().pImpl->TemporaryMDNodes.erase(this);
+ assert(WasTracked && "Temporary node not tracked");
+ (void)WasTracked;
// Enable uniquing callbacks.
for (auto &Op : mutable_operands())
@@ -981,6 +988,11 @@ void MDNode::handleChangedOperand(void *Ref, Metadata *New) {
}
void MDNode::deleteAsSubclass() {
+ if (isTemporary()) {
+ bool WasTracked = getContext().pImpl->TemporaryMDNodes.erase(this);
+ assert(WasTracked && "Temporary node not tracked");
+ (void)WasTracked;
+ }
switch (getMetadataID()) {
default:
llvm_unreachable("Invalid subclass of MDNode");
@@ -1066,6 +1078,11 @@ void MDNode::deleteTemporary(MDNode *N) {
void MDNode::storeDistinctInContext() {
assert(!Context.hasReplaceableUses() && "Unexpected replaceable uses");
assert(!getNumUnresolved() && "Unexpected unresolved nodes");
+ if (isTemporary()) {
+ bool WasTracked = getContext().pImpl->TemporaryMDNodes.erase(this);
+ assert(WasTracked && "Temporary node not tracked");
+ (void)WasTracked;
+ }
Storage = Distinct;
assert(isResolved() && "Expected this to be resolved");
diff --git a/llvm/lib/IR/MetadataImpl.h b/llvm/lib/IR/MetadataImpl.h
index b4188dd7d3ee4..0045b7c406f97 100644
--- a/llvm/lib/IR/MetadataImpl.h
+++ b/llvm/lib/IR/MetadataImpl.h
@@ -33,6 +33,7 @@ template <class T> T *MDNode::storeImpl(T *N, StorageType Storage) {
N->storeDistinctInContext();
break;
case Temporary:
+ N->getContext().pImpl->TemporaryMDNodes.insert(N);
break;
}
return N;
@@ -48,6 +49,7 @@ T *MDNode::storeImpl(T *N, StorageType Storage, StoreT &Store) {
N->storeDistinctInContext();
break;
case Temporary:
+ N->getContext().pImpl->TemporaryMDNodes.insert(N);
break;
}
return N;
diff --git a/llvm/lib/IR/SSAContext.cpp b/llvm/lib/IR/SSAContext.cpp
index feb8570d32757..ca093a1e6a76c 100644
--- a/llvm/lib/IR/SSAContext.cpp
+++ b/llvm/lib/IR/SSAContext.cpp
@@ -93,7 +93,7 @@ template <> Printable SSAContext::print(const BasicBlock *BB) const {
return Printable([BB](raw_ostream &Out) { Out << BB->getName(); });
return Printable([BB](raw_ostream &Out) {
- ModuleSlotTracker MST{BB->getParent()->getParent(), false};
+ ModuleSlotTracker MST{BB->getParent()->getParent()};
MST.incorporateFunction(*BB->getParent());
Out << MST.getLocalSlot(BB);
});
diff --git a/llvm/lib/IRPrinter/IRPrintingPasses.cpp b/llvm/lib/IRPrinter/IRPrintingPasses.cpp
index adb192ac4a916..8893e34fdeec2 100644
--- a/llvm/lib/IRPrinter/IRPrintingPasses.cpp
+++ b/llvm/lib/IRPrinter/IRPrintingPasses.cpp
@@ -23,15 +23,22 @@
using namespace llvm;
-PrintModulePass::PrintModulePass() : OS(dbgs()) {}
+PrintModulePass::PrintModulePass()
+ : OS(dbgs()), ShouldPreserveUseListOrder(false), EmitSummaryIndex(false),
+ ShouldRenumberMetadata(false) {}
PrintModulePass::PrintModulePass(raw_ostream &OS, const std::string &Banner,
bool ShouldPreserveUseListOrder,
- bool EmitSummaryIndex)
+ bool EmitSummaryIndex,
+ bool ShouldRenumberMetadata)
: OS(OS), Banner(Banner),
ShouldPreserveUseListOrder(ShouldPreserveUseListOrder),
- EmitSummaryIndex(EmitSummaryIndex) {}
+ EmitSummaryIndex(EmitSummaryIndex),
+ ShouldRenumberMetadata(ShouldRenumberMetadata) {}
PreservedAnalyses PrintModulePass::run(Module &M, ModuleAnalysisManager &AM) {
+ if (ShouldRenumberMetadata)
+ M.renumberMetadataForAssembly();
+
if (llvm::isFunctionInPrintList("*")) {
if (!Banner.empty())
OS << Banner << "\n";
@@ -68,9 +75,10 @@ PrintFunctionPass::PrintFunctionPass(raw_ostream &OS, const std::string &Banner)
PreservedAnalyses PrintFunctionPass::run(Function &F,
FunctionAnalysisManager &) {
if (isFunctionInPrintList(F.getName())) {
- if (forcePrintModuleIR())
- OS << Banner << " (function: " << F.getName() << ")\n" << *F.getParent();
- else
+ if (forcePrintModuleIR()) {
+ OS << Banner << " (function: " << F.getName() << ")\n";
+ F.getParent()->print(OS, nullptr);
+ } else
OS << Banner << '\n' << static_cast<Value &>(F);
}
diff --git a/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp b/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp
index 35990848e0e1d..8d8a7812e47f8 100644
--- a/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp
+++ b/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp
@@ -9,6 +9,9 @@
#include "DXILPrettyPrinter.h"
#include "DirectX.h"
#include "DirectXIRPasses/DXILDebugInfo.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/DXILResource.h"
#include "llvm/IR/AssemblyAnnotationWriter.h"
@@ -262,17 +265,25 @@ static void prettyPrintResources(raw_ostream &OS, const DXILResourceMap &DRM,
}
namespace {
+class DXILModuleSlotTracker : public ModuleSlotTracker {
+public:
+ using ModuleSlotTracker::ModuleSlotTracker;
+ using ModuleSlotTracker::renumberMetadataForAssembly;
+};
+
class DXILAssemblyAnnotationWriter : public llvm::AssemblyAnnotationWriter {
private:
ModuleSlotTracker &MST;
AbstractSlotTrackerStorage &STS;
const DXILDebugInfoMap &DI;
+ DenseSet<const MDNode *> &EmittedMDNodes;
public:
DXILAssemblyAnnotationWriter(ModuleSlotTracker &MST,
AbstractSlotTrackerStorage &STS,
- const DXILDebugInfoMap &DI)
- : MST(MST), STS(STS), DI(DI) {}
+ const DXILDebugInfoMap &DI,
+ DenseSet<const MDNode *> &EmittedMDNodes)
+ : MST(MST), STS(STS), DI(DI), EmittedMDNodes(EmittedMDNodes) {}
void emitInstructionAnnot(const Instruction *OrigI,
formatted_raw_ostream &os) override {
@@ -284,10 +295,11 @@ class DXILAssemblyAnnotationWriter : public llvm::AssemblyAnnotationWriter {
}
void emitMDNodeAnnot(const MDNode *N, formatted_raw_ostream &os) override {
+ EmittedMDNodes.insert(N);
+
if (const Metadata *NewMD = DI.MDReplace.lookup(N)) {
if (const auto *NewN = dyn_cast<MDNode>(NewMD))
- if (STS.getMetadataSlot(NewN) == -1)
- STS.createMetadataSlot(NewN);
+ STS.createMetadataSlot(NewN);
os << "; DXIL: ";
N->printAsOperand(os, MST);
@@ -299,8 +311,7 @@ class DXILAssemblyAnnotationWriter : public llvm::AssemblyAnnotationWriter {
if (const Metadata *ExtraMD = DI.MDExtra.lookup(N)) {
if (const auto *ExtraN = dyn_cast<MDNode>(ExtraMD))
- if (STS.getMetadataSlot(ExtraN) == -1)
- STS.createMetadataSlot(ExtraN);
+ STS.createMetadataSlot(ExtraN);
os << "; DXIL: ";
N->printAsOperand(os, MST);
@@ -313,6 +324,71 @@ class DXILAssemblyAnnotationWriter : public llvm::AssemblyAnnotationWriter {
};
} // namespace
+static SmallVector<const MDNode *>
+collectAdditionalMetadata(Module &M, const DXILDebugInfoMap &DI) {
+ // Annotation metadata follows module metadata in the order its keys print.
+ // Follow replacement graphs to preserve that order in canonical output.
+ M.renumberMetadataForAssembly();
+
+ ModuleSlotTracker MST(&M);
+ AbstractSlotTrackerStorage *STS = nullptr;
+ MST.setProcessHook(
+ [&](AbstractSlotTrackerStorage *STS_, const Module *) { STS = STS_; });
+ MDNode::get(M.getContext(), {})->print(llvm::nulls(), MST);
+ assert(STS && "Slot tracker storage should have been initialised");
+
+ DenseSet<const Metadata *> ReplacementMetadata;
+ for (auto [_, Replacement] : DI.MDReplace)
+ ReplacementMetadata.insert(Replacement);
+
+ SmallVector<std::pair<unsigned, const MDNode *>> OriginalNodes;
+ DenseSet<const MDNode *> Queued;
+ auto AddOriginal = [&](const Metadata *MD) {
+ const auto *N = dyn_cast<MDNode>(MD);
+ if (!N || ReplacementMetadata.contains(N) || !Queued.insert(N).second)
+ return;
+ OriginalNodes.emplace_back(STS->getMetadataSlot(N), N);
+ };
+ for (auto [Original, _] : DI.MDReplace)
+ AddOriginal(Original);
+ for (auto [Original, _] : DI.MDExtra)
+ AddOriginal(Original);
+ llvm::sort(OriginalNodes);
+
+ SmallVector<const MDNode *> Worklist;
+ for (auto [_, N] : OriginalNodes)
+ Worklist.push_back(N);
+
+ SmallVector<const MDNode *> AdditionalMetadata;
+ auto AddAdditional = [&](const Metadata *MD) {
+ const auto *Root = dyn_cast_or_null<MDNode>(MD);
+ if (!Root || Queued.contains(Root))
+ return;
+
+ AdditionalMetadata.push_back(Root);
+ SmallVector<const MDNode *> Nodes = {Root};
+ while (!Nodes.empty()) {
+ const MDNode *N = Nodes.pop_back_val();
+ if (!Queued.insert(N).second)
+ continue;
+ Worklist.push_back(N);
+ for (const MDOperand &Op : llvm::reverse(N->operands()))
+ if (const auto *OpNode = dyn_cast_or_null<MDNode>(Op.get()))
+ Nodes.push_back(OpNode);
+ }
+ };
+
+ for (size_t I = 0; I != Worklist.size(); ++I) {
+ const MDNode *N = Worklist[I];
+ if (const Metadata *Replacement = DI.MDReplace.lookup(N)) {
+ AddAdditional(Replacement);
+ continue;
+ }
+ AddAdditional(DI.MDExtra.lookup(N));
+ }
+ return AdditionalMetadata;
+}
+
static void prettyPrint(raw_ostream &OS, Module &M, const DXILResourceMap &DRM,
DXILResourceTypeMap &DRTM) {
formatted_raw_ostream FOS(OS);
@@ -321,30 +397,32 @@ static void prettyPrint(raw_ostream &OS, Module &M, const DXILResourceMap &DRM,
DXILDebugInfoMap DI = DXILDebugInfoPass::run(M);
- ModuleSlotTracker MST(&M);
+ SmallVector<const MDNode *> AdditionalMetadata =
+ collectAdditionalMetadata(M, DI);
+ DXILModuleSlotTracker MST(&M);
+ MST.renumberMetadataForAssembly(AdditionalMetadata);
AbstractSlotTrackerStorage *STS = nullptr;
- unsigned NextMetadataSlot = 0;
MST.setProcessHook(
- [&](AbstractSlotTrackerStorage *STS_, const Module *, bool) {
- STS = STS_;
- NextMetadataSlot = STS->getNextMetadataSlot();
- });
+ [&](AbstractSlotTrackerStorage *STS_, const Module *) { STS = STS_; });
// Force initialisation. ModuleSlotTracker does not have a dedicated function
// for this so trigger it through a dummy print.
MDNode::get(M.getContext(), {})->print(llvm::nulls(), MST);
assert(STS && "Slot tracker storage should have been initialised");
- DXILAssemblyAnnotationWriter DAAW(MST, *STS, DI);
+ DenseSet<const MDNode *> EmittedMDNodes;
+ DXILAssemblyAnnotationWriter DAAW(MST, *STS, DI, EmittedMDNodes);
M.print(FOS, &DAAW);
ModuleSlotTracker::MachineMDNodeListType MDNodes;
- MST.collectMDNodes(MDNodes, NextMetadataSlot, ~0u);
+ MST.collectMDNodes(MDNodes);
std::sort(MDNodes.begin(), MDNodes.end(),
[](const std::pair<unsigned, const MDNode *> &A,
const std::pair<unsigned, const MDNode *> &B) {
return A.first < B.first;
});
for (auto [_, MDNode] : MDNodes) {
+ if (EmittedMDNodes.contains(MDNode))
+ continue;
DAAW.emitMDNodeAnnot(MDNode, FOS);
MDNode->print(FOS, MST);
FOS << "\n";
diff --git a/llvm/test/CodeGen/DirectX/DebugInfo/di-globalvariable.ll b/llvm/test/CodeGen/DirectX/DebugInfo/di-globalvariable.ll
index 978c6f6cfb221..fd23adbcd42b5 100644
--- a/llvm/test/CodeGen/DirectX/DebugInfo/di-globalvariable.ll
+++ b/llvm/test/CodeGen/DirectX/DebugInfo/di-globalvariable.ll
@@ -1,4 +1,5 @@
; RUN: llc %s -o - | FileCheck %s
+; RUN: llc %s -o - | FileCheck %s --check-prefix=NO-DUP
target triple = "dxil-unknown-shadermodel6.3-library"
@@ -24,6 +25,12 @@ define void @foo() {
; CHECK-DAG: ![[FILE]] = !DIFile(filename: "cu.cpp", directory: "/tmp")
; CHECK-DAG: ![[TYPE]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+; NO-DUP: ![[GVY:[0-9]+]] = !DIGlobalVariable(name: "y"
+; NO-DUP-NOT: ![[GVY]] =
+; NO-DUP: ![[GVX:[0-9]+]] = !DIGlobalVariable(name: "x"
+; NO-DUP-NOT: ![[GVX]] =
+; NO-DUP-NOT: ![[GVY]] =
+
!llvm.dbg.cu = !{!4}
!llvm.module.flags = !{!8, !9}
diff --git a/llvm/test/CodeGen/Hexagon/swp-no-alias.mir b/llvm/test/CodeGen/Hexagon/swp-no-alias.mir
index 38b7212702ff9..c37b9b32f8230 100644
--- a/llvm/test/CodeGen/Hexagon/swp-no-alias.mir
+++ b/llvm/test/CodeGen/Hexagon/swp-no-alias.mir
@@ -27,7 +27,7 @@
# CHECK-DAG: SU(4): Data Latency=0 Reg=%10
# CHECK-DAG: SU(2): Data Latency=0 Reg=%10
# CHECK-DAG: SU(7): Anti Latency=1
-# CHECK-NEXT: SU(2): %12:hvxvr = V6_vL32b_ai %10:intregs, 0 :: (load (s1024) from %ir.iptr.09, !tbaa !4)
+# CHECK-NEXT: SU(2): %12:hvxvr = V6_vL32b_ai %10:intregs, 0 :: (load (s1024) from %ir.iptr.09, !tbaa !10)
# CHECK-NEXT: # preds left
# CHECK-NEXT: # succs left
# CHECK-NEXT: # rdefs left
@@ -38,7 +38,7 @@
# CHECK-NEXT: SU(1): Data Latency=0 Reg=%10
# CHECK-NEXT: Successors:
# CHECK-NEXT: SU(3): Data Latency=0 Reg=%12
-# CHECK-NEXT: SU(3): V6_vS32b_ai %8:intregs, 0, %12:hvxvr :: (store (s1024) into %ir.optr.010, !tbaa !4)
+# CHECK-NEXT: SU(3): V6_vS32b_ai %8:intregs, 0, %12:hvxvr :: (store (s1024) into %ir.optr.010, !tbaa !10)
# CHECK-NEXT: # preds left
# CHECK-NEXT: # succs left
# CHECK-NEXT: # rdefs left
@@ -48,7 +48,7 @@
# CHECK-NEXT: Predecessors:
# CHECK-DAG: SU(2): Data Latency=0 Reg=%12
# CHECK-DAG: SU(0): Data Latency=0 Reg=%8
-# CHECK-NEXT: SU(4): %13:hvxvr = V6_vL32b_ai %10:intregs, 128 :: (load (s1024) from %ir.cgep, !tbaa !4)
+# CHECK-NEXT: SU(4): %13:hvxvr = V6_vL32b_ai %10:intregs, 128 :: (load (s1024) from %ir.cgep, !tbaa !10)
# CHECK-NEXT: # preds left
# CHECK-NEXT: # succs left
# CHECK-NEXT: # rdefs left
@@ -59,7 +59,7 @@
# CHECK-NEXT: SU(1): Data Latency=0 Reg=%10
# CHECK-NEXT: Successors:
# CHECK-NEXT: SU(5): Data Latency=0 Reg=%13
-# CHECK-NEXT: SU(5): V6_vS32b_ai %8:intregs, 128, %13:hvxvr :: (store (s1024) into %ir.cgep3, !tbaa !4)
+# CHECK-NEXT: SU(5): V6_vS32b_ai %8:intregs, 128, %13:hvxvr :: (store (s1024) into %ir.cgep3, !tbaa !10)
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/instr-mmra.mir b/llvm/test/CodeGen/MIR/AMDGPU/instr-mmra.mir
index 62593255ea4ab..7dce5c230df63 100644
--- a/llvm/test/CodeGen/MIR/AMDGPU/instr-mmra.mir
+++ b/llvm/test/CodeGen/MIR/AMDGPU/instr-mmra.mir
@@ -19,7 +19,7 @@ body: |
liveins: $vgpr0, $vgpr1
; CHECK-LABEL: name: test_mmra
- ; CHECK: ATOMIC_FENCE 5, 2, mmra !0
+ ; CHECK: ATOMIC_FENCE 5, 2, mmra !{{[0-9]+}}
ATOMIC_FENCE 5, 2, mmra !0
S_ENDPGM 0
...
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/machine-metadata.mir b/llvm/test/CodeGen/MIR/AMDGPU/machine-metadata.mir
index 9570f8b98c468..45cf5a3fb7f7b 100644
--- a/llvm/test/CodeGen/MIR/AMDGPU/machine-metadata.mir
+++ b/llvm/test/CodeGen/MIR/AMDGPU/machine-metadata.mir
@@ -86,11 +86,11 @@ body: |
; CHECK: [[REG_SEQUENCE:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1
; CHECK: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1
; CHECK: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE1]]
- ; CHECK: [[GLOBAL_LOAD_DWORDX4_:%[0-9]+]]:vreg_128 = GLOBAL_LOAD_DWORDX4 [[COPY5]], 16, 0, implicit $exec :: (load (s128) from %ir.p1, align 4, !alias.scope !5, !noalias !8, addrspace 1)
+ ; CHECK: [[GLOBAL_LOAD_DWORDX4_:%[0-9]+]]:vreg_128 = GLOBAL_LOAD_DWORDX4 [[COPY5]], 16, 0, implicit $exec :: (load (s128) from %ir.p1, align 4, !alias.scope ![[LOAD_SCOPE:[0-9]+]], !noalias ![[LOAD_NOALIAS:[0-9]+]], addrspace 1)
; CHECK: [[COPY6:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE1]]
- ; CHECK: GLOBAL_STORE_DWORDX4 [[COPY6]], killed [[GLOBAL_LOAD_DWORDX4_]], 0, 0, implicit $exec :: (store (s128) into %ir.p0, align 4, !alias.scope !10, !noalias !11, addrspace 1)
+ ; CHECK: GLOBAL_STORE_DWORDX4 [[COPY6]], killed [[GLOBAL_LOAD_DWORDX4_]], 0, 0, implicit $exec :: (store (s128) into %ir.p0, align 4, !alias.scope ![[STORE_SCOPE:[0-9]+]], !noalias ![[STORE_NOALIAS:[0-9]+]], addrspace 1)
; CHECK: [[COPY7:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE]]
- ; CHECK: [[GLOBAL_LOAD_DWORDX2_:%[0-9]+]]:vreg_64 = GLOBAL_LOAD_DWORDX2 killed [[COPY7]], 0, 0, implicit $exec :: (load (s64) from %ir.1, align 4, !alias.scope !3, !noalias !0, addrspace 1)
+ ; CHECK: [[GLOBAL_LOAD_DWORDX2_:%[0-9]+]]:vreg_64 = GLOBAL_LOAD_DWORDX2 killed [[COPY7]], 0, 0, implicit $exec :: (load (s64) from %ir.1, align 4, !alias.scope ![[IR_SCOPE:[0-9]+]], !noalias ![[IR_NOALIAS:[0-9]+]], addrspace 1)
; CHECK: [[COPY8:%[0-9]+]]:vgpr_32 = COPY [[GLOBAL_LOAD_DWORDX2_]].sub0
; CHECK: [[COPY9:%[0-9]+]]:vgpr_32 = COPY [[GLOBAL_LOAD_DWORDX2_]].sub1
; CHECK: [[V_ADD_U32_e64_:%[0-9]+]]:vgpr_32 = V_ADD_U32_e64 killed [[COPY8]], killed [[COPY9]], 0, implicit $exec
@@ -137,11 +137,11 @@ body: |
; CHECK: [[REG_SEQUENCE:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1
; CHECK: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1
; CHECK: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE1]]
- ; CHECK: [[GLOBAL_LOAD_DWORDX4_:%[0-9]+]]:vreg_128 = GLOBAL_LOAD_DWORDX4 [[COPY5]], 16, 0, implicit $exec :: (load (s128) from %ir.p1, align 4, !alias.scope !5, !noalias !8, addrspace 1)
+ ; CHECK: [[GLOBAL_LOAD_DWORDX4_:%[0-9]+]]:vreg_128 = GLOBAL_LOAD_DWORDX4 [[COPY5]], 16, 0, implicit $exec :: (load (s128) from %ir.p1, align 4, !alias.scope ![[INLINE_LOAD_SCOPE:[0-9]+]], !noalias ![[INLINE_LOAD_NOALIAS:[0-9]+]], addrspace 1)
; CHECK: [[COPY6:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE1]]
- ; CHECK: GLOBAL_STORE_DWORDX4 [[COPY6]], killed [[GLOBAL_LOAD_DWORDX4_]], 0, 0, implicit $exec :: (store (s128) into %ir.p0, align 4, !alias.scope !10, !noalias !11, addrspace 1)
+ ; CHECK: GLOBAL_STORE_DWORDX4 [[COPY6]], killed [[GLOBAL_LOAD_DWORDX4_]], 0, 0, implicit $exec :: (store (s128) into %ir.p0, align 4, !alias.scope ![[INLINE_STORE_SCOPE:[0-9]+]], !noalias ![[INLINE_STORE_NOALIAS:[0-9]+]], addrspace 1)
; CHECK: [[COPY7:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE]]
- ; CHECK: [[GLOBAL_LOAD_DWORDX2_:%[0-9]+]]:vreg_64 = GLOBAL_LOAD_DWORDX2 killed [[COPY7]], 0, 0, implicit $exec :: (load (s64) from %ir.1, align 4, !alias.scope !3, !noalias !0, addrspace 1)
+ ; CHECK: [[GLOBAL_LOAD_DWORDX2_:%[0-9]+]]:vreg_64 = GLOBAL_LOAD_DWORDX2 killed [[COPY7]], 0, 0, implicit $exec :: (load (s64) from %ir.1, align 4, !alias.scope ![[IR_SCOPE]], !noalias ![[IR_NOALIAS]], addrspace 1)
; CHECK: [[COPY8:%[0-9]+]]:vgpr_32 = COPY [[GLOBAL_LOAD_DWORDX2_]].sub0
; CHECK: [[COPY9:%[0-9]+]]:vgpr_32 = COPY [[GLOBAL_LOAD_DWORDX2_]].sub1
; CHECK: [[V_ADD_U32_e64_:%[0-9]+]]:vgpr_32 = V_ADD_U32_e64 killed [[COPY8]], killed [[COPY9]], 0, implicit $exec
diff --git a/llvm/test/CodeGen/MIR/X86/instr-heap-alloc-operands.mir b/llvm/test/CodeGen/MIR/X86/instr-heap-alloc-operands.mir
index ca59e5fe7b8fd..724335cc371dc 100644
--- a/llvm/test/CodeGen/MIR/X86/instr-heap-alloc-operands.mir
+++ b/llvm/test/CodeGen/MIR/X86/instr-heap-alloc-operands.mir
@@ -34,7 +34,7 @@ body: |
ADJCALLSTACKDOWN64 32, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
$ecx = COPY %0
CALL64pcrel32 @f, csr_win64, implicit $rsp, implicit $ssp, implicit $ecx, implicit-def $rsp, implicit-def $ssp, implicit-def dead $rax, heap-alloc-marker !2
- ; CHECK: CALL64pcrel32 @f, {{.*}} heap-alloc-marker !2
+ ; CHECK: CALL64pcrel32 @f, {{.*}} heap-alloc-marker !{{[0-9]+}}
ADJCALLSTACKUP64 32, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
$eax = MOV32r0 implicit-def dead $eflags
RET 0, killed $eax
diff --git a/llvm/test/CodeGen/MIR/X86/instr-pcsections.mir b/llvm/test/CodeGen/MIR/X86/instr-pcsections.mir
index 947d93ef35937..4a50838f45444 100644
--- a/llvm/test/CodeGen/MIR/X86/instr-pcsections.mir
+++ b/llvm/test/CodeGen/MIR/X86/instr-pcsections.mir
@@ -27,7 +27,7 @@ body: |
liveins: $rdi
; CHECK-LABEL: name: test
- ; CHECK: MOV{{.*}} pcsections !0
+ ; CHECK: MOV{{.*}} pcsections !{{[0-9]+}}
renamable $al = MOV8rm killed renamable $rdi, 1, $noreg, 0, $noreg, pcsections !0
RET64 implicit killed $al
diff --git a/llvm/test/CodeGen/MIR/X86/instructions-debug-location.mir b/llvm/test/CodeGen/MIR/X86/instructions-debug-location.mir
index 11fed8ae64fd0..11b41182a36af 100644
--- a/llvm/test/CodeGen/MIR/X86/instructions-debug-location.mir
+++ b/llvm/test/CodeGen/MIR/X86/instructions-debug-location.mir
@@ -72,10 +72,10 @@ stack:
body: |
bb.0.entry:
liveins: $edi
- ; CHECK: DBG_VALUE $noreg, 0, !11, !DIExpression(), debug-location !12
- ; CHECK: DBG_VALUE $noreg, 0, !11, !DIExpression(), debug-location !12
- ; CHECK: $eax = COPY %0, debug-location !13
- ; CHECK: RET64 $eax, debug-location !13
+ ; CHECK: DBG_VALUE $noreg, 0, ![[VAR:[0-9]+]], !DIExpression(), debug-location ![[VAR_LOC:[0-9]+]]
+ ; CHECK: DBG_VALUE $noreg, 0, ![[VAR]], !DIExpression(), debug-location ![[VAR_LOC]]
+ ; CHECK: $eax = COPY %0, debug-location ![[RET_LOC:[0-9]+]]
+ ; CHECK: RET64 $eax, debug-location ![[RET_LOC]]
%0 = COPY $edi
DBG_VALUE _, 0, !12, !DIExpression(), debug-location !13
; Test whether debug-use is still recognized for compatibility with old
@@ -99,9 +99,9 @@ body: |
liveins: $edi
%0 = COPY $edi
- ; CHECK: DBG_VALUE $noreg, i32 0, !11, !DIExpression()
- ; CHECK-NEXT: DBG_VALUE $noreg, i64 -22, !11, !DIExpression()
- ; CHECK-NEXT: DBG_VALUE $noreg, i128 123492148938512984928424384934328985928, !11, !DIExpression()
+ ; CHECK: DBG_VALUE $noreg, i32 0, ![[VAR]], !DIExpression()
+ ; CHECK-NEXT: DBG_VALUE $noreg, i64 -22, ![[VAR]], !DIExpression()
+ ; CHECK-NEXT: DBG_VALUE $noreg, i128 123492148938512984928424384934328985928, ![[VAR]], !DIExpression()
DBG_VALUE _, i32 0, !12, !DIExpression(), debug-location !13
DBG_VALUE _, i64 -22, !12, !DIExpression(), debug-location !13
DBG_VALUE _, i128 123492148938512984928424384934328985928, !12, !DIExpression(), debug-location !13
diff --git a/llvm/test/CodeGen/MIR/X86/machine-metadata.mir b/llvm/test/CodeGen/MIR/X86/machine-metadata.mir
index 47929752f1af8..cb782c88b40b4 100644
--- a/llvm/test/CodeGen/MIR/X86/machine-metadata.mir
+++ b/llvm/test/CodeGen/MIR/X86/machine-metadata.mir
@@ -76,12 +76,12 @@ body: |
; CHECK-LABEL: name: test_memcpy
; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rsi
; CHECK: [[COPY1:%[0-9]+]]:gr64 = COPY $rdi
- ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 16, $noreg :: (load (s64) from %ir.p1, align 4, !alias.scope !5, !noalias !8)
- ; CHECK: [[MOV64rm1:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 24, $noreg :: (load (s64) from %ir.p1 + 8, align 4, !alias.scope !5, !noalias !8)
- ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 8, $noreg, killed [[MOV64rm1]] :: (store (s64) into %ir.p0 + 8, align 4, !alias.scope !10, !noalias !11)
- ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 0, $noreg, killed [[MOV64rm]] :: (store (s64) into %ir.p0, align 4, !alias.scope !10, !noalias !11)
- ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load (s32) from %ir.q, !alias.scope !3, !noalias !0)
- ; CHECK: [[ADD32rm:%[0-9]+]]:gr32 = ADD32rm [[MOV32rm]], [[COPY]], 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load (s32) from %ir.q1, !alias.scope !3, !noalias !0)
+ ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 16, $noreg :: (load (s64) from %ir.p1, align 4, !alias.scope ![[MEMCPY_LOAD_SCOPE:[0-9]+]], !noalias ![[MEMCPY_LOAD_NOALIAS:[0-9]+]])
+ ; CHECK: [[MOV64rm1:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 24, $noreg :: (load (s64) from %ir.p1 + 8, align 4, !alias.scope ![[MEMCPY_LOAD_SCOPE]], !noalias ![[MEMCPY_LOAD_NOALIAS]])
+ ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 8, $noreg, killed [[MOV64rm1]] :: (store (s64) into %ir.p0 + 8, align 4, !alias.scope ![[MEMCPY_STORE_SCOPE:[0-9]+]], !noalias ![[MEMCPY_STORE_NOALIAS:[0-9]+]])
+ ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 0, $noreg, killed [[MOV64rm]] :: (store (s64) into %ir.p0, align 4, !alias.scope ![[MEMCPY_STORE_SCOPE]], !noalias ![[MEMCPY_STORE_NOALIAS]])
+ ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load (s32) from %ir.q, !alias.scope ![[IR_SCOPE:[0-9]+]], !noalias ![[IR_NOALIAS:[0-9]+]])
+ ; CHECK: [[ADD32rm:%[0-9]+]]:gr32 = ADD32rm [[MOV32rm]], [[COPY]], 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load (s32) from %ir.q1, !alias.scope ![[IR_SCOPE]], !noalias ![[IR_NOALIAS]])
; CHECK: $eax = COPY [[ADD32rm]]
; CHECK: RET 0, $eax
%1:gr64 = COPY $rsi
@@ -113,12 +113,12 @@ body: |
; CHECK-LABEL: name: test_memcpy_inline
; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rsi
; CHECK: [[COPY1:%[0-9]+]]:gr64 = COPY $rdi
- ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 16, $noreg :: (load (s64) from %ir.p1, align 4, !alias.scope !5, !noalias !8)
- ; CHECK: [[MOV64rm1:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 24, $noreg :: (load (s64) from %ir.p1 + 8, align 4, !alias.scope !5, !noalias !8)
- ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 8, $noreg, killed [[MOV64rm1]] :: (store (s64) into %ir.p0 + 8, align 4, !alias.scope !10, !noalias !11)
- ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 0, $noreg, killed [[MOV64rm]] :: (store (s64) into %ir.p0, align 4, !alias.scope !10, !noalias !11)
- ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load (s32) from %ir.q, !alias.scope !3, !noalias !0)
- ; CHECK: [[ADD32rm:%[0-9]+]]:gr32 = ADD32rm [[MOV32rm]], [[COPY]], 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load (s32) from %ir.q1, !alias.scope !3, !noalias !0)
+ ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 16, $noreg :: (load (s64) from %ir.p1, align 4, !alias.scope ![[INLINE_LOAD_SCOPE:[0-9]+]], !noalias ![[INLINE_LOAD_NOALIAS:[0-9]+]])
+ ; CHECK: [[MOV64rm1:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 24, $noreg :: (load (s64) from %ir.p1 + 8, align 4, !alias.scope ![[INLINE_LOAD_SCOPE]], !noalias ![[INLINE_LOAD_NOALIAS]])
+ ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 8, $noreg, killed [[MOV64rm1]] :: (store (s64) into %ir.p0 + 8, align 4, !alias.scope ![[INLINE_STORE_SCOPE:[0-9]+]], !noalias ![[INLINE_STORE_NOALIAS:[0-9]+]])
+ ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 0, $noreg, killed [[MOV64rm]] :: (store (s64) into %ir.p0, align 4, !alias.scope ![[INLINE_STORE_SCOPE]], !noalias ![[INLINE_STORE_NOALIAS]])
+ ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load (s32) from %ir.q, !alias.scope ![[IR_SCOPE]], !noalias ![[IR_NOALIAS]])
+ ; CHECK: [[ADD32rm:%[0-9]+]]:gr32 = ADD32rm [[MOV32rm]], [[COPY]], 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load (s32) from %ir.q1, !alias.scope ![[IR_SCOPE]], !noalias ![[IR_NOALIAS]])
; CHECK: $eax = COPY [[ADD32rm]]
; CHECK: RET 0, $eax
%1:gr64 = COPY $rsi
@@ -150,12 +150,12 @@ body: |
; CHECK-LABEL: name: test_mempcpy
; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rsi
; CHECK: [[COPY1:%[0-9]+]]:gr64 = COPY $rdi
- ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 16, $noreg :: (load (s64) from %ir.p1, align 1, !alias.scope !5, !noalias !8)
- ; CHECK: [[MOV64rm1:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 24, $noreg :: (load (s64) from %ir.p1 + 8, align 1, !alias.scope !5, !noalias !8)
- ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 8, $noreg, killed [[MOV64rm1]] :: (store (s64) into %ir.p0 + 8, align 1, !alias.scope !10, !noalias !11)
- ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 0, $noreg, killed [[MOV64rm]] :: (store (s64) into %ir.p0, align 1, !alias.scope !10, !noalias !11)
- ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load (s32) from %ir.q, !alias.scope !3, !noalias !0)
- ; CHECK: [[ADD32rm:%[0-9]+]]:gr32 = ADD32rm [[MOV32rm]], [[COPY]], 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load (s32) from %ir.q1, !alias.scope !3, !noalias !0)
+ ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 16, $noreg :: (load (s64) from %ir.p1, align 1, !alias.scope ![[MEMPCPY_LOAD_SCOPE:[0-9]+]], !noalias ![[MEMPCPY_LOAD_NOALIAS:[0-9]+]])
+ ; CHECK: [[MOV64rm1:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 24, $noreg :: (load (s64) from %ir.p1 + 8, align 1, !alias.scope ![[MEMPCPY_LOAD_SCOPE]], !noalias ![[MEMPCPY_LOAD_NOALIAS]])
+ ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 8, $noreg, killed [[MOV64rm1]] :: (store (s64) into %ir.p0 + 8, align 1, !alias.scope ![[MEMPCPY_STORE_SCOPE:[0-9]+]], !noalias ![[MEMPCPY_STORE_NOALIAS:[0-9]+]])
+ ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 0, $noreg, killed [[MOV64rm]] :: (store (s64) into %ir.p0, align 1, !alias.scope ![[MEMPCPY_STORE_SCOPE]], !noalias ![[MEMPCPY_STORE_NOALIAS]])
+ ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load (s32) from %ir.q, !alias.scope ![[IR_SCOPE]], !noalias ![[IR_NOALIAS]])
+ ; CHECK: [[ADD32rm:%[0-9]+]]:gr32 = ADD32rm [[MOV32rm]], [[COPY]], 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load (s32) from %ir.q1, !alias.scope ![[IR_SCOPE]], !noalias ![[IR_NOALIAS]])
; CHECK: $eax = COPY [[ADD32rm]]
; CHECK: RET 0, $eax
%1:gr64 = COPY $rsi
diff --git a/llvm/test/CodeGen/MIR/X86/mem-cache-hint.mir b/llvm/test/CodeGen/MIR/X86/mem-cache-hint.mir
index 196307e14ef1d..f59023de10e77 100644
--- a/llvm/test/CodeGen/MIR/X86/mem-cache-hint.mir
+++ b/llvm/test/CodeGen/MIR/X86/mem-cache-hint.mir
@@ -28,9 +28,9 @@ body: |
; CHECK: liveins: $rdi, $esi
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:gr64 = COPY $rdi
- ; CHECK-NEXT: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load (s32) from %ir.p, !mem.cache_hint !0)
+ ; CHECK-NEXT: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load (s32) from %ir.p, !mem.cache_hint !{{[0-9]+}})
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr32 = COPY $esi
- ; CHECK-NEXT: MOV32mr [[COPY]], 1, $noreg, 0, $noreg, [[COPY1]] :: (store (s32) into %ir.p, !mem.cache_hint !2)
+ ; CHECK-NEXT: MOV32mr [[COPY]], 1, $noreg, 0, $noreg, [[COPY1]] :: (store (s32) into %ir.p, !mem.cache_hint !{{[0-9]+}})
; CHECK-NEXT: $eax = COPY [[MOV32rm]]
; CHECK-NEXT: RET 0, $eax
%0:gr64 = COPY $rdi
diff --git a/llvm/test/CodeGen/MIR/X86/memory-operands.mir b/llvm/test/CodeGen/MIR/X86/memory-operands.mir
index 60a5a4b192aed..b738dd9b12b51 100644
--- a/llvm/test/CodeGen/MIR/X86/memory-operands.mir
+++ b/llvm/test/CodeGen/MIR/X86/memory-operands.mir
@@ -459,8 +459,8 @@ body: |
bb.0.entry:
$rax = MOV64rm $rip, 1, _, @a, _ :: (load (s64) from got)
; CHECK-LABEL: name: tbaa_metadata
- ; CHECK: $eax = MOV32rm killed $rax, 1, $noreg, 0, $noreg, implicit-def $rax :: (load (s32) from @a, !tbaa !2)
- ; CHECK-NEXT: $eax = MOV32rm killed $rax, 1, $noreg, 0, $noreg :: (load (s32) from %ir.1, !tbaa !6)
+ ; CHECK: $eax = MOV32rm killed $rax, 1, $noreg, 0, $noreg, implicit-def $rax :: (load (s32) from @a, !tbaa !{{[0-9]+}})
+ ; CHECK-NEXT: $eax = MOV32rm killed $rax, 1, $noreg, 0, $noreg :: (load (s32) from %ir.1, !tbaa !{{[0-9]+}})
$eax = MOV32rm killed $rax, 1, _, 0, _, implicit-def $rax :: (load (s32) from @a, !tbaa !2)
$eax = MOV32rm killed $rax, 1, _, 0, _ :: (load (s32) from %ir.1, !tbaa !6)
RET64 $eax
@@ -475,9 +475,9 @@ body: |
bb.0.entry:
liveins: $rdi, $rsi
; CHECK-LABEL: name: aa_scope
- ; CHECK: $xmm0 = MOVSSrm_alt $rsi, 1, $noreg, 0, $noreg :: (load (s32) from %ir.c, !alias.scope !9)
+ ; CHECK: $xmm0 = MOVSSrm_alt $rsi, 1, $noreg, 0, $noreg :: (load (s32) from %ir.c, !alias.scope ![[AA_SCOPE:[0-9]+]])
$xmm0 = MOVSSrm_alt $rsi, 1, _, 0, _ :: (load (s32) from %ir.c, !alias.scope !9)
- ; CHECK-NEXT: MOVSSmr $rdi, 1, $noreg, 20, $noreg, killed $xmm0 :: (store (s32) into %ir.arrayidx.i, !noalias !9)
+ ; CHECK-NEXT: MOVSSmr $rdi, 1, $noreg, 20, $noreg, killed $xmm0 :: (store (s32) into %ir.arrayidx.i, !noalias ![[AA_SCOPE]])
MOVSSmr $rdi, 1, _, 20, _, killed $xmm0 :: (store (s32) into %ir.arrayidx.i, !noalias !9)
$xmm0 = MOVSSrm_alt killed $rsi, 1, _, 0, _ :: (load (s32) from %ir.c)
MOVSSmr killed $rdi, 1, _, 28, _, killed $xmm0 :: (store (s32) into %ir.arrayidx)
@@ -492,7 +492,7 @@ body: |
bb.0.entry:
liveins: $rdi
; CHECK-LABEL: name: range_metadata
- ; CHECK: $al = MOV8rm killed $rdi, 1, $noreg, 0, $noreg :: (load (s8) from %ir.x, !range !11, !mem.cache_hint !12)
+ ; CHECK: $al = MOV8rm killed $rdi, 1, $noreg, 0, $noreg :: (load (s8) from %ir.x, !range !{{[0-9]+}}, !mem.cache_hint !{{[0-9]+}})
$al = MOV8rm killed $rdi, 1, _, 0, _ :: (load (s8) from %ir.x, !range !11, !mem.cache_hint !12)
RET64 $al
...
diff --git a/llvm/test/CodeGen/MIR/X86/metadata-operands.mir b/llvm/test/CodeGen/MIR/X86/metadata-operands.mir
index c80af7dd6501c..063b04e828b24 100644
--- a/llvm/test/CodeGen/MIR/X86/metadata-operands.mir
+++ b/llvm/test/CodeGen/MIR/X86/metadata-operands.mir
@@ -51,7 +51,7 @@ body: |
bb.0.entry:
liveins: $edi
; CHECK: %0:gr32 = COPY $edi
- ; CHECK-NEXT: DBG_VALUE $noreg, 0, !11, !DIExpression()
+ ; CHECK-NEXT: DBG_VALUE $noreg, 0, !{{[0-9]+}}, !DIExpression()
%0 = COPY $edi
DBG_VALUE _, 0, !12, !DIExpression(), debug-location !13
MOV32mr %stack.0.x.addr, 1, _, 0, _, %0
diff --git a/llvm/test/CodeGen/MIR/X86/pr38773.mir b/llvm/test/CodeGen/MIR/X86/pr38773.mir
index 1d4be4b23f400..32b175775f63a 100644
--- a/llvm/test/CodeGen/MIR/X86/pr38773.mir
+++ b/llvm/test/CodeGen/MIR/X86/pr38773.mir
@@ -97,14 +97,14 @@ body: |
IDIV32r killed renamable $ecx, implicit-def $eax, implicit-def dead $edx, implicit-def dead $eflags, implicit $eax, implicit killed $edx
renamable $ecx = COPY $eax
; CHECK: IDIV32r killed renamable $ecx
- ; CHECK-NEXT: DBG_VALUE $eax, $noreg, !12, !DIExpression(), debug-location !13
+ ; CHECK-NEXT: DBG_VALUE $eax, $noreg, ![[VAR:[0-9]+]], !DIExpression(), debug-location ![[LOC:[0-9]+]]
DBG_VALUE $ecx, $noreg, !12, !DIExpression(), debug-location !13
; The following mov and DBG_VALUE have been inserted after the PR was
; resolved to check that MCP will update debug users that are not
; immediately after the dead copy.
; CHECK-NEXT: $edx = MOV32r0
$edx = MOV32r0 implicit-def dead $eflags
- ; CHECK-NEXT: DBG_VALUE $eax, $noreg, !12, !DIExpression(), debug-location !13
+ ; CHECK-NEXT: DBG_VALUE $eax, $noreg, ![[VAR]], !DIExpression(), debug-location ![[LOC]]
DBG_VALUE $ecx, $noreg, !12, !DIExpression(), debug-location !13
$eax = COPY killed renamable $ecx
RET 0, $eax
diff --git a/llvm/test/CodeGen/MIR/X86/stack-object-debug-info.mir b/llvm/test/CodeGen/MIR/X86/stack-object-debug-info.mir
index 416f8cfbaed0a..c34622fe8512a 100644
--- a/llvm/test/CodeGen/MIR/X86/stack-object-debug-info.mir
+++ b/llvm/test/CodeGen/MIR/X86/stack-object-debug-info.mir
@@ -54,8 +54,8 @@ frameInfo:
# CHECK: stack:
# CHECK: - { id: 0, name: y.i, type: default, offset: 0, size: 256, alignment: 16,
# CHECK-NEXT: callee-saved-register: '', callee-saved-restored: true,
-# CHECK-NEXT: debug-info-variable: '!4', debug-info-expression: '!DIExpression()',
-# CHECK-NEXT: debug-info-location: '!12' }
+# CHECK-NEXT: debug-info-variable: '!{{[0-9]+}}', debug-info-expression: '!DIExpression()',
+# CHECK-NEXT: debug-info-location: '!{{[0-9]+}}' }
stack:
- { id: 0, name: y.i, offset: 0, size: 256, alignment: 16,
debug-info-variable: '!4', debug-info-expression: '!DIExpression()',
diff --git a/llvm/test/DebugInfo/MIR/AArch64/no-dbg-value-after-terminator.mir b/llvm/test/DebugInfo/MIR/AArch64/no-dbg-value-after-terminator.mir
index 34c099f27becb..586e5abc16e8b 100644
--- a/llvm/test/DebugInfo/MIR/AArch64/no-dbg-value-after-terminator.mir
+++ b/llvm/test/DebugInfo/MIR/AArch64/no-dbg-value-after-terminator.mir
@@ -5,7 +5,7 @@
# CHECK-NEXT: - function: f1
# CHECK-NEXT: - basic block: %bb.0
# CHECK-NEXT: - instruction: DBG_VALUE $noreg, $noreg, !"1", !DIExpression(DW_OP_LLVM_entry_value, 1)
-# CHECK-NEXT: First terminator was: RET undef $lr, debug-location !12; /tmp/foo.ll:2:1
+# CHECK-NEXT: First terminator was: RET undef $lr, debug-location !26; /tmp/foo.ll:2:1
--- |
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
diff --git a/llvm/test/Other/legacy-callgraph-scc-pass-printer.ll b/llvm/test/Other/legacy-callgraph-scc-pass-printer.ll
index fda04f6740575..341584508ea79 100644
--- a/llvm/test/Other/legacy-callgraph-scc-pass-printer.ll
+++ b/llvm/test/Other/legacy-callgraph-scc-pass-printer.ll
@@ -1,11 +1,22 @@
; RUN: llc -mtriple=x86_64-unknown-linux-gnu -enable-ipra \
; RUN: -print-after=DummyCGSCCPass -o - %s 2>&1 | FileCheck %s
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -enable-ipra \
+; RUN: -print-after=DummyCGSCCPass -print-module-scope -o - %s 2>&1 \
+; RUN: | FileCheck %s --check-prefix=PERSISTENT
; REQUIRES: x86-registered-target
; The legacy CallGraphSCCPass printer should emit the banner as its own line.
; CHECK-LABEL: *** IR Dump After DummyCGSCCPass (DummyCGSCCPass) ***
; CHECK-NEXT: define void @bar() {
+; PERSISTENT-LABEL: *** IR Dump After DummyCGSCCPass (DummyCGSCCPass) ***
+; PERSISTENT: define void @bar() {
+; PERSISTENT: ret void, !annotation ![[USED:[0-9]+]]
+; PERSISTENT: ![[USED]] = !{!"used"}
+
define void @bar() {
- ret void
+ ret void, !annotation !1
}
+
+!0 = !{!"unused"}
+!1 = !{!"used"}
diff --git a/llvm/test/Other/print-changed-persistent-metadata-ids.ll b/llvm/test/Other/print-changed-persistent-metadata-ids.ll
new file mode 100644
index 0000000000000..01cb0eb3fb548
--- /dev/null
+++ b/llvm/test/Other/print-changed-persistent-metadata-ids.ll
@@ -0,0 +1,77 @@
+; RUN: opt -passes=instsimplify -filter-print-funcs=second \
+; RUN: -print-changed=quiet -disable-output < %s 2>&1 | FileCheck %s --check-prefix=CHANGED
+; RUN: opt -passes=instsimplify -filter-print-funcs=second \
+; RUN: -print-before=instsimplify -print-after=instsimplify \
+; RUN: -disable-output < %s 2>&1 | FileCheck %s --check-prefix=STABLE
+; RUN: opt -passes='function(instsimplify),globaldce' -filter-print-funcs=second \
+; RUN: -print-changed=quiet -print-module-scope -disable-output < %s 2>&1 \
+; RUN: | FileCheck %s --check-prefix=CROSS-KIND
+; RUN: opt -passes='function(instsimplify),print' -disable-output < %s 2> %t
+; RUN: FileCheck %s --check-prefix=SPARSE < %t
+; RUN: opt -disable-output < %t
+; RUN: opt -S -passes='function(instsimplify)' < %s \
+; RUN: | FileCheck %s --check-prefix=COMPACT
+
+declare i32 @opaque(i32)
+
+ at dead = internal global i32 0
+
+define i32 @first(i32 %arg) #0 {
+ %keep = call i32 @opaque(i32 %arg)
+ ret i32 %keep
+}
+
+define i32 @second(i32 %arg) #1 {
+ %constant = add i32 2, 3, !annotation !0
+ %keep = call i32 @opaque(i32 %arg), !annotation !1, !other !3
+ %result = add i32 %keep, %constant
+ ret i32 %result
+}
+
+!0 = !{!"removed metadata"}
+!1 = !{!2}
+!2 = !{!"second metadata"}
+!3 = !{!"other metadata"}
+
+attributes #0 = { nounwind }
+attributes #1 = { noinline }
+
+; CHANGED: *** IR Dump After InstSimplifyPass on second ***
+; CHANGED: define i32 @second(i32 %arg) #1 {
+; CHANGED: %keep = call i32 @opaque(i32 %arg)
+; CHANGED-SAME: !annotation ![[ANNOTATION:[0-9]+]], !other ![[OTHER:[0-9]+]]
+
+; STABLE: *** IR Dump Before InstSimplifyPass on second ***
+; STABLE: %constant = add i32 2, 3, !annotation !{{[0-9]+}}
+; STABLE: %keep = call i32 @opaque(i32 %arg)
+; STABLE-SAME: !annotation ![[STABLE_ANNOTATION:[0-9]+]], !other ![[STABLE_OTHER:[0-9]+]]
+; STABLE: *** IR Dump After InstSimplifyPass on second ***
+; STABLE-NOT: %constant
+; STABLE: %keep = call i32 @opaque(i32 %arg)
+; STABLE-SAME: !annotation ![[STABLE_ANNOTATION]], !other ![[STABLE_OTHER]]
+
+; CROSS-KIND: *** IR Dump After InstSimplifyPass on second ***
+; CROSS-KIND: @dead = internal global i32 0
+; CROSS-KIND: define i32 @second(i32 %arg) #1 {
+; CROSS-KIND: %keep = call i32 @opaque(i32 %arg)
+; CROSS-KIND-SAME: !annotation ![[CROSS_ANNOTATION:[0-9]+]], !other ![[CROSS_OTHER:[0-9]+]]
+; CROSS-KIND: *** IR Dump After GlobalDCEPass on [module] ***
+; CROSS-KIND-NOT: @dead
+; CROSS-KIND: define i32 @second(i32 %arg) #1 {
+; CROSS-KIND: %keep = call i32 @opaque(i32 %arg)
+; CROSS-KIND-SAME: !annotation ![[CROSS_ANNOTATION]], !other ![[CROSS_OTHER]]
+
+; SPARSE: define i32 @second(i32 %arg) #1 {
+; SPARSE: %keep = call i32 @opaque(i32 %arg)
+; SPARSE-SAME: !annotation ![[SPARSE_ANNOTATION:[1-9][0-9]*]], !other ![[SPARSE_OTHER:[0-9]+]]
+; SPARSE-NOT: !0 =
+; SPARSE: ![[SPARSE_ANNOTATION]] = !{![[SPARSE_NESTED:[0-9]+]]}
+; SPARSE-DAG: ![[SPARSE_NESTED]] = !{!"second metadata"}
+; SPARSE-DAG: ![[SPARSE_OTHER]] = !{!"other metadata"}
+
+; COMPACT: define i32 @second(i32 %arg) #1 {
+; COMPACT: %keep = call i32 @opaque(i32 %arg)
+; COMPACT-SAME: !annotation !0, !other !2
+; COMPACT: !0 = !{!1}
+; COMPACT: !1 = !{!"second metadata"}
+; COMPACT: !2 = !{!"other metadata"}
diff --git a/llvm/test/Other/print-persistent-metadata-ids.ll b/llvm/test/Other/print-persistent-metadata-ids.ll
new file mode 100644
index 0000000000000..79ae153353d02
--- /dev/null
+++ b/llvm/test/Other/print-persistent-metadata-ids.ll
@@ -0,0 +1,94 @@
+; RUN: opt -S -passes=no-op-module < %s | FileCheck %s --check-prefix=COMPACT
+; RUN: opt -disable-output -passes=print < %s 2>&1 | FileCheck %s --check-prefix=PERSISTENT-MODULE
+; RUN: opt -disable-output -passes=print < %s 2> %t
+; RUN: opt -disable-output < %t
+; RUN: opt -disable-output -passes='function(print)' -filter-print-funcs=second \
+; RUN: < %s 2>&1 | FileCheck %s --check-prefix=PERSISTENT-FUNCTION
+; RUN: opt -disable-output -passes='function(no-op-function)' \
+; RUN: -print-before=no-op-function -filter-print-funcs=second \
+; RUN: < %s 2>&1 | FileCheck %s --check-prefix=PERSISTENT-FUNCTION
+; RUN: opt -disable-output -passes='function(no-op-function)' -print-after-all \
+; RUN: -filter-print-funcs=second < %s 2>&1 | FileCheck %s --check-prefix=PERSISTENT-FUNCTION
+; RUN: opt -disable-output -passes=no-op-module -print-before=no-op-module \
+; RUN: -filter-print-funcs=first,second < %s 2>&1 | FileCheck %s --check-prefix=PERSISTENT-MULTI
+; RUN: opt -disable-output -passes='loop(no-op-loop)' -print-before=no-op-loop \
+; RUN: -filter-print-funcs=loop < %s 2>&1 | FileCheck %s --check-prefix=PERSISTENT-LOOP
+; RUN: opt -disable-output -passes='print,function(print)' < %s 2>&1 | FileCheck %s --check-prefix=SAME-ID
+$group = comdat any
+
+ at named = global ptr @0, comdat($group), !annotation !5
+ at 0 = global i32 0
+ at 1 = global i32 1
+
+declare void @callee(ptr)
+
+define void @first() #0 {
+ call void @callee(ptr @0) #1
+ call void @callee(ptr @1) #1
+ ret void, !annotation !1
+}
+
+define void @second() {
+ call void @callee(ptr @1) #1, !annotation !3
+ ret void, !annotation !3
+}
+
+define void @loop() {
+entry:
+ call void @callee(ptr @0) #1
+ call void @callee(ptr @1) #1
+ br label %loop
+
+loop:
+ call void @callee(ptr @1) #1
+ br i1 false, label %loop, label %exit
+
+exit:
+ ret void
+}
+
+attributes #0 = { noinline }
+attributes #1 = { nounwind }
+
+!named = !{!0}
+!0 = !{!"named metadata"}
+!1 = !{!2}
+!2 = !{!"first metadata"}
+!3 = !{!4}
+!4 = !{!"second metadata"}
+!5 = !{!6}
+!6 = !{!"global metadata"}
+
+; COMPACT: @named = global ptr @0, comdat($group), !annotation !0
+; COMPACT: ret void, !annotation !3
+; COMPACT: call void @callee(ptr @1) #1, !annotation !5
+; COMPACT: ret void, !annotation !5
+; COMPACT: !named = !{!2}
+
+; PERSISTENT-MODULE: @named = global ptr @0, comdat($group), !annotation ![[GLOBAL:[0-9]+]]
+; PERSISTENT-MODULE: ret void, !annotation ![[FIRST:[0-9]+]]
+; PERSISTENT-MODULE: call void @callee(ptr @1) #1, !annotation ![[SECOND:[0-9]+]]
+; PERSISTENT-MODULE: ret void, !annotation ![[SECOND]]
+; PERSISTENT-MODULE: !named = !{![[NAMED:[0-9]+]]}
+
+; PERSISTENT-FUNCTION: define void @second() {
+; PERSISTENT-FUNCTION: call void @callee(ptr @1) #1, !annotation ![[SECOND:[0-9]+]]
+; PERSISTENT-FUNCTION: ret void, !annotation ![[SECOND]]
+
+; PERSISTENT-MULTI: define void @first() #0 {
+; PERSISTENT-MULTI: call void @callee(ptr @0) #1
+; PERSISTENT-MULTI: call void @callee(ptr @1) #1
+; PERSISTENT-MULTI: define void @second() {
+; PERSISTENT-MULTI: call void @callee(ptr @1) #1
+
+; PERSISTENT-LOOP: ; Preheader:
+; PERSISTENT-LOOP: call void @callee(ptr @0) #1
+; PERSISTENT-LOOP: call void @callee(ptr @1) #1
+; PERSISTENT-LOOP: ; Loop:
+; PERSISTENT-LOOP: call void @callee(ptr @1) #1
+
+; SAME-ID: define void @second() {
+; SAME-ID: call void @callee(ptr @1) #1, !annotation ![[SAME_SECOND:[0-9]+]]
+; SAME-ID: ![[SAME_SECOND]] = !{!{{[0-9]+}}}
+; SAME-ID: define void @second() {
+; SAME-ID: call void @callee(ptr @1) #1, !annotation ![[SAME_SECOND]]
diff --git a/llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-distribute.ll.expected b/llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-distribute.ll.expected
index b2cd7cc79a70c..e3e62c44f6ce4 100644
--- a/llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-distribute.ll.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-distribute.ll.expected
@@ -72,12 +72,12 @@ define void @ldist(i1 %cond, ptr %A, ptr %B, ptr %C) {
; CHECK-NEXT: LDist: Partition 0:
; CHECK-NEXT: for.body.ldist1: ; preds = %if.end.ldist1, %for.body.ph.ldist1
; CHECK-NEXT: %iv.ldist1 = phi i16 [ 0, %for.body.ph.ldist1 ], [ %iv.next.ldist1, %if.end.ldist1 ]
-; CHECK-NEXT: %lv.ldist1 = load i16, ptr %A, align 1, !alias.scope !2, !noalias !5
-; CHECK-NEXT: store i16 %lv.ldist1, ptr %A, align 1, !alias.scope !2, !noalias !5
+; CHECK-NEXT: %lv.ldist1 = load i16, ptr %A, align 1, !alias.scope !5, !noalias !4
+; CHECK-NEXT: store i16 %lv.ldist1, ptr %A, align 1, !alias.scope !5, !noalias !4
; CHECK-NEXT: br i1 %cond, label %if.then.ldist1, label %if.end.ldist1
; CHECK-EMPTY:
; CHECK-NEXT: if.then.ldist1: ; preds = %for.body.ldist1
-; CHECK-NEXT: %lv2.ldist1 = load i16, ptr %A, align 1, !alias.scope !2, !noalias !5
+; CHECK-NEXT: %lv2.ldist1 = load i16, ptr %A, align 1, !alias.scope !5, !noalias !4
; CHECK-NEXT: br label %if.end.ldist1
; CHECK-EMPTY:
; CHECK-NEXT: if.end.ldist1: ; preds = %if.then.ldist1, %for.body.ldist1
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/IR/01-ir-print-basic-details.test b/llvm/test/tools/llvm-debuginfo-analyzer/IR/01-ir-print-basic-details.test
index 51a807942c48e..b11128d164ea7 100644
--- a/llvm/test/tools/llvm-debuginfo-analyzer/IR/01-ir-print-basic-details.test
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/IR/01-ir-print-basic-details.test
@@ -40,11 +40,11 @@
; ONE-NEXT: [003] {Block}
; ONE-NEXT: [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
; ONE-NEXT: [004] 5 {Line}
-; ONE-NEXT: [004] {Code} 'store i32 7, ptr %CONSTANT, align 4, !dbg !32'
+; ONE-NEXT: [004] {Code} 'store i32 7, ptr %CONSTANT, align 4, !dbg !{{[0-9]+}}'
; ONE-NEXT: [004] 6 {Line}
-; ONE-NEXT: [004] {Code} 'store i32 7, ptr %retval, align 4, !dbg !33'
+; ONE-NEXT: [004] {Code} 'store i32 7, ptr %retval, align 4, !dbg !{{[0-9]+}}'
; ONE-NEXT: [004] 6 {Line}
-; ONE-NEXT: [004] {Code} 'br label %return, !dbg !33'
+; ONE-NEXT: [004] {Code} 'br label %return, !dbg !{{[0-9]+}}'
; ONE-NEXT: [003] 2 {Parameter} 'ParamPtr' -> 'INTPTR'
; ONE-NEXT: [003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int'
; ONE-NEXT: [003] 2 {Parameter} 'ParamBool' -> 'bool'
@@ -60,19 +60,19 @@
; ONE-NEXT: [003] {Code} '%storedv = zext i1 %ParamBool to i8'
; ONE-NEXT: [003] {Code} 'store i8 %storedv, ptr %ParamBool.addr, align 1'
; ONE-NEXT: [003] 8 {Line}
-; ONE-NEXT: [003] {Code} '%1 = load i32, ptr %ParamUnsigned.addr, align 4, !dbg !34'
+; ONE-NEXT: [003] {Code} '%1 = load i32, ptr %ParamUnsigned.addr, align 4, !dbg !{{[0-9]+}}'
; ONE-NEXT: [003] 8 {Line}
-; ONE-NEXT: [003] {Code} 'store i32 %1, ptr %retval, align 4, !dbg !35'
+; ONE-NEXT: [003] {Code} 'store i32 %1, ptr %retval, align 4, !dbg !{{[0-9]+}}'
; ONE-NEXT: [003] 8 {Line}
-; ONE-NEXT: [003] {Code} 'br label %return, !dbg !35'
+; ONE-NEXT: [003] {Code} 'br label %return, !dbg !{{[0-9]+}}'
; ONE-NEXT: [003] 9 {Line}
-; ONE-NEXT: [003] {Code} '%2 = load i32, ptr %retval, align 4, !dbg !36'
+; ONE-NEXT: [003] {Code} '%2 = load i32, ptr %retval, align 4, !dbg !{{[0-9]+}}'
; ONE-NEXT: [003] 9 {Line}
-; ONE-NEXT: [003] {Code} 'ret i32 %2, !dbg !36'
+; ONE-NEXT: [003] {Code} 'ret i32 %2, !dbg !{{[0-9]+}}'
; ONE-NEXT: [003] 3 {Line}
-; ONE-NEXT: [003] {Code} '%0 = load i8, ptr %ParamBool.addr, align 1, !dbg !26'
+; ONE-NEXT: [003] {Code} '%0 = load i8, ptr %ParamBool.addr, align 1, !dbg !{{[0-9]+}}'
; ONE-NEXT: [003] 3 {Line}
-; ONE-NEXT: [003] {Code} '%loadedv = trunc i8 %0 to i1, !dbg !26'
+; ONE-NEXT: [003] {Code} '%loadedv = trunc i8 %0 to i1, !dbg !{{[0-9]+}}'
; ONE-NEXT: [003] 3 {Line}
-; ONE-NEXT: [003] {Code} 'br i1 %loadedv, label %if.then, label %if.end, !dbg !26'
+; ONE-NEXT: [003] {Code} 'br i1 %loadedv, label %if.then, label %if.end, !dbg !{{[0-9]+}}'
; ONE-NEXT: [002] 1 {TypeAlias} 'INTPTR' -> '* const int'
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/IR/01-ir-select-logical-elements.test b/llvm/test/tools/llvm-debuginfo-analyzer/IR/01-ir-select-logical-elements.test
index 51bbb30c1d97e..cae4183e7253f 100644
--- a/llvm/test/tools/llvm-debuginfo-analyzer/IR/01-ir-select-logical-elements.test
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/IR/01-ir-select-logical-elements.test
@@ -30,16 +30,16 @@
; ONE-NEXT: [000] {File} 'test-clang.ll'
; ONE-EMPTY:
; ONE-NEXT: [001] {CompileUnit} 'test.cpp'
-; ONE-NEXT: [003] {Code} '%0 = load i8, ptr %ParamBool.addr, align 1, !dbg !26'
-; ONE-NEXT: [003] {Code} '%1 = load i32, ptr %ParamUnsigned.addr, align 4, !dbg !34'
-; ONE-NEXT: [003] {Code} '%2 = load i32, ptr %retval, align 4, !dbg !36'
-; ONE-NEXT: [003] {Code} '%loadedv = trunc i8 %0 to i1, !dbg !26'
+; ONE-NEXT: [003] {Code} '%0 = load i8, ptr %ParamBool.addr, align 1, !dbg !{{[0-9]+}}'
+; ONE-NEXT: [003] {Code} '%1 = load i32, ptr %ParamUnsigned.addr, align 4, !dbg !{{[0-9]+}}'
+; ONE-NEXT: [003] {Code} '%2 = load i32, ptr %retval, align 4, !dbg !{{[0-9]+}}'
+; ONE-NEXT: [003] {Code} '%loadedv = trunc i8 %0 to i1, !dbg !{{[0-9]+}}'
; ONE-NEXT: [003] {Code} '%storedv = zext i1 %ParamBool to i8'
-; ONE-NEXT: [003] {Code} 'br i1 %loadedv, label %if.then, label %if.end, !dbg !26'
-; ONE-NEXT: [003] {Code} 'store i32 %1, ptr %retval, align 4, !dbg !35'
+; ONE-NEXT: [003] {Code} 'br i1 %loadedv, label %if.then, label %if.end, !dbg !{{[0-9]+}}'
+; ONE-NEXT: [003] {Code} 'store i32 %1, ptr %retval, align 4, !dbg !{{[0-9]+}}'
; ONE-NEXT: [003] {Code} 'store i32 %ParamUnsigned, ptr %ParamUnsigned.addr, align 4'
-; ONE-NEXT: [004] {Code} 'store i32 7, ptr %CONSTANT, align 4, !dbg !32'
-; ONE-NEXT: [004] {Code} 'store i32 7, ptr %retval, align 4, !dbg !33'
+; ONE-NEXT: [004] {Code} 'store i32 7, ptr %CONSTANT, align 4, !dbg !{{[0-9]+}}'
+; ONE-NEXT: [004] {Code} 'store i32 7, ptr %retval, align 4, !dbg !{{[0-9]+}}'
; ONE-NEXT: [003] {Code} 'store i8 %storedv, ptr %ParamBool.addr, align 1'
; ONE-NEXT: [003] {Code} 'store ptr %ParamPtr, ptr %ParamPtr.addr, align 8'
; ONE-EMPTY:
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/IR/02-ir-logical-lines.test b/llvm/test/tools/llvm-debuginfo-analyzer/IR/02-ir-logical-lines.test
index 76272e3f677ea..8280d0f41ff6d 100644
--- a/llvm/test/tools/llvm-debuginfo-analyzer/IR/02-ir-logical-lines.test
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/IR/02-ir-logical-lines.test
@@ -33,9 +33,9 @@
; ONE-NEXT: [003] {Code} '%retval = alloca i32, align 4'
; ONE-NEXT: [003] {Code} 'store i32 0, ptr %retval, align 4'
; ONE-NEXT: [003] 5 {Line}
-; ONE-NEXT: [003] {Code} '%call = call noundef i32 (ptr, ...) @_Z6printfPKcz(ptr noundef @.str), !dbg !22'
+; ONE-NEXT: [003] {Code} '%call = call noundef i32 (ptr, ...) @_Z6printfPKcz(ptr noundef @.str), !dbg !{{[0-9]+}}'
; ONE-NEXT: [003] 6 {Line}
-; ONE-NEXT: [003] {Code} 'ret i32 0, !dbg !23'
+; ONE-NEXT: [003] {Code} 'ret i32 0, !dbg !{{[0-9]+}}'
; ONE-EMPTY:
; ONE-NEXT: Logical View:
; ONE-NEXT: [000] {File} 'hello-world-dwarf-clang.o' -> elf64-x86-64
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/IR/06-ir-full-logical-view.test b/llvm/test/tools/llvm-debuginfo-analyzer/IR/06-ir-full-logical-view.test
index 3f6db431a676c..29fc246b27a21 100644
--- a/llvm/test/tools/llvm-debuginfo-analyzer/IR/06-ir-full-logical-view.test
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/IR/06-ir-full-logical-view.test
@@ -51,11 +51,11 @@
; ONE-NEXT: [0x0000000000][006] {Location}
; ONE-NEXT: [0x0000000000][007] {Entry} bregx 3 ptr %CONSTANT+0
; ONE-NEXT: [0x0000000030][004] 5 {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x0000000030][004] {Code} 'store i32 7, ptr %CONSTANT, align 4, !dbg !32'
+; ONE-NEXT: [0x0000000030][004] {Code} 'store i32 7, ptr %CONSTANT, align 4, !dbg !{{[0-9]+}}'
; ONE-NEXT: [0x0000000034][004] 6 {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x0000000034][004] {Code} 'store i32 7, ptr %retval, align 4, !dbg !33'
+; ONE-NEXT: [0x0000000034][004] {Code} 'store i32 7, ptr %retval, align 4, !dbg !{{[0-9]+}}'
; ONE-NEXT: [0x0000000038][004] 6 {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x0000000038][004] {Code} 'br label %return, !dbg !33'
+; ONE-NEXT: [0x0000000038][004] {Code} 'br label %return, !dbg !{{[0-9]+}}'
; ONE-NEXT: [0x0000000014][003] 2 {Parameter} 'ParamPtr' -> [0x0000000028]'INTPTR'
; ONE-NEXT: [0x0000000014][004] {Coverage} 100.00%
; ONE-NEXT: [0x0000000000][004] {Location}
@@ -80,21 +80,21 @@
; ONE-NEXT: [0x000000001c][003] {Code} '%storedv = zext i1 %ParamBool to i8'
; ONE-NEXT: [0x0000000020][003] {Code} 'store i8 %storedv, ptr %ParamBool.addr, align 1'
; ONE-NEXT: [0x000000003c][003] 8 {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x000000003c][003] {Code} '%1 = load i32, ptr %ParamUnsigned.addr, align 4, !dbg !34'
+; ONE-NEXT: [0x000000003c][003] {Code} '%1 = load i32, ptr %ParamUnsigned.addr, align 4, !dbg !{{[0-9]+}}'
; ONE-NEXT: [0x0000000040][003] 8 {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x0000000040][003] {Code} 'store i32 %1, ptr %retval, align 4, !dbg !35'
+; ONE-NEXT: [0x0000000040][003] {Code} 'store i32 %1, ptr %retval, align 4, !dbg !{{[0-9]+}}'
; ONE-NEXT: [0x0000000044][003] 8 {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x0000000044][003] {Code} 'br label %return, !dbg !35'
+; ONE-NEXT: [0x0000000044][003] {Code} 'br label %return, !dbg !{{[0-9]+}}'
; ONE-NEXT: [0x0000000048][003] 9 {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x0000000048][003] {Code} '%2 = load i32, ptr %retval, align 4, !dbg !36'
+; ONE-NEXT: [0x0000000048][003] {Code} '%2 = load i32, ptr %retval, align 4, !dbg !{{[0-9]+}}'
; ONE-NEXT: [0x000000004c][003] 9 {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x000000004c][003] {Code} 'ret i32 %2, !dbg !36'
+; ONE-NEXT: [0x000000004c][003] {Code} 'ret i32 %2, !dbg !{{[0-9]+}}'
; ONE-NEXT: [0x0000000024][003] 3 {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x0000000024][003] {Code} '%0 = load i8, ptr %ParamBool.addr, align 1, !dbg !26'
+; ONE-NEXT: [0x0000000024][003] {Code} '%0 = load i8, ptr %ParamBool.addr, align 1, !dbg !{{[0-9]+}}'
; ONE-NEXT: [0x0000000028][003] 3 {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x0000000028][003] {Code} '%loadedv = trunc i8 %0 to i1, !dbg !26'
+; ONE-NEXT: [0x0000000028][003] {Code} '%loadedv = trunc i8 %0 to i1, !dbg !{{[0-9]+}}'
; ONE-NEXT: [0x000000002c][003] 3 {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x000000002c][003] {Code} 'br i1 %loadedv, label %if.then, label %if.end, !dbg !26'
+; ONE-NEXT: [0x000000002c][003] {Code} 'br i1 %loadedv, label %if.then, label %if.end, !dbg !{{[0-9]+}}'
; ONE-NEXT: [0x0000000024][002] {BaseType} 'int'
; ONE-NEXT: [0x0000000028][002] 1 {TypeAlias} 'INTPTR' -> [0x000000002c]'* const int'
; ONE-NEXT: [0x0000000034][002] {BaseType} 'unsigned int'
diff --git a/llvm/tools/llvm-dis/llvm-dis.cpp b/llvm/tools/llvm-dis/llvm-dis.cpp
index a961f9cb0f7dd..2a986fc145fbf 100644
--- a/llvm/tools/llvm-dis/llvm-dis.cpp
+++ b/llvm/tools/llvm-dis/llvm-dis.cpp
@@ -263,6 +263,7 @@ int main(int argc, char **argv) {
// All that llvm-dis does is write the assembly to a file.
if (!DontPrint) {
if (M) {
+ M->renumberMetadataForAssembly();
M->print(Out->os(), Annotator.get(),
/* ShouldPreserveUseListOrder */ false);
}
diff --git a/llvm/tools/llvm-extract/llvm-extract.cpp b/llvm/tools/llvm-extract/llvm-extract.cpp
index 439a4a48b350a..17ce664a64ba2 100644
--- a/llvm/tools/llvm-extract/llvm-extract.cpp
+++ b/llvm/tools/llvm-extract/llvm-extract.cpp
@@ -411,8 +411,10 @@ int main(int argc, char **argv) {
}
if (OutputAssembly)
- PM.addPass(
- PrintModulePass(Out.os(), "", /* ShouldPreserveUseListOrder */ false));
+ PM.addPass(PrintModulePass(Out.os(), "",
+ /*ShouldPreserveUseListOrder=*/false,
+ /*EmitSummaryIndex=*/false,
+ /*ShouldRenumberMetadata=*/true));
else if (Force || !CheckBitcodeOutputToConsole(Out.os()))
PM.addPass(
BitcodeWriterPass(Out.os(), /* ShouldPreserveUseListOrder */ true));
diff --git a/llvm/tools/llvm-link/llvm-link.cpp b/llvm/tools/llvm-link/llvm-link.cpp
index e49082f2d7bfb..9390301f1b75a 100644
--- a/llvm/tools/llvm-link/llvm-link.cpp
+++ b/llvm/tools/llvm-link/llvm-link.cpp
@@ -518,6 +518,7 @@ int main(int argc, char **argv) {
if (Verbose)
errs() << "Writing bitcode...\n";
if (OutputAssembly) {
+ Composite->renumberMetadataForAssembly();
Composite->print(Out.os(), nullptr, /* ShouldPreserveUseListOrder */ false);
} else if (Force || !CheckBitcodeOutputToConsole(Out.os())) {
WriteBitcodeToFile(*Composite, Out.os(),
diff --git a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
index fa4da7a073f1e..c483a7ef893e0 100644
--- a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
+++ b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
@@ -20,6 +20,7 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineModuleSlotTracker.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValueManager.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
@@ -443,12 +444,18 @@ static std::unique_ptr<MachineFunction> cloneMF(MachineFunction *SrcMF,
void ReducerWorkItem::print(raw_ostream &ROS, void *p) const {
if (MMI) {
+ M->renumberMetadataForAssembly();
printMIR(ROS, *M);
for (Function &F : *M) {
- if (auto *MF = MMI->getMachineFunction(F))
+ if (auto *MF = MMI->getMachineFunction(F)) {
+ MachineModuleSlotTracker MST(
+ [&](const Function &F) { return MMI->getMachineFunction(F); }, MF);
+ MST.renumberMetadataForAssembly();
printMIR(ROS, *MMI, *MF);
+ }
}
} else {
+ M->renumberMetadataForAssembly();
M->print(ROS, /*AssemblyAnnotationWriter=*/nullptr,
/*ShouldPreserveUseListOrder=*/true);
}
diff --git a/llvm/tools/llvm-split/llvm-split.cpp b/llvm/tools/llvm-split/llvm-split.cpp
index e7c9d52127274..4ead6fd4b88be 100644
--- a/llvm/tools/llvm-split/llvm-split.cpp
+++ b/llvm/tools/llvm-split/llvm-split.cpp
@@ -116,7 +116,7 @@ void writeStringToFile(StringRef Content, StringRef Path) {
OS << Content << "\n";
}
-void writeModuleToFile(const Module &M, StringRef Path, bool OutputAssembly) {
+void writeModuleToFile(Module &M, StringRef Path, bool OutputAssembly) {
int FD = -1;
if (std::error_code EC = sys::fs::openFileForWrite(Path, FD)) {
errs() << formatv("error opening file: {0}, error: {1}", Path, EC.message())
@@ -125,9 +125,10 @@ void writeModuleToFile(const Module &M, StringRef Path, bool OutputAssembly) {
}
raw_fd_ostream OS(FD, /*ShouldClose*/ true);
- if (OutputAssembly)
+ if (OutputAssembly) {
+ M.renumberMetadataForAssembly();
M.print(OS, /*AssemblyAnnotationWriter*/ nullptr);
- else
+ } else
WriteBitcodeToFile(M, OS);
}
diff --git a/llvm/tools/llvm-stress/llvm-stress.cpp b/llvm/tools/llvm-stress/llvm-stress.cpp
index e3c8a5c3d51ab..e99c83c2b9bac 100644
--- a/llvm/tools/llvm-stress/llvm-stress.cpp
+++ b/llvm/tools/llvm-stress/llvm-stress.cpp
@@ -754,6 +754,7 @@ int main(int argc, char **argv) {
report_fatal_error("Broken module found, compilation aborted!");
// Output textual IR.
+ M->renumberMetadataForAssembly();
M->print(Out->os(), nullptr);
Out->keep();
diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp
index 04c7b99e08cbc..4fbaf02526a87 100644
--- a/llvm/tools/opt/NewPMDriver.cpp
+++ b/llvm/tools/opt/NewPMDriver.cpp
@@ -529,7 +529,8 @@ bool llvm::runPassPipeline(
MPM.addPass(AssignGUIDPass());
}
MPM.addPass(PrintModulePass(
- Out->os(), "", ShouldPreserveAssemblyUseListOrder, EmitSummaryIndex));
+ Out->os(), "", ShouldPreserveAssemblyUseListOrder, EmitSummaryIndex,
+ /*ShouldRenumberMetadata=*/true));
break;
case OK_OutputBitcode:
if (EmitSummaryIndex) {
diff --git a/llvm/tools/opt/optdriver.cpp b/llvm/tools/opt/optdriver.cpp
index 2db4502aa449b..5333825629a27 100644
--- a/llvm/tools/opt/optdriver.cpp
+++ b/llvm/tools/opt/optdriver.cpp
@@ -930,10 +930,11 @@ optMain(int argc, char **argv,
BOS = std::make_unique<raw_svector_ostream>(Buffer);
OS = BOS.get();
}
- if (OutputAssembly)
+ if (OutputAssembly) {
Passes.add(createPrintModulePass(
- *OS, "", /* ShouldPreserveAssemblyUseListOrder */ false));
- else
+ *OS, "", /*ShouldPreserveAssemblyUseListOrder=*/false,
+ /*ShouldRenumberMetadata=*/true));
+ } else
Passes.add(createBitcodeWriterPass(
*OS, /* ShouldPreserveBitcodeUseListOrder */ true));
}
diff --git a/llvm/tools/verify-uselistorder/verify-uselistorder.cpp b/llvm/tools/verify-uselistorder/verify-uselistorder.cpp
index 8f58cc00a3dd1..95edf41e84ce4 100644
--- a/llvm/tools/verify-uselistorder/verify-uselistorder.cpp
+++ b/llvm/tools/verify-uselistorder/verify-uselistorder.cpp
@@ -75,7 +75,7 @@ struct TempFile {
FileRemover Remover;
bool init(const std::string &Ext, bool IsText = false);
bool writeBitcode(const Module &M) const;
- bool writeAssembly(const Module &M) const;
+ bool writeAssembly(Module &M) const;
std::unique_ptr<Module> readBitcode(LLVMContext &Context) const;
std::unique_ptr<Module> readAssembly(LLVMContext &Context) const;
};
@@ -137,7 +137,7 @@ bool TempFile::writeBitcode(const Module &M) const {
return false;
}
-bool TempFile::writeAssembly(const Module &M) const {
+bool TempFile::writeAssembly(Module &M) const {
LLVM_DEBUG(dbgs() << " - write assembly\n");
std::error_code EC;
raw_fd_ostream OS(Filename, EC, sys::fs::OF_TextWithCRLF);
@@ -146,6 +146,7 @@ bool TempFile::writeAssembly(const Module &M) const {
return true;
}
+ M.renumberMetadataForAssembly();
M.print(OS, nullptr, /* ShouldPreserveUseListOrder */ true);
return false;
}
@@ -379,7 +380,7 @@ static void verifyBitcodeUseListOrder(const Module &M) {
verifyAfterRoundTrip(M, F.readBitcode(Context));
}
-static void verifyAssemblyUseListOrder(const Module &M) {
+static void verifyAssemblyUseListOrder(Module &M) {
TempFile F;
if (F.init("ll", /*IsText=*/true))
report_fatal_error("failed to initialize assembly file");
@@ -391,7 +392,7 @@ static void verifyAssemblyUseListOrder(const Module &M) {
verifyAfterRoundTrip(M, F.readAssembly(Context));
}
-static void verifyUseListOrder(const Module &M) {
+static void verifyUseListOrder(Module &M) {
outs() << "verify bitcode\n";
verifyBitcodeUseListOrder(M);
outs() << "verify assembly\n";
diff --git a/llvm/unittests/AsmParser/AsmParserTest.cpp b/llvm/unittests/AsmParser/AsmParserTest.cpp
index bdfd91dbec269..631cbe5c56464 100644
--- a/llvm/unittests/AsmParser/AsmParserTest.cpp
+++ b/llvm/unittests/AsmParser/AsmParserTest.cpp
@@ -16,10 +16,12 @@
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
#define DEBUG_TYPE "unittest-asm-parser-tests"
@@ -73,6 +75,37 @@ TEST(AsmParserTest, SlotMappingTest) {
EXPECT_EQ(Mapping.MetadataNodes.count(1), 0u);
}
+TEST(AsmParserTest, ParsingPreservesMetadataIDsInOtherModules) {
+ StringRef Source = "!named = !{!0}\n!0 = distinct !{}\n";
+
+ for (bool WithIndex : {false, true}) {
+ SCOPED_TRACE(WithIndex ? "parseAssemblyWithIndex" : "parseAssembly");
+ LLVMContext Ctx;
+ SMDiagnostic Error;
+ auto Mod1 = parseAssemblyString(Source, Error, Ctx);
+ ASSERT_TRUE(Mod1) << Error.getMessage().str();
+ MDNode *Node = Mod1->getNamedMetadata("named")->getOperand(0);
+
+ auto PrintMetadataID = [&] {
+ std::string ID;
+ raw_string_ostream OS(ID);
+ Node->printAsOperand(OS, Mod1.get());
+ return ID;
+ };
+ std::string ID = PrintMetadataID();
+
+ std::unique_ptr<Module> Mod2;
+ if (WithIndex)
+ Mod2 = parseAssemblyWithIndex(MemoryBufferRef(Source, "<string>"), Error,
+ Ctx)
+ .Mod;
+ else
+ Mod2 = parseAssemblyString(Source, Error, Ctx);
+ ASSERT_TRUE(Mod2) << Error.getMessage().str();
+ EXPECT_EQ(ID, PrintMetadataID());
+ }
+}
+
TEST(AsmParserTest, TypeAndConstantValueParsing) {
LLVMContext Ctx;
SMDiagnostic Error;
diff --git a/llvm/unittests/IR/AsmWriterTest.cpp b/llvm/unittests/IR/AsmWriterTest.cpp
index 75305f4e2dea4..6c04309af810e 100644
--- a/llvm/unittests/IR/AsmWriterTest.cpp
+++ b/llvm/unittests/IR/AsmWriterTest.cpp
@@ -5,6 +5,7 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+#include "llvm/AsmParser/Parser.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/Function.h"
@@ -12,6 +13,7 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
+#include "llvm/Support/SourceMgr.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -62,6 +64,128 @@ TEST(AsmWriterTest, DumpDIExpression) {
EXPECT_EQ("!DIExpression(DW_OP_constu, 4, DW_OP_minus, DW_OP_deref)", S);
}
+TEST(AsmWriterTest, PersistentBasicBlockPrint) {
+ LLVMContext Ctx;
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M = parseAssemblyString(R"(
+ @0 = global i32 0
+
+ declare void @use(ptr)
+
+ define void @f() !dbg !6 {
+ call void @use(ptr @0), !annotation !12
+ #dbg_value(i32 0, !9, !DIExpression(DW_OP_constu, 4), !11)
+ ret void, !annotation !12
+ }
+
+ define void @g() {
+ ret void
+ }
+
+ !llvm.dbg.cu = !{!0}
+ !llvm.module.flags = !{!5}
+
+ !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "test", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+ !1 = !DIFile(filename: "t.ll", directory: "/")
+ !2 = !{}
+ !5 = !{i32 2, !"Debug Info Version", i32 3}
+ !6 = distinct !DISubprogram(name: "f", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
+ !7 = !DISubroutineType(types: !2)
+ !8 = !{!9}
+ !9 = !DILocalVariable(name: "x", scope: !6, file: !1, line: 1, type: !10)
+ !10 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_unsigned)
+ !11 = !DILocation(line: 1, column: 1, scope: !6)
+ !12 = !{!"annotation"}
+ )",
+ Err, Ctx);
+ ASSERT_NE(M, nullptr);
+
+ std::string First;
+ raw_string_ostream FirstOS(First);
+ M->getFunction("f")->getEntryBlock().print(FirstOS);
+
+ std::string Second;
+ raw_string_ostream SecondOS(Second);
+ M->getFunction("f")->getEntryBlock().print(SecondOS);
+
+ EXPECT_EQ(First, Second);
+ EXPECT_THAT(First, HasSubstr("call void @use(ptr @0), !annotation !"));
+ EXPECT_THAT(First, HasSubstr("#dbg_value(i32 0, !"));
+ EXPECT_THAT(First, HasSubstr("!DIExpression(DW_OP_constu, 4)"));
+ EXPECT_THAT(First, HasSubstr("ret void, !annotation !"));
+
+ MDNode *Earlier = MDNode::getDistinct(Ctx, MDString::get(Ctx, "earlier"));
+ M->getFunction("f")->getEntryBlock().getTerminator()->setMetadata("order",
+ Earlier);
+ MDNode *Later = MDNode::getDistinct(Ctx, MDString::get(Ctx, "later"));
+ M->getFunction("g")->getEntryBlock().getTerminator()->setMetadata("order",
+ Later);
+
+ std::string LaterOutput;
+ raw_string_ostream LaterOS(LaterOutput);
+ M->getFunction("g")->getEntryBlock().print(LaterOS);
+
+ std::string EarlierOutput;
+ raw_string_ostream EarlierOS(EarlierOutput);
+ M->getFunction("f")->getEntryBlock().print(EarlierOS);
+
+ StringRef MetadataPrefix = "!order !";
+ size_t EarlierPos = EarlierOutput.find(MetadataPrefix);
+ size_t LaterPos = LaterOutput.find(MetadataPrefix);
+ ASSERT_NE(EarlierPos, StringRef::npos);
+ ASSERT_NE(LaterPos, StringRef::npos);
+ StringRef EarlierIDText =
+ StringRef(EarlierOutput).drop_front(EarlierPos + MetadataPrefix.size());
+ StringRef LaterIDText =
+ StringRef(LaterOutput).drop_front(LaterPos + MetadataPrefix.size());
+ unsigned EarlierID;
+ unsigned LaterID;
+ ASSERT_FALSE(EarlierIDText.consumeInteger(10, EarlierID));
+ ASSERT_FALSE(LaterIDText.consumeInteger(10, LaterID));
+ EXPECT_LT(EarlierID, LaterID);
+}
+
+TEST(AsmWriterTest, PersistentPrintTemporaryMetadata) {
+ LLVMContext Ctx;
+ Module M("test", Ctx);
+ Function *F = Function::Create(
+ FunctionType::get(Type::getVoidTy(Ctx), /*isVarArg=*/false),
+ Function::ExternalLinkage, "f", M);
+ BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F);
+ ReturnInst *Ret = ReturnInst::Create(Ctx, BB);
+
+ MDNode *Permanent = MDNode::getDistinct(Ctx, MDString::get(Ctx, "permanent"));
+ TempMDNode Temporary = MDNode::getTemporary(Ctx, Permanent);
+ Ret->setMetadata("permanent", Permanent);
+ Ret->setMetadata("temporary", Temporary.get());
+
+ std::string FunctionText;
+ raw_string_ostream FunctionOS(FunctionText);
+ F->print(FunctionOS);
+ EXPECT_THAT(FunctionText, HasSubstr("!permanent !0"));
+ EXPECT_THAT(FunctionText, HasSubstr("!temporary !1"));
+
+ std::string BasicBlockText;
+ raw_string_ostream BasicBlockOS(BasicBlockText);
+ BB->print(BasicBlockOS);
+ EXPECT_THAT(BasicBlockText, HasSubstr("!permanent !0"));
+ EXPECT_THAT(BasicBlockText, HasSubstr("!temporary !1"));
+
+ std::string ModuleText;
+ raw_string_ostream ModuleOS(ModuleText);
+ M.print(ModuleOS, nullptr);
+ EXPECT_THAT(ModuleText, HasSubstr("!0 = distinct !{!\"permanent\"}"));
+ EXPECT_THAT(ModuleText, HasSubstr("!1 = <temporary!> !{!0}"));
+
+ MDNode *Later = MDNode::getDistinct(Ctx, MDString::get(Ctx, "later"));
+ Ret->setMetadata("later", Later);
+ std::string LaterText;
+ raw_string_ostream LaterOS(LaterText);
+ F->print(LaterOS);
+ EXPECT_THAT(LaterText, HasSubstr("!later !2"));
+ EXPECT_THAT(LaterText, HasSubstr("!temporary !1"));
+}
+
TEST(AsmWriterTest, PrintAddrspaceWithNullOperand) {
LLVMContext Ctx;
Module M("test module", Ctx);
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index f2c55c0f2a534..5f6feb5bd87bb 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -282,15 +282,11 @@ TEST_F(MDNodeTest, Print) {
std::string Expected;
{
raw_string_ostream OS(Expected);
- OS << "<" << (void *)N << "> = !{";
+ OS << "!3 = !{";
C->printAsOperand(OS);
OS << ", ";
S->printAsOperand(OS);
- OS << ", null";
- MDNode *Nodes[] = {N0, N1, N2};
- for (auto *Node : Nodes)
- OS << ", <" << (void *)Node << ">";
- OS << "}";
+ OS << ", null, !0, !1, !2}";
}
std::string Actual;
@@ -319,9 +315,9 @@ TEST_F(MDNodeTest, PrintTemporary) {
NamedMDNode *NMD = M.getOrInsertNamedMetadata("named");
NMD->addOperand(N);
- EXPECT_PRINTER_EQ("!0 = !{!1}", N->print(OS, &M));
- EXPECT_PRINTER_EQ("!1 = <temporary!> !{!2}", Temp->print(OS, &M));
- EXPECT_PRINTER_EQ("!2 = !{}", Arg->print(OS, &M));
+ EXPECT_PRINTER_EQ("!2 = !{!1}", N->print(OS, &M));
+ EXPECT_PRINTER_EQ("!1 = <temporary!> !{!0}", Temp->print(OS, &M));
+ EXPECT_PRINTER_EQ("!0 = !{}", Arg->print(OS, &M));
// Cleanup.
Temp->replaceAllUsesWith(Arg);
@@ -343,11 +339,11 @@ TEST_F(MDNodeTest, PrintFromModule) {
std::string Expected;
{
raw_string_ostream OS(Expected);
- OS << "!0 = !{";
+ OS << "!3 = !{";
C->printAsOperand(OS);
OS << ", ";
S->printAsOperand(OS);
- OS << ", null, !1, !2, !3}";
+ OS << ", null, !0, !1, !2}";
}
EXPECT_PRINTER_EQ(Expected, N->print(OS, &M));
diff --git a/llvm/unittests/IR/ModuleTest.cpp b/llvm/unittests/IR/ModuleTest.cpp
index e8c2ecfb9f3a8..82e652aadc013 100644
--- a/llvm/unittests/IR/ModuleTest.cpp
+++ b/llvm/unittests/IR/ModuleTest.cpp
@@ -438,6 +438,7 @@ define void @Foo2() {
ASSERT_EQ(NMD.getParent(), &*M1);
}
+ M1->renumberMetadataForAssembly();
std::string M1Print;
{
llvm::raw_string_ostream Os(M1Print);
@@ -446,6 +447,60 @@ define void @Foo2() {
ASSERT_EQ(M2Str, M1Print);
}
+TEST(ModuleTest, RenumberMetadataPreservesContextWideUniqueIDs) {
+ LLVMContext Context;
+ Module M("M", Context);
+ MDNode *Detached =
+ MDNode::getDistinct(Context, MDString::get(Context, "detached"));
+ MDNode *Attached =
+ MDNode::getDistinct(Context, MDString::get(Context, "attached"));
+ NamedMDNode *NMD = M.getOrInsertNamedMetadata("n");
+ NMD->addOperand(Attached);
+
+ M.renumberMetadataForAssembly();
+ NMD->addOperand(Detached);
+
+ std::string Assembly;
+ raw_string_ostream OS(Assembly);
+ M.print(OS, nullptr);
+ EXPECT_NE(Assembly.find("!n = !{!0, !2}"), std::string::npos);
+
+ LLVMContext ParsedContext;
+ SMDiagnostic Err;
+ EXPECT_TRUE(parseAssemblyString(Assembly, Err, ParsedContext))
+ << Err.getMessage().str();
+}
+
+TEST(ModuleTest, RenumberMetadataPreservesUniqueTemporaryIDs) {
+ LLVMContext Context;
+ Module M("M", Context);
+ TempMDTuple DetachedA =
+ MDTuple::getTemporary(Context, MDString::get(Context, "detached-a"));
+ TempMDTuple DetachedB =
+ MDTuple::getTemporary(Context, MDString::get(Context, "detached-b"));
+ MDNode *AttachedA =
+ MDNode::getDistinct(Context, MDString::get(Context, "attached-a"));
+ MDNode *AttachedB =
+ MDNode::getDistinct(Context, MDString::get(Context, "attached-b"));
+ NamedMDNode *NMD = M.getOrInsertNamedMetadata("n");
+ NMD->addOperand(AttachedA);
+ NMD->addOperand(AttachedB);
+
+ M.renumberMetadataForAssembly();
+ NMD->addOperand(MDNode::replaceWithDistinct(std::move(DetachedA)));
+ NMD->addOperand(MDNode::replaceWithDistinct(std::move(DetachedB)));
+
+ std::string Assembly;
+ raw_string_ostream OS(Assembly);
+ M.print(OS, nullptr);
+ EXPECT_NE(Assembly.find("!n = !{!0, !1, !4, !5}"), std::string::npos);
+
+ LLVMContext ParsedContext;
+ SMDiagnostic Err;
+ EXPECT_TRUE(parseAssemblyString(Assembly, Err, ParsedContext))
+ << Err.getMessage().str();
+}
+
TEST(ModuleTest, FunctionDefinitions) {
// Test getFunctionDefs() method which returns only functions with bodies
LLVMContext Context;
diff --git a/llvm/unittests/MIR/MachineMetadata.cpp b/llvm/unittests/MIR/MachineMetadata.cpp
index f58a3cac1bb0f..c611cf062bf6b 100644
--- a/llvm/unittests/MIR/MachineMetadata.cpp
+++ b/llvm/unittests/MIR/MachineMetadata.cpp
@@ -19,6 +19,7 @@
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/FileCheck/FileCheck.h"
+#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSlotTracker.h"
@@ -49,20 +50,9 @@ class MachineMetadataTest : public testing::Test {
void SetUp() override { M = std::make_unique<Module>("Dummy", Context); }
void addHooks(ModuleSlotTracker &MST, const MachineOperand &MO) {
- // Setup hooks to assign slot numbers for the specified machine metadata.
- MST.setProcessHook([&MO](AbstractSlotTrackerStorage *AST, const Module *M,
- bool ShouldInitializeAllMetadata) {
- if (ShouldInitializeAllMetadata) {
- if (MO.isMetadata())
- AST->createMetadataSlot(MO.getMetadata());
- }
- });
- MST.setProcessHook([&MO](AbstractSlotTrackerStorage *AST, const Function *F,
- bool ShouldInitializeAllMetadata) {
- if (!ShouldInitializeAllMetadata) {
- if (MO.isMetadata())
- AST->createMetadataSlot(MO.getMetadata());
- }
+ MST.setProcessHook([&MO](AbstractSlotTrackerStorage *AST, const Module *) {
+ if (MO.isMetadata())
+ AST->createMetadataSlot(MO.getMetadata());
});
}
@@ -140,9 +130,7 @@ TEST_F(MachineMetadataTest, TrivialHook) {
}
TEST_F(MachineMetadataTest, BasicHook) {
- // Verify that post-process hook is invoked to assign slot numbers for
- // machine metadata. When both LLVM IR and machine IR contain metadata,
- // ensure that machine metadata is always assigned after LLVM IR.
+ // Verify that the post-process hook records machine metadata.
ASSERT_TRUE(M);
// Create a MachineOperand with a metadata and print it.
@@ -165,16 +153,16 @@ TEST_F(MachineMetadataTest, BasicHook) {
addHooks(MST, MO);
// Print a MachineOperand containing a metadata node.
- EXPECT_EQ("!1", print([&](raw_ostream &OS) {
+ EXPECT_EQ("!0", print([&](raw_ostream &OS) {
MO.print(OS, MST, LLT{}, /*OpIdx*/ ~0U, /*PrintDef=*/false,
/*IsStandalone=*/false,
/*ShouldPrintRegisterTies=*/false, /*TiedOperandIdx=*/0,
/*TRI=*/nullptr);
}));
// Print the definition of these unnamed metadata nodes.
- EXPECT_EQ("!0 = !{!\"bar\"}",
+ EXPECT_EQ("!1 = !{!\"bar\"}",
print([&](raw_ostream &OS) { Node->print(OS, MST); }));
- EXPECT_EQ("!1 = !{!\"foo\"}",
+ EXPECT_EQ("!0 = !{!\"foo\"}",
print([&](raw_ostream &OS) { MachineNode->print(OS, MST); }));
}
@@ -252,10 +240,9 @@ body: |
MachineModuleSlotTracker MST(
[&](const Function &F) { return MMI.getMachineFunction(F); }, MF);
- // Print that MI with new machine metadata, which slot numbers should be
- // assigned.
+ // Print the MI using the stored IDs of the new machine metadata.
EXPECT_EQ("%1:gpr32 = LDRWui %0, 0 :: (load (s32) from %ir.p, "
- "!alias.scope !0, !noalias !3)",
+ "!alias.scope !3, !noalias !4)",
print([&](raw_ostream &OS) {
MI.print(OS, MST, /*IsStandalone=*/false, /*SkipOpers=*/false,
/*SkipDebugLoc=*/false, /*AddNewLine=*/false);
@@ -342,10 +329,64 @@ body: |
auto *MF = MMI.getMachineFunction(*M->getFunction("test0"));
auto *MBB = MF->getBlockNumbered(0);
+ MachineInstr *DbgValue = nullptr;
for (auto It = MBB->begin(); It != MBB->end(); ++It) {
MachineInstr &MI = *It;
ASSERT_TRUE(MI.isMetaInstruction());
+ if (MI.isDebugValue())
+ DbgValue = &MI;
}
+
+ ASSERT_NE(DbgValue, nullptr);
+ auto *IRVar = cast<DILocalVariable>(DbgValue->getOperand(2).getMetadata());
+ M->getOrInsertNamedMetadata("test.ir.variable")
+ ->addOperand(const_cast<DILocalVariable *>(IRVar));
+ // Leave gaps between reachable nodes to exercise sparse metadata IDs.
+ auto *UnusedModuleNode = MDNode::getDistinct(Context, {});
+ (void)UnusedModuleNode;
+ auto *ModuleNode =
+ MDNode::getDistinct(Context, MDString::get(Context, "module metadata"));
+ M->getOrInsertNamedMetadata("test.module.metadata")->addOperand(ModuleNode);
+ auto PrintMetadataID = [&](const MDNode *N) {
+ return print([&](raw_ostream &OS) { N->printAsOperand(OS, M.get()); });
+ };
+ std::string ModuleNodeID = PrintMetadataID(ModuleNode);
+ print([&](raw_ostream &OS) { printMIR(OS, *M); });
+ EXPECT_EQ(ModuleNodeID, PrintMetadataID(ModuleNode));
+
+ auto *UnusedMachineNode = MDNode::getDistinct(Context, {});
+ (void)UnusedMachineNode;
+ auto *MachineLoc =
+ DILocation::get(Context, 2, 1, DbgValue->getDebugLoc()->getScope());
+ auto *MachineNode =
+ MDNode::get(Context, {MDString::get(Context, "machine"), MachineLoc});
+ MBB->front().addOperand(*MF, MachineOperand::CreateMetadata(MachineNode));
+ auto *InlineMachineLoc =
+ DILocation::get(Context, 3, 1, DbgValue->getDebugLoc()->getScope());
+ DbgValue->setDebugLoc(DebugLoc(InlineMachineLoc));
+
+ MachineModuleSlotTracker MST(
+ [&](const Function &F) { return MMI.getMachineFunction(F); }, MF);
+ MachineModuleSlotTracker::MachineMDNodeListType MDList;
+ MST.collectMachineMDNodes(MDList);
+ EXPECT_TRUE(llvm::any_of(
+ MDList, [&](const auto &MD) { return MD.second == MachineNode; }));
+ EXPECT_TRUE(llvm::any_of(
+ MDList, [&](const auto &MD) { return MD.second == MachineLoc; }));
+ EXPECT_FALSE(llvm::any_of(
+ MDList, [&](const auto &MD) { return MD.second == InlineMachineLoc; }));
+ EXPECT_FALSE(
+ llvm::any_of(MDList, [&](const auto &MD) { return MD.second == IRVar; }));
+
+ std::string MachineNodeID = PrintMetadataID(MachineNode);
+ std::string Output = print([&](raw_ostream &OS) {
+ printMIR(OS, *M);
+ printMIR(OS, MMI, *MF);
+ });
+ EXPECT_EQ(ModuleNodeID, PrintMetadataID(ModuleNode));
+ EXPECT_EQ(MachineNodeID, PrintMetadataID(MachineNode));
+ MachineModuleInfo RoundTripMMI(TM.get());
+ EXPECT_TRUE(parseMIR(*TM, Output, RoundTripMMI)) << Output;
}
TEST_F(MachineMetadataTest, MMSlotTrackerX64) {
@@ -403,14 +444,19 @@ body: |
MachineModuleSlotTracker MST(
[&](const Function &F) { return MMI.getMachineFunction(F); }, MF);
- // Print that MI with new machine metadata, which slot numbers should be
- // assigned.
- EXPECT_EQ("%1:gr32 = MOV32rm %0, 1, $noreg, 0, $noreg :: (load (s32) from %ir.p, "
- "!alias.scope !0, !noalias !3)",
- print([&](raw_ostream &OS) {
- MI.print(OS, MST, /*IsStandalone=*/false, /*SkipOpers=*/false,
- /*SkipDebugLoc=*/false, /*AddNewLine=*/false);
- }));
+ // Print the MI using the stored IDs of the new machine metadata.
+ std::string Set0ID =
+ print([&](raw_ostream &OS) { Set0->printAsOperand(OS, M.get()); });
+ std::string Set1ID =
+ print([&](raw_ostream &OS) { Set1->printAsOperand(OS, M.get()); });
+ EXPECT_EQ(
+ "%1:gr32 = MOV32rm %0, 1, $noreg, 0, $noreg :: (load (s32) from %ir.p, "
+ "!alias.scope " +
+ Set0ID + ", !noalias " + Set1ID + ")",
+ print([&](raw_ostream &OS) {
+ MI.print(OS, MST, /*IsStandalone=*/false, /*SkipOpers=*/false,
+ /*SkipDebugLoc=*/false, /*AddNewLine=*/false);
+ }));
std::vector<const MDNode *> Generated{Domain, Scope0, Scope1, Set0, Set1};
// Examine machine metadata collected. They should match ones
@@ -502,11 +548,15 @@ body: |
MachineModuleSlotTracker MST(
[&](const Function &F) { return MMI.getMachineFunction(F); }, MF);
- // Print that MI with new machine metadata, which slot numbers should be
- // assigned.
+ // Print the MI using the stored IDs of the new machine metadata.
+ std::string Set0ID =
+ print([&](raw_ostream &OS) { Set0->printAsOperand(OS, M.get()); });
+ std::string Set1ID =
+ print([&](raw_ostream &OS) { Set1->printAsOperand(OS, M.get()); });
EXPECT_EQ(
"%5:vgpr_32 = FLAT_LOAD_DWORD killed %4, 0, 0, implicit $exec, implicit "
- "$flat_scr :: (load (s32) from %ir.p, !alias.scope !0, !noalias !3)",
+ "$flat_scr :: (load (s32) from %ir.p, !alias.scope " +
+ Set0ID + ", !noalias " + Set1ID + ")",
print([&](raw_ostream &OS) {
MI.print(OS, MST, /*IsStandalone=*/false, /*SkipOpers=*/false,
/*SkipDebugLoc=*/false, /*AddNewLine=*/false);
diff --git a/mlir/lib/Target/LLVMIR/ConvertToLLVMIR.cpp b/mlir/lib/Target/LLVMIR/ConvertToLLVMIR.cpp
index fef191a302ac8..1797efec0252f 100644
--- a/mlir/lib/Target/LLVMIR/ConvertToLLVMIR.cpp
+++ b/mlir/lib/Target/LLVMIR/ConvertToLLVMIR.cpp
@@ -31,6 +31,7 @@ void registerToLLVMIRTranslation() {
if (!llvmModule)
return failure();
+ llvmModule->renumberMetadataForAssembly();
llvmModule->print(output, nullptr);
return success();
},
diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll
index 7b59f91497120..ba854d8616144 100644
--- a/mlir/test/Target/LLVMIR/Import/import-failure.ll
+++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll
@@ -65,7 +65,7 @@ define void @access_group(ptr %arg1) {
; CHECK: <unknown>
; CHECK-SAME: warning: expected all loop properties to be either debug locations or metadata nodes
; CHECK: <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, i32 42}
+; CHECK-SAME: warning: unhandled metadata: ![[LOOP_ID:[0-9]+]] = distinct !{![[LOOP_ID]], i32 42}
define void @invalid_loop_node(i64 %n, ptr %A) {
entry:
br label %end, !llvm.loop !0
@@ -80,7 +80,7 @@ end:
; CHECK: <unknown>
; CHECK-SAME: warning: cannot import empty loop property
; CHECK: <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1}
+; CHECK-SAME: warning: unhandled metadata: ![[EMPTY_LOOP:[0-9]+]] = distinct !{![[EMPTY_LOOP]], ![[EMPTY_PROP:[0-9]+]]}
define void @invalid_loop_node(i64 %n, ptr %A) {
entry:
br label %end, !llvm.loop !0
@@ -96,7 +96,7 @@ end:
; CHECK: <unknown>
; CHECK-SAME: warning: cannot import loop property without a name
; CHECK: <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1}
+; CHECK-SAME: warning: unhandled metadata: ![[UNNAMED_LOOP:[0-9]+]] = distinct !{![[UNNAMED_LOOP]], ![[UNNAMED_PROP:[0-9]+]]}
define void @invalid_loop_node(i64 %n, ptr %A) {
entry:
br label %end, !llvm.loop !0
@@ -112,7 +112,7 @@ end:
; CHECK: <unknown>
; CHECK-SAME: warning: cannot import loop properties with duplicated names llvm.loop.disable_nonforced
; CHECK: <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1, !1}
+; CHECK-SAME: warning: unhandled metadata: ![[DUP_LOOP:[0-9]+]] = distinct !{![[DUP_LOOP]], ![[DUP_PROP:[0-9]+]], ![[DUP_PROP]]}
define void @unsupported_loop_annotation(i64 %n, ptr %A) {
entry:
br label %end, !llvm.loop !0
@@ -128,7 +128,7 @@ end:
; CHECK: <unknown>
; CHECK-SAME: warning: expected metadata node llvm.loop.disable_nonforced to hold no value
; CHECK: <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1}
+; CHECK-SAME: warning: unhandled metadata: ![[VALUE_LOOP:[0-9]+]] = distinct !{![[VALUE_LOOP]], ![[VALUE_PROP:[0-9]+]]}
define void @unsupported_loop_annotation(i64 %n, ptr %A) {
entry:
br label %end, !llvm.loop !0
@@ -144,7 +144,7 @@ end:
; CHECK: <unknown>
; CHECK-SAME: warning: expected metadata nodes llvm.loop.unroll.enable and llvm.loop.unroll.disable to be mutually exclusive
; CHECK: <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1, !2}
+; CHECK-SAME: warning: unhandled metadata: ![[EXCLUSIVE_LOOP:[0-9]+]] = distinct !{![[EXCLUSIVE_LOOP]], ![[ENABLE_PROP:[0-9]+]], ![[DISABLE_PROP:[0-9]+]]}
define void @unsupported_loop_annotation(i64 %n, ptr %A) {
entry:
br label %end, !llvm.loop !0
@@ -161,7 +161,7 @@ end:
; CHECK: <unknown>
; CHECK-SAME: warning: expected metadata node llvm.loop.vectorize.width to hold an i32 value
; CHECK: <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1}
+; CHECK-SAME: warning: unhandled metadata: ![[WIDTH_LOOP:[0-9]+]] = distinct !{![[WIDTH_LOOP]], ![[WIDTH_PROP:[0-9]+]]}
define void @unsupported_loop_annotation(i64 %n, ptr %A) {
entry:
br label %end, !llvm.loop !0
@@ -177,7 +177,7 @@ end:
; CHECK: <unknown>
; CHECK-SAME: warning: expected metadata node llvm.loop.vectorize.followup_all to hold an MDNode
; CHECK: <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1}
+; CHECK-SAME: warning: unhandled metadata: ![[FOLLOWUP_LOOP:[0-9]+]] = distinct !{![[FOLLOWUP_LOOP]], ![[FOLLOWUP_PROP:[0-9]+]]}
define void @unsupported_loop_annotation(i64 %n, ptr %A) {
entry:
br label %end, !llvm.loop !0
@@ -193,7 +193,7 @@ end:
; CHECK: <unknown>
; CHECK-SAME: warning: expected metadata node llvm.loop.parallel_accesses to hold one or multiple MDNodes
; CHECK: <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1}
+; CHECK-SAME: warning: unhandled metadata: ![[PARALLEL_LOOP:[0-9]+]] = distinct !{![[PARALLEL_LOOP]], ![[PARALLEL_PROP:[0-9]+]]}
define void @unsupported_loop_annotation(i64 %n, ptr %A) {
entry:
br label %end, !llvm.loop !0
@@ -209,7 +209,7 @@ end:
; CHECK: <unknown>
; CHECK-SAME: warning: unknown loop annotation llvm.loop.typo
; CHECK: <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1, !2}
+; CHECK-SAME: warning: unhandled metadata: ![[UNKNOWN_LOOP:[0-9]+]] = distinct !{![[UNKNOWN_LOOP]], ![[KNOWN_PROP:[0-9]+]], ![[UNKNOWN_PROP:[0-9]+]]}
define void @unsupported_loop_annotation(i64 %n, ptr %A) {
entry:
br label %end, !llvm.loop !0
@@ -241,7 +241,7 @@ end:
; // -----
; CHECK: <unknown>
-; CHECK-SAME: warning: dropped instruction: call void @llvm.experimental.noalias.scope.decl(metadata !0)
+; CHECK-SAME: warning: dropped instruction: call void @llvm.experimental.noalias.scope.decl(metadata ![[SCOPE_LIST:[0-9]+]])
define void @unused_scope() {
call void @llvm.experimental.noalias.scope.decl(metadata !0)
ret void
@@ -320,7 +320,7 @@ bb1:
!10 = !{ i32 1, !"foo", i32 1 }
!11 = !{ i32 4, !"bar", i32 37 }
!12 = !{ i32 2, !"qux", i32 42 }
-; CHECK: unsupported module flag value for key 'qux' : !4 = !{!"foo", i32 1}
+; CHECK: unsupported module flag value for key 'qux' : ![[FLAG_VALUE:[0-9]+]] = !{!"foo", i32 1}
!13 = !{ i32 3, !"qux", !{ !"foo", i32 1 }}
!llvm.module.flags = !{ !10, !11, !12, !13 }
diff --git a/polly/test/ForwardOpTree/atax.ll b/polly/test/ForwardOpTree/atax.ll
index 3dfe3fa0aa8e6..3d3a44b763aa3 100644
--- a/polly/test/ForwardOpTree/atax.ll
+++ b/polly/test/ForwardOpTree/atax.ll
@@ -87,7 +87,7 @@ declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i32, i1)
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: { Stmt_for_body3[i0] -> MemRef1__phi[] };
; CHECK-NEXT: Instructions {
-; CHECK-NEXT: store double 0.000000e+00, ptr %arrayidx5, align 8, !tbaa !2
+; CHECK-NEXT: store double 0.000000e+00, ptr %arrayidx5, align 8, !tbaa !13
; CHECK-NEXT: }
; CHECK-NEXT: Stmt_for_body8
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
@@ -105,11 +105,11 @@ declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i32, i1)
; CHECK-NEXT: { Stmt_for_body8[i0, i1] -> MemRef_add[] };
; CHECK-NEXT: Instructions {
; CHECK-NEXT: %0 = phi double [ 0.000000e+00, %for.body3 ], [ %add, %for.body8 ]
-; CHECK-NEXT: %1 = load double, ptr %arrayidx14, align 8, !tbaa !2
-; CHECK-NEXT: %2 = load double, ptr %arrayidx16, align 8, !tbaa !2
+; CHECK-NEXT: %1 = load double, ptr %arrayidx14, align 8, !tbaa !13
+; CHECK-NEXT: %2 = load double, ptr %arrayidx16, align 8, !tbaa !13
; CHECK-NEXT: %mul = fmul double %1, %2
; CHECK-NEXT: %add = fadd double %0, %mul
-; CHECK-NEXT: store double %add, ptr %arrayidx5, align 8, !tbaa !2
+; CHECK-NEXT: store double %add, ptr %arrayidx5, align 8, !tbaa !13
; CHECK-NEXT: %exitcond = icmp eq i64 %indvars.iv.next, 2
; CHECK-NEXT: }
; CHECK-NEXT: Stmt_for_end21
@@ -131,11 +131,11 @@ declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i32, i1)
; CHECK-NEXT: { Stmt_for_body24[i0, i1] -> MemRef_y[i1] };
; CHECK-NEXT: Instructions {
; CHECK-NEXT: %3 = phi double [ %add, %for.end21 ], [ %.pre, %for.body24.for.body24_crit_edge ]
-; CHECK-NEXT: %4 = load double, ptr %arrayidx26, align 8, !tbaa !2
-; CHECK-NEXT: %5 = load double, ptr %arrayidx30, align 8, !tbaa !2
+; CHECK-NEXT: %4 = load double, ptr %arrayidx26, align 8, !tbaa !13
+; CHECK-NEXT: %5 = load double, ptr %arrayidx30, align 8, !tbaa !13
; CHECK-NEXT: %mul33 = fmul double %5, %3
; CHECK-NEXT: %add34 = fadd double %4, %mul33
-; CHECK-NEXT: store double %add34, ptr %arrayidx26, align 8, !tbaa !2
+; CHECK-NEXT: store double %add34, ptr %arrayidx26, align 8, !tbaa !13
; CHECK-NEXT: %exitcond7 = icmp eq i64 %indvars.iv.next6, 2
; CHECK-NEXT: }
; CHECK-NEXT: Stmt_for_body24_for_body24_crit_edge
@@ -144,6 +144,6 @@ declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i32, i1)
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: { Stmt_for_body24_for_body24_crit_edge[i0, i1] -> MemRef_tmp[i0] };
; CHECK-NEXT: Instructions {
-; CHECK-NEXT: %.pre = load double, ptr %arrayidx5, align 8, !tbaa !2
+; CHECK-NEXT: %.pre = load double, ptr %arrayidx5, align 8, !tbaa !13
; CHECK-NEXT: }
; CHECK-NEXT: }
diff --git a/polly/test/ForwardOpTree/jacobi-1d.ll b/polly/test/ForwardOpTree/jacobi-1d.ll
index 3bc504d88c0eb..fbae4c7bc227b 100644
--- a/polly/test/ForwardOpTree/jacobi-1d.ll
+++ b/polly/test/ForwardOpTree/jacobi-1d.ll
@@ -74,8 +74,8 @@ for.end35: ; preds = %for.inc33
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: { Stmt_for_body[i0] -> MemRef2__phi[] };
; CHECK-NEXT: Instructions {
-; CHECK-NEXT: %.pre = load double, ptr %A, align 8, !tbaa !2
-; CHECK-NEXT: %.pre10 = load double, ptr %arrayidx6.phi.trans.insert, align 8, !tbaa !2
+; CHECK-NEXT: %.pre = load double, ptr %A, align 8, !tbaa !13
+; CHECK-NEXT: %.pre10 = load double, ptr %arrayidx6.phi.trans.insert, align 8, !tbaa !13
; CHECK-NEXT: }
; CHECK-NEXT: Stmt_for_body3
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
@@ -96,10 +96,10 @@ for.end35: ; preds = %for.inc33
; CHECK-NEXT: %0 = phi double [ %.pre10, %for.body ], [ %2, %for.body3 ]
; CHECK-NEXT: %1 = phi double [ %.pre, %for.body ], [ %0, %for.body3 ]
; CHECK-NEXT: %add = fadd double %1, %0
-; CHECK-NEXT: %2 = load double, ptr %arrayidx9, align 8, !tbaa !2
+; CHECK-NEXT: %2 = load double, ptr %arrayidx9, align 8, !tbaa !13
; CHECK-NEXT: %add10 = fadd double %add, %2
; CHECK-NEXT: %mul = fmul double %add10, 3.333300e-01
-; CHECK-NEXT: store double %mul, ptr %arrayidx12, align 8, !tbaa !2
+; CHECK-NEXT: store double %mul, ptr %arrayidx12, align 8, !tbaa !13
; CHECK-NEXT: %exitcond = icmp eq i64 %indvars.iv.next, 3
; CHECK-NEXT: }
; CHECK-NEXT: }
diff --git a/polly/test/ScopInfo/preserve-equiv-class-order-in-basic_block.ll b/polly/test/ScopInfo/preserve-equiv-class-order-in-basic_block.ll
index 800b0339a1422..adcd95a277e62 100644
--- a/polly/test/ScopInfo/preserve-equiv-class-order-in-basic_block.ll
+++ b/polly/test/ScopInfo/preserve-equiv-class-order-in-basic_block.ll
@@ -77,7 +77,7 @@ for.end13: ; preds = %for.inc11
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: { Stmt_for_end_a[] -> MemRef_conv[] };
; CHECK-NEXT: Instructions {
-; CHECK-NEXT: %1 = load i32, ptr @e, align 4, !tbaa !0
+; CHECK-NEXT: %1 = load i32, ptr @e, align 4, !tbaa !4
; CHECK-NEXT: %2 = trunc i32 %1 to i16
; CHECK-NEXT: %conv = and i16 %2, 1
; CHECK-NEXT: %tobool = icmp eq i16 %conv, 0
@@ -90,5 +90,5 @@ for.end13: ; preds = %for.inc11
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: { Stmt_for_end[] -> MemRef_e[0] };
; CHECK-NEXT: Instructions {
-; CHECK-NEXT: store i32 2, ptr @e, align 4, !tbaa !0
+; CHECK-NEXT: store i32 2, ptr @e, align 4, !tbaa !4
; CHECK-NEXT: }
diff --git a/polly/test/ScopInfo/stmt_split_exit_of_region_stmt.ll b/polly/test/ScopInfo/stmt_split_exit_of_region_stmt.ll
index 54832607f11d5..8a160c299172b 100644
--- a/polly/test/ScopInfo/stmt_split_exit_of_region_stmt.ll
+++ b/polly/test/ScopInfo/stmt_split_exit_of_region_stmt.ll
@@ -19,7 +19,7 @@
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: { Stmt_Stmt[i0] -> MemRef_A[i0] };
; CHECK-NEXT: Instructions {
-; CHECK-NEXT: store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !0
+; CHECK-NEXT: store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !1
; CHECK-NEXT: }
; CHECK-NEXT: Stmt_Stmt_b
; CHECK-NEXT: Domain :=
diff --git a/polly/test/ScopInfo/stmt_split_no_after_split.ll b/polly/test/ScopInfo/stmt_split_no_after_split.ll
index 0a4284bdd34f5..b0dffa98c7e79 100644
--- a/polly/test/ScopInfo/stmt_split_no_after_split.ll
+++ b/polly/test/ScopInfo/stmt_split_no_after_split.ll
@@ -9,7 +9,7 @@
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: { Stmt_Stmt[i0] -> MemRef_A[i0] };
; CHECK-NEXT: Instructions {
-; CHECK-NEXT: store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !0
+; CHECK-NEXT: store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !1
; CHECK-NEXT: }
; CHECK-NEXT: }
;
diff --git a/polly/test/ScopInfo/stmt_split_no_dependence.ll b/polly/test/ScopInfo/stmt_split_no_dependence.ll
index ed2180407c68d..d129e58c11204 100644
--- a/polly/test/ScopInfo/stmt_split_no_dependence.ll
+++ b/polly/test/ScopInfo/stmt_split_no_dependence.ll
@@ -17,7 +17,7 @@
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: { Stmt_Stmt[i0] -> MemRef_A[i0] };
; CHECK-NEXT: Instructions {
-; CHECK-NEXT: store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !0
+; CHECK-NEXT: store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !1
; CHECK-NEXT: }
; CHECK-NEXT: Stmt_Stmt_b
; CHECK-NEXT: Domain :=
diff --git a/polly/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll b/polly/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll
index 0521525e272b3..1150c5ead3065 100644
--- a/polly/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll
+++ b/polly/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll
@@ -9,7 +9,7 @@
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: { Stmt_Stmt[i0] -> MemRef_A[i0] };
; CHECK-NEXT: Instructions {
-; CHECK-NEXT: store i32 %phi, ptr %arrayidx, align 4, !polly_split_after !0
+; CHECK-NEXT: store i32 %phi, ptr %arrayidx, align 4, !polly_split_after !1
; CHECK-NEXT: }
; CHECK-NEXT: Stmt_Stmt_b
; CHECK-NEXT: Domain :=
diff --git a/polly/test/ScopInfo/stmt_split_phi_in_stmt.ll b/polly/test/ScopInfo/stmt_split_phi_in_stmt.ll
index 82a85aa5f0099..2ba38dc7b3a4b 100644
--- a/polly/test/ScopInfo/stmt_split_phi_in_stmt.ll
+++ b/polly/test/ScopInfo/stmt_split_phi_in_stmt.ll
@@ -9,7 +9,7 @@
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: { Stmt_Stmt[i0] -> MemRef_A[i0] };
; CHECK-NEXT: Instructions {
-; CHECK-NEXT: store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !0
+; CHECK-NEXT: store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !1
; CHECK-NEXT: }
; CHECK-NEXT: Stmt_Stmt_b
; CHECK-NEXT: Domain :=
diff --git a/polly/test/ScopInfo/stmt_split_scalar_dependence.ll b/polly/test/ScopInfo/stmt_split_scalar_dependence.ll
index 1f21c0ce7225f..a98a0538fb3a5 100644
--- a/polly/test/ScopInfo/stmt_split_scalar_dependence.ll
+++ b/polly/test/ScopInfo/stmt_split_scalar_dependence.ll
@@ -12,7 +12,7 @@
; CHECK-NEXT: { Stmt_Stmt[i0] -> MemRef_a[] };
; CHECK-NEXT: Instructions {
; CHECK-NEXT: %a = fadd double 2.100000e+01, 2.100000e+01
-; CHECK-NEXT: store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !0
+; CHECK-NEXT: store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !1
; CHECK-NEXT: }
; CHECK-NEXT: Stmt_Stmt_b
; CHECK-NEXT: Domain :=
diff --git a/polly/test/ScopInfo/stmt_split_within_loop.ll b/polly/test/ScopInfo/stmt_split_within_loop.ll
index 580ffab567846..6164cce2de7fd 100644
--- a/polly/test/ScopInfo/stmt_split_within_loop.ll
+++ b/polly/test/ScopInfo/stmt_split_within_loop.ll
@@ -9,7 +9,7 @@
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: { Stmt_Stmt[i0, i1] -> MemRef_A[i0] };
; CHECK-NEXT: Instructions {
-; CHECK-NEXT: store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !0
+; CHECK-NEXT: store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !1
; CHECK-NEXT: }
; CHECK-NEXT: Stmt_Stmt_b
; CHECK-NEXT: Domain :=
More information about the flang-commits
mailing list