#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 {
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;
};
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;
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
/// \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:
/// \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
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;