X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=include%2Fllvm%2FIR%2FInstrTypes.h;h=e6ebc87d1e0f13b0a1613ae6b14cb15ffe019976;hb=26b7bf38ac14e6b01d6a267235dbcf1313711c24;hp=a6a470ff6c33dab438ed0eb1eb34fcabad04e766;hpb=5b674c0b49619bc95ab27abfeffc25fb4b0cc71a;p=oota-llvm.git diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index a6a470ff6c3..e6ebc87d1e0 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -16,7 +16,9 @@ #ifndef LLVM_IR_INSTRTYPES_H #define LLVM_IR_INSTRTYPES_H +#include "llvm/ADT/Optional.h" #include "llvm/ADT/Twine.h" +#include "llvm/IR/Attributes.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/OperandTraits.h" @@ -687,7 +689,7 @@ public: Value *S, ///< The pointer value to be casted (operand 0) Type *Ty, ///< The type to which cast should be made const Twine &Name = "", ///< Name for the instruction - Instruction *InsertBefore = 0 ///< Place to insert the instruction + Instruction *InsertBefore = nullptr ///< Place to insert the instruction ); /// @brief Create a BitCast, a PtrToInt, or an IntToPTr cast instruction. @@ -700,7 +702,7 @@ public: Value *S, ///< The pointer value to be casted (operand 0) Type *Ty, ///< The type to which cast should be made const Twine &Name = "", ///< Name for the instruction - Instruction *InsertBefore = 0 ///< Place to insert the instruction + Instruction *InsertBefore = nullptr ///< Place to insert the instruction ); /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. @@ -1031,6 +1033,19 @@ public: return isUnsigned(getPredicate()); } + /// For example, ULT->SLT, ULE->SLE, UGT->SGT, UGE->SGE, SLT->Failed assert + /// @returns the signed version of the unsigned predicate pred. + /// @brief return the signed version of a predicate + static Predicate getSignedPredicate(Predicate pred); + + /// For example, ULT->SLT, ULE->SLE, UGT->SGT, UGE->SGE, SLT->Failed assert + /// @returns the signed version of the predicate for this instruction (which + /// has to be an unsigned predicate). + /// @brief return the signed version of a predicate + Predicate getSignedPredicate() { + return getSignedPredicate(getPredicate()); + } + /// This is just a convenience. /// @brief Determine if this is true when both operands are the same. bool isTrueWhenEqual() const { @@ -1099,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 @@ -1113,13 +1155,30 @@ struct OperandBundleUse { /// Unlike OperandBundleUse, OperandBundleDefT owns the memory it carries, and /// so it is possible to create and pass around "self-contained" instances of /// OperandBundleDef and ConstOperandBundleDef. -template struct OperandBundleDefT { +template class OperandBundleDefT { std::string Tag; std::vector Inputs; - OperandBundleDefT() {} - explicit OperandBundleDefT(StringRef Tag, const std::vector &Inputs) +public: + explicit OperandBundleDefT(StringRef Tag, std::vector &&Inputs) : Tag(Tag), Inputs(Inputs) {} + + explicit OperandBundleDefT(std::string &&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()); + } + + ArrayRef getInputs() const { return Inputs; } + + typedef typename std::vector::const_iterator input_iterator; + size_t input_size() const { return Inputs.size(); } + input_iterator input_begin() const { return Inputs.begin(); } + input_iterator input_end() const { return Inputs.end(); } + + StringRef getTag() const { return Tag; } }; typedef OperandBundleDefT OperandBundleDef; @@ -1134,19 +1193,19 @@ typedef OperandBundleDefT ConstOperandBundleDef; /// /// The layout of an operand bundle user is /// -/// +-------uint32_t End---------------------------------+ -/// / \ -/// / +------uint32_t Begin------------------+ \ -/// / / \ \ +/// +-----------uint32_t End-------------------------------------+ +/// | | +/// | +--------uint32_t Begin--------------------+ | +/// | | | | /// ^ ^ v v /// |------|------|----|----|----|----|----|---------|----|---------|----|----- /// | BOI0 | BOI1 | .. | DU | U0 | U1 | .. | BOI0_U0 | .. | BOI1_U0 | .. | Un /// |------|------|----|----|----|----|----|---------|----|---------|----|----- /// v v ^ ^ -/// \ \ / / -/// \ +------uint32_t Begin----------+ / -/// \ / -/// +-------uint32_t End-------------------------+ +/// | | | | +/// | +--------uint32_t Begin------------+ | +/// | | +/// +-----------uint32_t End-----------------------------+ /// /// /// BOI0, BOI1 ... are descriptions of operand bundles in this User's use list. @@ -1181,39 +1240,150 @@ 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 operand bundle at a specific index. - OperandBundleUse getOperandBundle(unsigned Index) { - 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); + /// \brief Return the number of operand bundles with the tag Name attached to + /// this instruction. + unsigned countOperandBundlesOfType(StringRef Name) const { + unsigned Count = 0; + for (unsigned i = 0, e = getNumOperandBundles(); i != e; ++i) + 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; + } + + /// \brief Return an operand bundle by name, 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(StringRef Name) const { + assert(countOperandBundlesOfType(Name) < 2 && "Precondition violated!"); + + for (unsigned i = 0, e = getNumOperandBundles(); i != e; ++i) { + 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 { + // Implementation note: this is a conservative implementation of operand + // bundle semantics, where *any* operand bundle forces a callsite to be at + // least readonly. + return hasOperandBundles(); + } + + /// \brief Return true if this operand bundle user has operand bundles that + /// may write to the heap. + bool hasClobberingOperandBundles() const { + // Implementation note: this is a conservative implementation of operand + // bundle semantics, where *any* operand bundle forces a callsite to be + // read-write. + return hasOperandBundles(); } protected: + /// \brief Is the function attribute S disallowed by some operand bundle on + /// this operand bundle user? + bool isFnAttrDisallowedByOpBundle(StringRef S) const { + // Operand bundles only possibly disallow readnone, readonly and argmenonly + // attributes. All String attributes are fine. + return false; + } + + /// \brief Is the function attribute A disallowed by some operand bundle on + /// this operand bundle user? + bool isFnAttrDisallowedByOpBundle(Attribute::AttrKind A) const { + switch (A) { + default: + return false; + + case Attribute::ArgMemOnly: + return hasReadingOperandBundles(); + + case Attribute::ReadNone: + return hasReadingOperandBundles(); + + case Attribute::ReadOnly: + return hasClobberingOperandBundles(); + } + + llvm_unreachable("switch has a default case!"); + } + /// \brief Used to keep track of an operand bundle. See the main comment on /// OperandBundleUser above. struct BundleOpInfo { @@ -1230,6 +1400,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; @@ -1291,7 +1470,7 @@ protected: const unsigned BeginIndex) { auto It = static_cast(this)->op_begin() + BeginIndex; for (auto &B : Bundles) - It = std::copy(B.Inputs.begin(), B.Inputs.end(), It); + It = std::copy(B.input_begin(), B.input_end(), It); auto *ContextImpl = static_cast(this)->getContext().pImpl; auto BI = Bundles.begin(); @@ -1300,9 +1479,9 @@ protected: for (auto &BOI : bundle_op_infos()) { assert(BI != Bundles.end() && "Incorrect allocation?"); - BOI.Tag = ContextImpl->getOrInsertBundleTag(BI->Tag); + BOI.Tag = ContextImpl->getOrInsertBundleTag(BI->getTag()); BOI.Begin = CurrentIndex; - BOI.End = CurrentIndex + BI->Inputs.size(); + BOI.End = CurrentIndex + BI->input_size(); CurrentIndex = BOI.End; BI++; } @@ -1316,11 +1495,11 @@ protected: static unsigned CountBundleInputs(ArrayRef Bundles) { unsigned Total = 0; for (auto &B : Bundles) - Total += B.Inputs.size(); + Total += B.input_size(); return Total; } }; -} // End llvm namespace +} // end llvm namespace -#endif +#endif // LLVM_IR_INSTRTYPES_H