Use make_range to reduce mentions of iterator type. NFC
[oota-llvm.git] / include / llvm / IR / InstrTypes.h
index 737b46fbe337c00b57452edb2d0e962ae767e14d..157cb27cefbb45d9e6920359e5e062d8743f1c54 100644 (file)
@@ -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<uint32_t> *Tag, ArrayRef<Use> 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<uint32_t> *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<OperandBundleDef> &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_iterator> bundle_op_infos() {
-    return iterator_range<bundle_op_iterator>(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<const_bundle_op_iterator> bundle_op_infos() const {
-    return iterator_range<const_bundle_op_iterator>(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<OperandBundleDef> Bundles) {
     unsigned Total = 0;