diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h --- a/llvm/include/llvm/IR/Instruction.h +++ b/llvm/include/llvm/IR/Instruction.h @@ -339,7 +339,11 @@ /// If this instruction already has !annotation metadata, append \p Annotation /// to the existing node. void addAnnotationMetadata(StringRef Annotation); - + /// Adds an !annotation metadata node with an array of \p Annotations + /// as a tuple to this instruction. If this instruction already has + /// !annotation metadata, append the tuple to + /// the existing node. + void addAnnotationMetadata(SmallVector Annotations); /// Returns the AA metadata for this instruction. AAMDNodes getAAMetadata() const; diff --git a/llvm/lib/CodeGen/BasicBlockSections.cpp b/llvm/lib/CodeGen/BasicBlockSections.cpp --- a/llvm/lib/CodeGen/BasicBlockSections.cpp +++ b/llvm/lib/CodeGen/BasicBlockSections.cpp @@ -300,7 +300,8 @@ if (Existing) { MDTuple *Tuple = cast(Existing); for (const auto &N : Tuple->operands()) - if (cast(N.get())->getString() == MetadataName) + if (isa(N.get()) && + cast(N.get())->getString() == MetadataName) return true; } diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -119,7 +119,8 @@ auto *MetadataName = "unsafe-stack-size"; if (auto &N = Existing->getOperand(0)) { - if (cast(N.get())->getString() == MetadataName) { + if (isa(N.get()) && + cast(N.get())->getString() == MetadataName) { if (auto &Op = Existing->getOperand(1)) { auto Val = mdconst::extract(Op)->getZExtValue(); FrameInfo.setUnsafeStackSize(Val); diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp --- a/llvm/lib/IR/Metadata.cpp +++ b/llvm/lib/IR/Metadata.cpp @@ -1475,23 +1475,52 @@ Value::setMetadata(KindID, Node); } +void Instruction::addAnnotationMetadata(SmallVector Annotations) { + SmallSetVector AnnotationsSet(Annotations.begin(), + Annotations.end()); + MDBuilder MDB(getContext()); + + auto *Existing = getMetadata(LLVMContext::MD_annotation); + SmallVector Names; + if (Existing) { + auto *Tuple = cast(Existing); + for (auto &N : Tuple->operands()) { + if (isa(N.get())) + continue; + auto *MDAnnotationTuple = cast(N); + if (any_of(MDAnnotationTuple->operands(), [AnnotationsSet](auto &Op) { + return AnnotationsSet.contains(cast(Op)->getString()); + })) + return; + Names.push_back(N); + } + } + + SmallVector MDAnnotationStrings; + for (StringRef Annotation : Annotations) + MDAnnotationStrings.push_back(MDB.createString(Annotation)); + MDNode *InfoTuple = MDTuple::get(getContext(), MDAnnotationStrings); + Names.push_back(InfoTuple); + MDNode *MD = MDTuple::get(getContext(), Names); + setMetadata(LLVMContext::MD_annotation, MD); +} + void Instruction::addAnnotationMetadata(StringRef Name) { MDBuilder MDB(getContext()); auto *Existing = getMetadata(LLVMContext::MD_annotation); SmallVector Names; - bool AppendName = true; if (Existing) { auto *Tuple = cast(Existing); for (auto &N : Tuple->operands()) { - if (cast(N.get())->getString() == Name) - AppendName = false; + if (isa(N.get()) && + cast(N.get())->getString() == Name) + return; Names.push_back(N.get()); } } - if (AppendName) - Names.push_back(MDB.createString(Name)); + Names.push_back(MDB.createString(Name)); MDNode *MD = MDTuple::get(getContext(), Names); setMetadata(LLVMContext::MD_annotation, MD); } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -4678,8 +4678,15 @@ Check(isa(Annotation), "annotation must be a tuple"); Check(Annotation->getNumOperands() >= 1, "annotation must have at least one operand"); - for (const MDOperand &Op : Annotation->operands()) - Check(isa(Op.get()), "operands must be strings"); + for (const MDOperand &Op : Annotation->operands()) { + bool TupleOfStrings = + isa(Op.get()) && + all_of(cast(Op)->operands(), [](auto &Annotation) { + return isa(Annotation.get()); + }); + Check(isa(Op.get()) || TupleOfStrings, + "operands must be a string or a tuple of strings"); + } } void Verifier::visitAliasScopeMetadata(const MDNode *MD) { diff --git a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp --- a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp +++ b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp @@ -1301,7 +1301,8 @@ if (Existing) { MDTuple *Tuple = cast(Existing); for (const auto &N : Tuple->operands()) { - if (cast(N.get())->getString() == MetadataName) + if (isa(N.get()) && + cast(N.get())->getString() == MetadataName) return; Names.push_back(N.get()); } diff --git a/llvm/lib/Transforms/Scalar/AnnotationRemarks.cpp b/llvm/lib/Transforms/Scalar/AnnotationRemarks.cpp --- a/llvm/lib/Transforms/Scalar/AnnotationRemarks.cpp +++ b/llvm/lib/Transforms/Scalar/AnnotationRemarks.cpp @@ -58,7 +58,15 @@ for (const MDOperand &Op : I.getMetadata(LLVMContext::MD_annotation)->operands()) { - auto Iter = Mapping.insert({cast(Op.get())->getString(), 0}); + StringRef AnnotationStr; + if (isa(Op.get())) + AnnotationStr = cast(Op.get())->getString(); + else { + auto *AnnotationTuple = cast(Op.get()); + AnnotationStr = + cast(AnnotationTuple->getOperand(0).get())->getString(); + } + auto Iter = Mapping.insert({AnnotationStr, 0}); Iter.first->second++; } } diff --git a/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp b/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp --- a/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp +++ b/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp @@ -387,7 +387,8 @@ return false; return any_of(I->getMetadata(LLVMContext::MD_annotation)->operands(), [](const MDOperand &Op) { - return cast(Op.get())->getString() == "auto-init"; + return isa(Op.get()) && + cast(Op.get())->getString() == "auto-init"; }); } diff --git a/llvm/test/Verifier/annotation-metadata.ll b/llvm/test/Verifier/annotation-metadata.ll --- a/llvm/test/Verifier/annotation-metadata.ll +++ b/llvm/test/Verifier/annotation-metadata.ll @@ -5,7 +5,7 @@ ; CHECK: annotation must have at least one operand %a.addr = alloca ptr, align 8, !annotation !0 -; CHECK-NEXT: operands must be strings +; CHECK-NEXT: operands must be a string or a tuple of strings ret void, !annotation !1 }