X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FIR%2FInstrTypes.h;h=157cb27cefbb45d9e6920359e5e062d8743f1c54;hb=e6bc7d1f0d765d1e67a1c5d6c7a4f36677810c8e;hp=815fb73be06514bb1b96a925478cc4874548c91a;hpb=ef40fb975f4311c7452d6aa5fae769d703cbd527;p=oota-llvm.git diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index 815fb73be06..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; @@ -1155,13 +1162,30 @@ private: /// 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) - : Tag(Tag), Inputs(Inputs) {} +public: + explicit OperandBundleDefT(StringRef Tag, std::vector Inputs) + : Tag(Tag), Inputs(std::move(Inputs)) {} + + explicit OperandBundleDefT(std::string Tag, std::vector Inputs) + : Tag(std::move(Tag)), Inputs(std::move(Inputs)) {} + + explicit OperandBundleDefT(const OperandBundleUse &OBU) { + Tag = OBU.getTagName(); + Inputs.insert(Inputs.end(), OBU.Inputs.begin(), OBU.Inputs.end()); + } + + ArrayRef inputs() 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; @@ -1308,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 @@ -1332,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: @@ -1433,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 @@ -1453,7 +1497,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(); @@ -1462,9 +1506,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++; } @@ -1474,11 +1518,23 @@ 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; for (auto &B : Bundles) - Total += B.Inputs.size(); + Total += B.input_size(); return Total; } };