[llvm] r350109 - [CallSite removal] Add and flesh out APIs on the new `CallBase` base class that previously were only available on the `CallSite` wrapper.
Philip Reames via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 2 11:50:38 PST 2019
Thanks for staging this. Having the migration period will make this
much easier to handle downstream.
Philip
On 12/27/18 3:40 PM, Chandler Carruth via llvm-commits wrote:
> Author: chandlerc
> Date: Thu Dec 27 15:40:17 2018
> New Revision: 350109
>
> URL: http://llvm.org/viewvc/llvm-project?rev=350109&view=rev
> Log:
> [CallSite removal] Add and flesh out APIs on the new `CallBase` base class that previously were only available on the `CallSite` wrapper.
>
> Summary:
> This will make migrating code easier and generally seems like a good collection
> of API improvements.
>
> Some of these APIs seem like more consistent / better naming of existing
> ones. I've retained the old names for migration simplicit and am just
> adding the new ones in this commit. I'll try to garbage collect these
> once CallSite is gone.
>
> Subscribers: sanjoy, mcrosier, hiraditya, llvm-commits
>
> Differential Revision: https://reviews.llvm.org/D55638
>
> Modified:
> llvm/trunk/include/llvm/IR/InstrTypes.h
> llvm/trunk/lib/IR/Instructions.cpp
>
> Modified: llvm/trunk/include/llvm/IR/InstrTypes.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/InstrTypes.h?rev=350109&r1=350108&r2=350109&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/InstrTypes.h (original)
> +++ llvm/trunk/include/llvm/IR/InstrTypes.h Thu Dec 27 15:40:17 2018
> @@ -46,6 +46,10 @@
>
> namespace llvm {
>
> +namespace Intrinsic {
> +enum ID : unsigned;
> +}
> +
> //===----------------------------------------------------------------------===//
> // UnaryInstruction Class
> //===----------------------------------------------------------------------===//
> @@ -1040,6 +1044,9 @@ public:
> 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; }
>
> @@ -1048,6 +1055,47 @@ public:
> 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 {
> @@ -1056,25 +1104,33 @@ public:
>
> /// 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!");
> @@ -1096,7 +1152,20 @@ public:
> 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>(); }
>
> @@ -1113,6 +1182,17 @@ public:
> 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.
> @@ -1304,6 +1384,55 @@ public:
> 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(); }
>
> @@ -1324,6 +1453,11 @@ public:
> 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);
> @@ -1477,6 +1611,16 @@ public:
> 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 {
>
> Modified: llvm/trunk/lib/IR/Instructions.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Instructions.cpp?rev=350109&r1=350108&r2=350109&view=diff
> ==============================================================================
> --- llvm/trunk/lib/IR/Instructions.cpp (original)
> +++ llvm/trunk/lib/IR/Instructions.cpp Thu Dec 27 15:40:17 2018
> @@ -27,6 +27,7 @@
> #include "llvm/IR/Function.h"
> #include "llvm/IR/InstrTypes.h"
> #include "llvm/IR/Instruction.h"
> +#include "llvm/IR/Intrinsics.h"
> #include "llvm/IR/LLVMContext.h"
> #include "llvm/IR/Metadata.h"
> #include "llvm/IR/Module.h"
> @@ -254,6 +255,26 @@ void LandingPadInst::addClause(Constant
> // CallBase Implementation
> //===----------------------------------------------------------------------===//
>
> +Function *CallBase::getCaller() { return getParent()->getParent(); }
> +
> +Intrinsic::ID CallBase::getIntrinsicID() const {
> + if (auto *F = getCalledFunction())
> + return F->getIntrinsicID();
> + return Intrinsic::not_intrinsic;
> +}
> +
> +bool CallBase::isReturnNonNull() const {
> + if (hasRetAttr(Attribute::NonNull))
> + return true;
> +
> + if (getDereferenceableBytes(AttributeList::ReturnIndex) > 0 &&
> + !NullPointerIsDefined(getCaller(),
> + getType()->getPointerAddressSpace()))
> + return true;
> +
> + return false;
> +}
> +
> Value *CallBase::getReturnedArgOperand() const {
> unsigned Index;
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list