bool arg_empty() const { return arg_end() == arg_begin(); }
unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); }
+ /// Type of iterator to use when looping over data operands at this call site
+ /// (see below).
+ typedef IterTy data_operand_iterator;
+
+ /// data_operands_begin/data_operands_end - Return iterators iterating over
+ /// the call / invoke argument list and bundle operands. For invokes, this is
+ /// the set of instruction operands except the invoke target and the two
+ /// successor blocks; and for calls this is the set of instruction operands
+ /// except the call target.
+
+ IterTy data_operands_begin() const {
+ assert(getInstruction() && "Not a call or invoke instruction!");
+ return (*this)->op_begin();
+ }
+ IterTy data_operands_end() const {
+ assert(getInstruction() && "Not a call or invoke instruction!");
+ return (*this)->op_end() - (isCall() ? 1 : 3);
+ }
+ iterator_range<IterTy> data_ops() const {
+ return iterator_range<IterTy>(data_operands_begin(), data_operands_end());
+ }
+ bool data_operands_empty() const {
+ return data_operands_end() == data_operands_begin();
+ }
+ unsigned data_operands_size() const {
+ return std::distance(data_operands_begin(), data_operands_end());
+ }
+
/// getType - Return the type of the instruction that generated this call site
///
Type *getType() const { return (*this)->getType(); }
CALLSITE_DELEGATE_GETTER(paramHasAttr(i, A));
}
+ /// \brief Return true if the data operand at index \p i directly or
+ /// indirectly has the attribute \p A.
+ ///
+ /// Normal call or invoke arguments have per operand attributes, as specified
+ /// in the attribute set attached to this instruction, while operand bundle
+ /// operands may have some attributes implied by the type of its containing
+ /// operand bundle.
+ bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind A) const {
+ CALLSITE_DELEGATE_GETTER(dataOperandHasImpliedAttr(i, A));
+ }
+
/// @brief Extract the alignment for a call or parameter (0=unknown).
uint16_t getParamAlignment(uint16_t i) const {
CALLSITE_DELEGATE_GETTER(getParamAlignment(i));
#undef CALLSITE_DELEGATE_GETTER
#undef CALLSITE_DELEGATE_SETTER
- /// @brief Determine whether this argument is not captured.
- bool doesNotCapture(unsigned ArgNo) const {
- return paramHasAttr(ArgNo + 1, Attribute::NoCapture);
+ /// @brief Determine whether this data operand is not captured.
+ bool doesNotCapture(unsigned OpNo) const {
+ return dataOperandHasImpliedAttr(OpNo + 1, Attribute::NoCapture);
}
/// @brief Determine whether this argument is passed by value.
return paramHasAttr(arg_size(), Attribute::InAlloca);
}
- bool doesNotAccessMemory(unsigned ArgNo) const {
- return paramHasAttr(ArgNo + 1, Attribute::ReadNone);
+ bool doesNotAccessMemory(unsigned OpNo) const {
+ return dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadNone);
}
- bool onlyReadsMemory(unsigned ArgNo) const {
- return paramHasAttr(ArgNo + 1, Attribute::ReadOnly) ||
- paramHasAttr(ArgNo + 1, Attribute::ReadNone);
+ bool onlyReadsMemory(unsigned OpNo) const {
+ return dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadOnly) ||
+ dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadNone);
}
/// @brief Return true if the return value is known to be not null.
OperandBundleUse() {}
explicit OperandBundleUse(StringRef Tag, ArrayRef<Use> Inputs)
: Tag(Tag), Inputs(Inputs) {}
+
+ /// \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 {
+ // Conservative answer: no operands have any attributes.
+ return false;
+ };
};
/// \brief A container for an operand bundle being viewed as a set of values
return None;
}
+ /// \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!");
+ }
+
/// \brief Return true if this operand bundle user has operand bundles that
/// may read from the heap.
bool hasReadingOperandBundles() const {
/// \brief Determine whether the call or the callee has the given attributes.
bool paramHasAttr(unsigned i, Attribute::AttrKind A) const;
+ /// \brief Return true if the data operand at index \p i has the attribute \p
+ /// A.
+ ///
+ /// Data operands include call arguments and values used in operand bundles,
+ /// but does not include the callee operand. This routine dispatches to the
+ /// underlying AttributeList or the OperandBundleUser as appropriate.
+ ///
+ /// The index \p i is interpreted as
+ ///
+ /// \p i == Attribute::ReturnIndex -> the return value
+ /// \p i in [1, arg_size + 1) -> argument number (\p i - 1)
+ /// \p i in [arg_size + 1, data_operand_size + 1) -> bundle operand at index
+ /// (\p i - 1) in the operand list.
+ bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind A) const;
+
/// \brief Extract the alignment for a call or parameter (0=unknown).
unsigned getParamAlignment(unsigned i) const {
return AttributeList.getParamAlignment(i);
/// \brief Determine whether the call or the callee has the given attributes.
bool paramHasAttr(unsigned i, Attribute::AttrKind A) const;
+ /// \brief Return true if the data operand at index \p i has the attribute \p
+ /// A.
+ ///
+ /// Data operands include invoke arguments and values used in operand bundles,
+ /// but does not include the invokee operand, or the two successor blocks.
+ /// This routine dispatches to the underlying AttributeList or the
+ /// OperandBundleUser as appropriate.
+ ///
+ /// The index \p i is interpreted as
+ ///
+ /// \p i == Attribute::ReturnIndex -> the return value
+ /// \p i in [1, arg_size + 1) -> argument number (\p i - 1)
+ /// \p i in [arg_size + 1, data_operand_size + 1) -> bundle operand at index
+ /// (\p i - 1) in the operand list.
+ bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind A) const;
+
/// \brief Extract the alignment for a call or parameter (0=unknown).
unsigned getParamAlignment(unsigned i) const {
return AttributeList.getParamAlignment(i);
return false;
}
+bool CallInst::dataOperandHasImpliedAttr(unsigned i,
+ Attribute::AttrKind A) const {
+
+ // The attribute A can either be directly specified, if the operand in
+ // question is a call argument; or be indirectly implied by the kind of its
+ // containing operand bundle, if the operand is a bundle operand.
+
+ if (i < (getNumArgOperands() + 1))
+ return paramHasAttr(i, A);
+
+ assert(hasOperandBundles() && i >= (getBundleOperandsStartIndex() + 1) &&
+ "Must be either a call argument or an operand bundle!");
+ return getOperandBundleForOperand(i - 1).operandsHaveAttr(A);
+}
+
/// IsConstantOne - Return true only if val is constant int 1
static bool IsConstantOne(Value *val) {
assert(val && "IsConstantOne does not work with nullptr val");
return false;
}
+bool InvokeInst::dataOperandHasImpliedAttr(unsigned i,
+ Attribute::AttrKind A) const {
+ // The attribute A can either be directly specified, if the operand in
+ // question is an invoke argument; or be indirectly implied by the kind of its
+ // containing operand bundle, if the operand is a bundle operand.
+
+ if (i < (getNumArgOperands() + 1))
+ return paramHasAttr(i, A);
+
+ assert(hasOperandBundles() && i >= (getBundleOperandsStartIndex() + 1) &&
+ "Must be either an invoke argument or an operand bundle!");
+ return getOperandBundleForOperand(i - 1).operandsHaveAttr(A);
+}
+
void InvokeInst::addAttribute(unsigned i, Attribute::AttrKind attr) {
AttributeSet PAL = getAttributes();
PAL = PAL.addAttribute(getContext(), i, attr);