diff --git a/llvm/include/llvm/IR/CallSite.h b/llvm/include/llvm/IR/CallSite.h index ffea707a32de..820f96356c67 100644 --- a/llvm/include/llvm/IR/CallSite.h +++ b/llvm/include/llvm/IR/CallSite.h @@ -383,6 +383,10 @@ public: CALLSITE_DELEGATE_GETTER(getOperandBundle(Name)); } + Optional getOperandBundle(uint32_t ID) const { + CALLSITE_DELEGATE_GETTER(getOperandBundle(ID)); + } + #undef CALLSITE_DELEGATE_GETTER #undef CALLSITE_DELEGATE_SETTER diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h index e96f7ad10363..815fb73be065 100644 --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -1114,12 +1114,11 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CmpInst, Value) /// \brief A lightweight accessor for an operand bundle meant to be passed /// around by value. struct OperandBundleUse { - StringRef Tag; ArrayRef Inputs; OperandBundleUse() {} - explicit OperandBundleUse(StringRef Tag, ArrayRef Inputs) - : Tag(Tag), Inputs(Inputs) {} + explicit OperandBundleUse(StringMapEntry *Tag, ArrayRef Inputs) + : Inputs(Inputs), Tag(Tag) {} /// \brief Return true if all the operands in this operand bundle have the /// attribute A. @@ -1130,6 +1129,24 @@ struct OperandBundleUse { // Conservative answer: no operands have any attributes. return false; }; + + /// \brief Return the tag of this operand bundle as a string. + StringRef getTagName() const { + return Tag->getKey(); + } + + /// \brief Return the tag of this operand bundle as an integer. + /// + /// Operand bundle tags are interned by LLVMContextImpl::getOrInsertBundleTag, + /// and this function returns the unique integer getOrInsertBundleTag + /// associated the tag of this operand bundle to. + uint32_t getTagID() const { + return Tag->getValue(); + } + +private: + /// \brief Pointer to an entry in LLVMContextImpl::getOrInsertBundleTag. + StringMapEntry *Tag; }; /// \brief A container for an operand bundle being viewed as a set of values @@ -1242,7 +1259,18 @@ public: unsigned countOperandBundlesOfType(StringRef Name) const { unsigned Count = 0; for (unsigned i = 0, e = getNumOperandBundles(); i != e; ++i) - if (getOperandBundleAt(i).Tag == Name) + if (getOperandBundleAt(i).getTagName() == Name) + Count++; + + return Count; + } + + /// \brief Return the number of operand bundles with the tag ID attached to + /// this instruction. + unsigned countOperandBundlesOfType(uint32_t ID) const { + unsigned Count = 0; + for (unsigned i = 0, e = getNumOperandBundles(); i != e; ++i) + if (getOperandBundleAt(i).getTagID() == ID) Count++; return Count; @@ -1257,7 +1285,23 @@ public: for (unsigned i = 0, e = getNumOperandBundles(); i != e; ++i) { OperandBundleUse U = getOperandBundleAt(i); - if (U.Tag == Name) + if (U.getTagName() == Name) + return U; + } + + return None; + } + + /// \brief Return an operand bundle by tag ID, if present. + /// + /// It is an error to call this for operand bundle types that may have + /// multiple instances of them on the same instruction. + Optional getOperandBundle(uint32_t ID) const { + assert(countOperandBundlesOfType(ID) < 2 && "Precondition violated!"); + + for (unsigned i = 0, e = getNumOperandBundles(); i != e; ++i) { + OperandBundleUse U = getOperandBundleAt(i); + if (U.getTagID() == ID) return U; } @@ -1345,7 +1389,7 @@ protected: operandBundleFromBundleOpInfo(const BundleOpInfo &BOI) const { auto op_begin = static_cast(this)->op_begin(); ArrayRef Inputs(op_begin + BOI.Begin, op_begin + BOI.End); - return OperandBundleUse(BOI.Tag->getKey(), Inputs); + return OperandBundleUse(BOI.Tag, Inputs); } typedef BundleOpInfo *bundle_op_iterator; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index b5b79b26873c..845bbfb8d363 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1739,7 +1739,7 @@ static void WriteOperandBundles(BitstreamWriter &Stream, ImmutableCallSite CS, for (unsigned i = 0, e = CS.getNumOperandBundles(); i != e; ++i) { const auto &Bundle = CS.getOperandBundleAt(i); - Record.push_back(C.getOperandBundleTagID(Bundle.Tag)); + Record.push_back(C.getOperandBundleTagID(Bundle.getTagName())); for (auto &Input : Bundle.Inputs) PushValueAndType(Input, InstID, Record, VE); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 1816ea2102be..aaa719eda7e1 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -2176,7 +2176,7 @@ void AssemblyWriter::writeOperandBundles(ImmutableCallSite CS) { FirstBundle = false; Out << '"'; - PrintEscapedString(BU.Tag, Out); + PrintEscapedString(BU.getTagName(), Out); Out << '"'; Out << '(';