#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 {
// \brief Returns true if this terminator relates to exception handling.
bool isExceptional() const {
switch (getOpcode()) {
- case Instruction::CatchPad:
- case Instruction::CatchEndPad:
+ case Instruction::CatchSwitch:
case Instruction::CatchRet:
- case Instruction::CleanupEndPad:
case Instruction::CleanupRet:
case Instruction::Invoke:
case Instruction::Resume:
- case Instruction::TerminatePad:
return true;
default:
return false;
/// This class is the base class for the comparison instructions.
/// @brief Abstract base class of comparison instructions.
class CmpInst : public Instruction {
- void *operator new(size_t, unsigned) = delete;
- CmpInst() = delete;
-
-protected:
- CmpInst(Type *ty, Instruction::OtherOps op, unsigned short pred,
- Value *LHS, Value *RHS, const Twine &Name = "",
- Instruction *InsertBefore = nullptr);
-
- CmpInst(Type *ty, Instruction::OtherOps op, unsigned short pred,
- Value *LHS, Value *RHS, const Twine &Name,
- BasicBlock *InsertAtEnd);
-
- void anchor() override; // Out of line virtual method.
-
public:
/// This enumeration lists the possible predicates for CmpInst subclasses.
/// Values in the range 0-31 are reserved for FCmpInst, while values in the
BAD_ICMP_PREDICATE = ICMP_SLE + 1
};
+private:
+ void *operator new(size_t, unsigned) = delete;
+ CmpInst() = delete;
+
+protected:
+ CmpInst(Type *ty, Instruction::OtherOps op, Predicate pred,
+ Value *LHS, Value *RHS, const Twine &Name = "",
+ Instruction *InsertBefore = nullptr);
+
+ CmpInst(Type *ty, Instruction::OtherOps op, Predicate pred,
+ Value *LHS, Value *RHS, const Twine &Name,
+ BasicBlock *InsertAtEnd);
+
+ void anchor() override; // Out of line virtual method.
+
+public:
// allocate space for exactly two operands
void *operator new(size_t s) {
return User::operator new(s, 2);
/// The specified Instruction is allowed to be a dereferenced end iterator.
/// @brief Create a CmpInst
static CmpInst *Create(OtherOps Op,
- unsigned short predicate, Value *S1,
+ Predicate predicate, Value *S1,
Value *S2, const Twine &Name = "",
Instruction *InsertBefore = nullptr);
/// two operands. Also automatically insert this instruction to the end of
/// the BasicBlock specified.
/// @brief Create a CmpInst
- static CmpInst *Create(OtherOps Op, unsigned short predicate, Value *S1,
+ static CmpInst *Create(OtherOps Op, Predicate predicate, Value *S1,
Value *S2, const Twine &Name, BasicBlock *InsertAtEnd);
/// @brief Get the opcode casted to the right type
/// @returns true if the predicate is unsigned, false otherwise.
/// @brief Determine if the predicate is an unsigned operation.
- static bool isUnsigned(unsigned short predicate);
+ static bool isUnsigned(Predicate predicate);
/// @returns true if the predicate is signed, false otherwise.
/// @brief Determine if the predicate is an signed operation.
- static bool isSigned(unsigned short predicate);
+ static bool isSigned(Predicate predicate);
/// @brief Determine if the predicate is an ordered operation.
- static bool isOrdered(unsigned short predicate);
+ static bool isOrdered(Predicate predicate);
/// @brief Determine if the predicate is an unordered operation.
- static bool isUnordered(unsigned short predicate);
+ static bool isUnordered(Predicate predicate);
/// Determine if the predicate is true when comparing a value with itself.
- static bool isTrueWhenEqual(unsigned short predicate);
+ static bool isTrueWhenEqual(Predicate predicate);
/// Determine if the predicate is false when comparing a value with itself.
- static bool isFalseWhenEqual(unsigned short predicate);
+ static bool isFalseWhenEqual(Predicate predicate);
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CmpInst, Value)
+//===----------------------------------------------------------------------===//
+// FuncletPadInst Class
+//===----------------------------------------------------------------------===//
+class FuncletPadInst : public Instruction {
+private:
+ void init(Value *ParentPad, ArrayRef<Value *> Args, const Twine &NameStr);
+
+ FuncletPadInst(const FuncletPadInst &CPI);
+
+ explicit FuncletPadInst(Instruction::FuncletPadOps Op, Value *ParentPad,
+ ArrayRef<Value *> Args, unsigned Values,
+ const Twine &NameStr, Instruction *InsertBefore);
+ explicit FuncletPadInst(Instruction::FuncletPadOps Op, Value *ParentPad,
+ ArrayRef<Value *> Args, unsigned Values,
+ const Twine &NameStr, BasicBlock *InsertAtEnd);
+
+protected:
+ // Note: Instruction needs to be a friend here to call cloneImpl.
+ friend class Instruction;
+ friend class CatchPadInst;
+ friend class CleanupPadInst;
+ FuncletPadInst *cloneImpl() const;
+
+public:
+ /// Provide fast operand accessors
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
+ /// getNumArgOperands - Return the number of funcletpad arguments.
+ ///
+ unsigned getNumArgOperands() const { return getNumOperands() - 1; }
+
+ /// Convenience accessors
+
+ /// \brief Return the outer EH-pad this funclet is nested within.
+ ///
+ /// Note: This returns the associated CatchSwitchInst if this FuncletPadInst
+ /// is a CatchPadInst.
+ Value *getParentPad() const { return Op<-1>(); }
+ void setParentPad(Value *ParentPad) {
+ assert(ParentPad);
+ Op<-1>() = ParentPad;
+ }
+
+ /// getArgOperand/setArgOperand - Return/set the i-th funcletpad argument.
+ ///
+ Value *getArgOperand(unsigned i) const { return getOperand(i); }
+ void setArgOperand(unsigned i, Value *v) { setOperand(i, v); }
+
+ /// arg_operands - iteration adapter for range-for loops.
+ op_range arg_operands() { return op_range(op_begin(), op_end() - 1); }
+
+ /// arg_operands - iteration adapter for range-for loops.
+ const_op_range arg_operands() const {
+ return const_op_range(op_begin(), op_end() - 1);
+ }
+
+ // Methods for support type inquiry through isa, cast, and dyn_cast:
+ static inline bool classof(const Instruction *I) { return I->isFuncletPad(); }
+ static inline bool classof(const Value *V) {
+ return isa<Instruction>(V) && classof(cast<Instruction>(V));
+ }
+};
+
+template <>
+struct OperandTraits<FuncletPadInst>
+ : public VariadicOperandTraits<FuncletPadInst, /*MINARITY=*/1> {};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(FuncletPadInst, Value)
+
/// \brief A lightweight accessor for an operand bundle meant to be passed
/// around by value.
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;
};
return Tag->getValue();
}
+ /// \brief Return true if this is a "deopt" operand bundle.
+ bool isDeoptOperandBundle() const {
+ return getTagID() == LLVMContext::OB_deopt;
+ }
+
+ /// \brief Return true if this is a "funclet" operand bundle.
+ bool isFuncletOperandBundle() const {
+ return getTagID() == LLVMContext::OB_funclet;
+ }
+
private:
/// \brief Pointer to an entry in LLVMContextImpl::getOrInsertBundleTag.
StringMapEntry<uint32_t> *Tag;
std::vector<InputTy> Inputs;
public:
- explicit OperandBundleDefT(StringRef Tag, std::vector<InputTy> Inputs)
- : Tag(Tag), Inputs(std::move(Inputs)) {}
-
explicit OperandBundleDefT(std::string Tag, std::vector<InputTy> Inputs)
: Tag(std::move(Tag)), Inputs(std::move(Inputs)) {}
+ explicit OperandBundleDefT(std::string Tag, ArrayRef<InputTy> Inputs)
+ : Tag(std::move(Tag)), Inputs(Inputs) {}
explicit OperandBundleDefT(const OperandBundleUse &OBU) {
Tag = OBU.getTagName();
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 ||
+ BOI.Tag->second == LLVMContext::OB_funclet)
+ continue;
+
+ // This instruction has an operand bundle that is not known to us.
+ // 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);
}
+ /// \brief Return true if \p Other has the same sequence of operand bundle
+ /// tags with the same number of operands on each one of them as this
+ /// OperandBundleUser.
+ bool hasIdenticalOperandBundleSchema(
+ const OperandBundleUser<InstrTy, OpIteratorTy> &Other) const {
+ if (getNumOperandBundles() != Other.getNumOperandBundles())
+ return false;
+
+ return std::equal(bundle_op_info_begin(), bundle_op_info_end(),
+ Other.bundle_op_info_begin());
+ };
+
protected:
/// \brief Is the function attribute S disallowed by some operand bundle on
/// this operand bundle user?
/// \brief The index in the Use& vector where operands for this operand
/// bundle ends.
uint32_t End;
+
+ bool operator==(const BundleOpInfo &Other) const {
+ return Tag == Other.Tag && Begin == Other.Begin && End == Other.End;
+ }
};
/// \brief Simple helper function to map a BundleOpInfo to an
/// \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;