X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FIR%2FInstrTypes.h;h=f0035ca3d4270e24e524beb8c3bb642af1d6b0e0;hb=aca81124422db568eb596f06fb0ae8e90118e71c;hp=191061148800121a7f9d4366e892d7c3e91b5f08;hpb=b9d057df5ce39af68f9a66143b3050ff855e6d62;p=oota-llvm.git diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index 19106114880..f0035ca3d42 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -1114,12 +1114,39 @@ 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. + /// + /// Currently there is no way to have attributes on operand bundles differ on + /// a per operand granularity. + bool operandsHaveAttr(Attribute::AttrKind A) const { + // 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 @@ -1135,6 +1162,14 @@ template struct OperandBundleDefT { OperandBundleDefT() {} explicit OperandBundleDefT(StringRef Tag, const std::vector &Inputs) : Tag(Tag), Inputs(Inputs) {} + + explicit OperandBundleDefT(StringRef Tag, std::vector &&Inputs) + : Tag(Tag), Inputs(Inputs) {} + + explicit OperandBundleDefT(const OperandBundleUse &OBU) { + Tag = OBU.getTagName(); + Inputs.insert(Inputs.end(), OBU.Inputs.begin(), OBU.Inputs.end()); + } }; typedef OperandBundleDefT OperandBundleDef; @@ -1196,27 +1231,35 @@ public: /// \brief Return true if this User has any operand bundles. bool hasOperandBundles() const { return getNumOperandBundles() != 0; } + /// \brief Return the index of the first bundle operand in the Use array. + unsigned getBundleOperandsStartIndex() const { + assert(hasOperandBundles() && "Don't call otherwise!"); + return bundle_op_info_begin()->Begin; + } + + /// \brief Return the index of the last bundle operand in the Use array. + unsigned getBundleOperandsEndIndex() const { + assert(hasOperandBundles() && "Don't call otherwise!"); + return bundle_op_info_end()[-1].End; + } + /// \brief Return the total number operands (not operand bundles) used by /// every operand bundle in this OperandBundleUser. unsigned getNumTotalBundleOperands() const { if (!hasOperandBundles()) return 0; - auto *Begin = bundle_op_info_begin(); - auto *Back = bundle_op_info_end() - 1; - - assert(Begin <= Back && "hasOperandBundles() returned true!"); + unsigned Begin = getBundleOperandsStartIndex(); + unsigned End = getBundleOperandsEndIndex(); - return Back->End - Begin->Begin; + assert(Begin <= End && "Should be!"); + return End - Begin; } /// \brief Return the operand bundle at a specific index. - OperandBundleUse getOperandBundle(unsigned Index) const { + OperandBundleUse getOperandBundleAt(unsigned Index) const { assert(Index < getNumOperandBundles() && "Index out of bounds!"); - auto *BOI = bundle_op_info_begin() + Index; - 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 operandBundleFromBundleOpInfo(*(bundle_op_info_begin() + Index)); } /// \brief Return the number of operand bundles with the tag Name attached to @@ -1224,7 +1267,18 @@ public: unsigned countOperandBundlesOfType(StringRef Name) const { unsigned Count = 0; for (unsigned i = 0, e = getNumOperandBundles(); i != e; ++i) - if (getOperandBundle(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; @@ -1238,14 +1292,42 @@ public: assert(countOperandBundlesOfType(Name) < 2 && "Precondition violated!"); for (unsigned i = 0, e = getNumOperandBundles(); i != e; ++i) { - OperandBundleUse U = getOperandBundle(i); - if (U.Tag == Name) + OperandBundleUse U = getOperandBundleAt(i); + 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; } return None; } + /// \brief Return the operand bundle for the operand at index OpIdx. + /// + /// It is an error to call this with an OpIdx that does not correspond to an + /// bundle operand. + OperandBundleUse getOperandBundleForOperand(unsigned OpIdx) const { + for (auto &BOI : bundle_op_infos()) + if (BOI.Begin <= OpIdx && OpIdx < BOI.End) + return operandBundleFromBundleOpInfo(BOI); + + llvm_unreachable("Did not find operand bundle for operand!"); + } + /// \brief Return true if this operand bundle user has operand bundles that /// may read from the heap. bool hasReadingOperandBundles() const { @@ -1309,6 +1391,15 @@ protected: uint32_t End; }; + /// \brief Simple helper function to map a BundleOpInfo to an + /// OperandBundleUse. + OperandBundleUse + 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, Inputs); + } + typedef BundleOpInfo *bundle_op_iterator; typedef const BundleOpInfo *const_bundle_op_iterator;