#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 {
/// Currently there is no way to have attributes on operand bundles differ on
/// a per operand granularity.
bool operandsHaveAttr(Attribute::AttrKind A) const {
+ if (isDeoptOperandBundle())
+ return A == Attribute::ReadOnly || A == Attribute::NoCapture;
+
// 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;
/// 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 <typename InputTy> struct OperandBundleDefT {
+template <typename InputTy> class OperandBundleDefT {
std::string Tag;
std::vector<InputTy> Inputs;
- OperandBundleDefT() {}
- explicit OperandBundleDefT(StringRef Tag, const std::vector<InputTy> &Inputs)
- : Tag(Tag), Inputs(Inputs) {}
+public:
+ explicit OperandBundleDefT(StringRef Tag, std::vector<InputTy> Inputs)
+ : Tag(Tag), Inputs(std::move(Inputs)) {}
- explicit OperandBundleDefT(StringRef Tag, std::vector<InputTy> &&Inputs)
- : Tag(Tag), Inputs(Inputs) {}
+ explicit OperandBundleDefT(std::string Tag, std::vector<InputTy> 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<InputTy> inputs() const { return Inputs; }
+
+ typedef typename std::vector<InputTy>::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<Value *> OperandBundleDef;
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
/// \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;
}
protected:
const unsigned BeginIndex) {
auto It = static_cast<InstrTy *>(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<InstrTy *>(this)->getContext().pImpl;
auto BI = Bundles.begin();
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++;
}
static unsigned CountBundleInputs(ArrayRef<OperandBundleDef> Bundles) {
unsigned Total = 0;
for (auto &B : Bundles)
- Total += B.Inputs.size();
+ Total += B.input_size();
return Total;
}
};