X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FIR%2FInstrTypes.h;h=157cb27cefbb45d9e6920359e5e062d8743f1c54;hb=e6bc7d1f0d765d1e67a1c5d6c7a4f36677810c8e;hp=737b46fbe337c00b57452edb2d0e962ae767e14d;hpb=985201d38ceb7ddca755ae0b945327a5833255a4;p=oota-llvm.git diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index 737b46fbe33..157cb27cefb 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -21,6 +21,7 @@ #include "llvm/IR/Attributes.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Instruction.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/IR/OperandTraits.h" namespace llvm { @@ -1120,12 +1121,13 @@ struct OperandBundleUse { 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 { + /// \brief Return true if the operand at index \p Idx in this operand bundle + /// has the attribute A. + bool operandHasAttr(unsigned Idx, Attribute::AttrKind A) const { + if (isDeoptOperandBundle()) + if (A == Attribute::ReadOnly || A == Attribute::NoCapture) + return Inputs[Idx]->getType()->isPointerTy(); + // Conservative answer: no operands have any attributes. return false; }; @@ -1144,6 +1146,11 @@ struct OperandBundleUse { return Tag->getValue(); } + /// \brief Return true if this is a "deopt" operand bundle. + bool isDeoptOperandBundle() const { + return getTagID() == LLVMContext::OB_deopt; + } + private: /// \brief Pointer to an entry in LLVMContextImpl::getOrInsertBundleTag. StringMapEntry *Tag; @@ -1325,16 +1332,24 @@ public: return None; } + /// \brief Return the list of operand bundles attached to this instruction as + /// a vector of OperandBundleDefs. + /// + /// This function copies the OperandBundeUse instances associated with this + /// OperandBundleUser to a vector of OperandBundleDefs. Note: + /// OperandBundeUses and OperandBundleDefs are non-trivially *different* + /// representations of operand bundles (see documentation above). + void getOperandBundlesAsDefs(SmallVectorImpl &Defs) const { + for (unsigned i = 0, e = getNumOperandBundles(); i != e; ++i) + Defs.emplace_back(getOperandBundleAt(i)); + } + /// \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!"); + return operandBundleFromBundleOpInfo(getBundleOpInfoForOperand(OpIdx)); } /// \brief Return true if this operand bundle user has operand bundles that @@ -1349,10 +1364,24 @@ public: /// \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(); + for (auto &BOI : bundle_op_infos()) { + if (BOI.Tag->second == LLVMContext::OB_deopt) + continue; + + // This instruction has an operand bundle that is not a "deopt" operand + // bundle. Assume the worst. + return true; + } + + return false; + } + + /// \brief Return true if the bundle operand at index \p OpIdx has the + /// attribute \p A. + bool bundleOperandHasAttr(unsigned OpIdx, Attribute::AttrKind A) const { + auto &BOI = getBundleOpInfoForOperand(OpIdx); + auto OBU = operandBundleFromBundleOpInfo(BOI); + return OBU.operandHasAttr(OpIdx - BOI.Begin, A); } protected: @@ -1450,14 +1479,12 @@ protected: /// \brief Return the range [\p bundle_op_info_begin, \p bundle_op_info_end). iterator_range bundle_op_infos() { - return iterator_range(bundle_op_info_begin(), - bundle_op_info_end()); + return make_range(bundle_op_info_begin(), bundle_op_info_end()); } /// \brief Return the range [\p bundle_op_info_begin, \p bundle_op_info_end). iterator_range bundle_op_infos() const { - return iterator_range(bundle_op_info_begin(), - bundle_op_info_end()); + return make_range(bundle_op_info_begin(), bundle_op_info_end()); } /// \brief Populate the BundleOpInfo instances and the Use& vector from \p @@ -1491,6 +1518,18 @@ protected: return It; } + /// \brief Return the BundleOpInfo for the operand at index OpIdx. + /// + /// It is an error to call this with an OpIdx that does not correspond to an + /// bundle operand. + const BundleOpInfo &getBundleOpInfoForOperand(unsigned OpIdx) const { + for (auto &BOI : bundle_op_infos()) + if (BOI.Begin <= OpIdx && OpIdx < BOI.End) + return BOI; + + llvm_unreachable("Did not find operand bundle for operand!"); + } + /// \brief Return the total number of values used in \p Bundles. static unsigned CountBundleInputs(ArrayRef Bundles) { unsigned Total = 0;