namespace llvm {
+namespace Intrinsic {
+enum ID : unsigned;
+}
+
//===----------------------------------------------------------------------===//
// UnaryInstruction Class
//===----------------------------------------------------------------------===//
return I->getOpcode() == Instruction::Call ||
I->getOpcode() == Instruction::Invoke;
}
+ static bool classof(const Value *V) {
+ return isa<Instruction>(V) && classof(cast<Instruction>(V));
+ }
FunctionType *getFunctionType() const { return FTy; }
this->FTy = FTy;
}
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
+ /// 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.
+ User::op_iterator data_operands_begin() { return op_begin(); }
+ User::const_op_iterator data_operands_begin() const {
+ return const_cast<CallBase *>(this)->data_operands_begin();
+ }
+ User::op_iterator data_operands_end() {
+ // Walk from the end of the operands over the called operand and any
+ // subclass operands.
+ return op_end() - getNumSubclassExtraOperands() - 1;
+ }
+ User::const_op_iterator data_operands_end() const {
+ return const_cast<CallBase *>(this)->data_operands_end();
+ }
+ iterator_range<User::op_iterator> data_ops() {
+ return make_range(data_operands_begin(), data_operands_end());
+ }
+ iterator_range<User::const_op_iterator> data_ops() const {
+ return make_range(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());
+ }
+
+ bool isDataOperand(const Use *U) const {
+ assert(this == U->getUser() &&
+ "Only valid to query with a use of this instruction!");
+ return data_operands_begin() <= U && U < data_operands_end();
+ }
+ bool isDataOperand(Value::const_user_iterator UI) const {
+ return isDataOperand(&UI.getUse());
+ }
+
/// Return the iterator pointing to the beginning of the argument list.
User::op_iterator arg_begin() { return op_begin(); }
User::const_op_iterator arg_begin() const {
/// Return the iterator pointing to the end of the argument list.
User::op_iterator arg_end() {
- // Walk from the end of the operands over the called operand, the subclass
- // operands, and any operands for bundles to find the end of the argument
+ // From the end of the data operands, walk backwards past the bundle
// operands.
- return op_end() - getNumTotalBundleOperands() -
- getNumSubclassExtraOperands() - 1;
+ return data_operands_end() - getNumTotalBundleOperands();
}
User::const_op_iterator arg_end() const {
return const_cast<CallBase *>(this)->arg_end();
}
/// Iteration adapter for range-for loops.
+ iterator_range<User::op_iterator> args() {
+ return make_range(arg_begin(), arg_end());
+ }
+ iterator_range<User::const_op_iterator> args() const {
+ return make_range(arg_begin(), arg_end());
+ }
+ bool arg_empty() const { return arg_end() == arg_begin(); }
+ unsigned arg_size() const { return arg_end() - arg_begin(); }
+
+ // Legacy API names that duplicate the above and will be removed once users
+ // are migrated.
iterator_range<User::op_iterator> arg_operands() {
return make_range(arg_begin(), arg_end());
}
iterator_range<User::const_op_iterator> arg_operands() const {
return make_range(arg_begin(), arg_end());
}
-
- unsigned getNumArgOperands() const { return arg_end() - arg_begin(); }
+ unsigned getNumArgOperands() const { return arg_size(); }
Value *getArgOperand(unsigned i) const {
assert(i < getNumArgOperands() && "Out of bounds!");
return User::getOperandUse(i);
}
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+ bool isArgOperand(const Use *U) const {
+ assert(this == U->getUser() &&
+ "Only valid to query with a use of this instruction!");
+ return arg_begin() <= U && U < arg_end();
+ }
+ bool isArgOperand(Value::const_user_iterator UI) const {
+ return isArgOperand(&UI.getUse());
+ }
+
+ /// Returns true if this CallSite passes the given Value* as an argument to
+ /// the called function.
+ bool hasArgument(const Value *V) const {
+ return llvm::any_of(args(), [V](const Value *Arg) { return Arg == V; });
+ }
Value *getCalledOperand() const { return Op<CalledOperandOpEndIdx>(); }
return dyn_cast_or_null<Function>(getCalledOperand());
}
+ /// Helper to get the caller (the parent function).
+ Function *getCaller();
+ const Function *getCaller() const {
+ return const_cast<CallBase *>(this)->getCaller();
+ }
+
+ /// Returns the intrinsic ID of the intrinsic called or
+ /// Intrinsic::not_intrinsic if the called function is not an intrinsic, or if
+ /// this is an indirect call.
+ Intrinsic::ID getIntrinsicID() const;
+
void setCalledOperand(Value *V) { Op<CalledOperandOpEndIdx>() = V; }
/// Sets the function called, including updating the function type.
return bundleOperandHasAttr(i - 1, Kind);
}
+ /// Determine whether this data operand is not captured.
+ // FIXME: Once this API is no longer duplicated in `CallSite`, rename this to
+ // better indicate that this may return a conservative answer.
+ bool doesNotCapture(unsigned OpNo) const {
+ return dataOperandHasImpliedAttr(OpNo + 1, Attribute::NoCapture);
+ }
+
+ /// Determine whether this argument is passed by value.
+ bool isByValArgument(unsigned ArgNo) const {
+ return paramHasAttr(ArgNo, Attribute::ByVal);
+ }
+
+ /// Determine whether this argument is passed in an alloca.
+ bool isInAllocaArgument(unsigned ArgNo) const {
+ return paramHasAttr(ArgNo, Attribute::InAlloca);
+ }
+
+ /// Determine whether this argument is passed by value or in an alloca.
+ bool isByValOrInAllocaArgument(unsigned ArgNo) const {
+ return paramHasAttr(ArgNo, Attribute::ByVal) ||
+ paramHasAttr(ArgNo, Attribute::InAlloca);
+ }
+
+ /// Determine if there are is an inalloca argument. Only the last argument can
+ /// have the inalloca attribute.
+ bool hasInAllocaArgument() const {
+ return !arg_empty() && paramHasAttr(arg_size() - 1, Attribute::InAlloca);
+ }
+
+ // FIXME: Once this API is no longer duplicated in `CallSite`, rename this to
+ // better indicate that this may return a conservative answer.
+ bool doesNotAccessMemory(unsigned OpNo) const {
+ return dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadNone);
+ }
+
+ // FIXME: Once this API is no longer duplicated in `CallSite`, rename this to
+ // better indicate that this may return a conservative answer.
+ bool onlyReadsMemory(unsigned OpNo) const {
+ return dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadOnly) ||
+ dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadNone);
+ }
+
+ // FIXME: Once this API is no longer duplicated in `CallSite`, rename this to
+ // better indicate that this may return a conservative answer.
+ bool doesNotReadMemory(unsigned OpNo) const {
+ return dataOperandHasImpliedAttr(OpNo + 1, Attribute::WriteOnly) ||
+ dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadNone);
+ }
+
/// Extract the alignment of the return value.
unsigned getRetAlignment() const { return Attrs.getRetAlignment(); }
return Attrs.getDereferenceableOrNullBytes(i);
}
+ /// Return true if the return value is known to be not null.
+ /// This may be because it has the nonnull attribute, or because at least
+ /// one byte is dereferenceable and the pointer is in addrspace(0).
+ bool isReturnNonNull() const;
+
/// Determine if the return value is marked with NoAlias attribute.
bool returnDoesNotAlias() const {
return Attrs.hasAttribute(AttributeList::ReturnIndex, Attribute::NoAlias);
Idx < getBundleOperandsEndIndex();
}
+ /// Returns true if the use is a bundle operand.
+ bool isBundleOperand(const Use *U) const {
+ assert(this == U->getUser() &&
+ "Only valid to query with a use of this instruction!");
+ return hasOperandBundles() && isBundleOperand(U - op_begin());
+ }
+ bool isBundleOperand(Value::const_user_iterator UI) const {
+ return isBundleOperand(&UI.getUse());
+ }
+
/// Return the total number operands (not operand bundles) used by
/// every operand bundle in this OperandBundleUser.
unsigned getNumTotalBundleOperands() const {