[llvm] r350109 - [CallSite removal] Add and flesh out APIs on the new `CallBase` base class that previously were only available on the `CallSite` wrapper.

Chandler Carruth via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 2 19:02:27 PST 2019


There is more we can do here if needed.

For example, I can add a bunch of compatibility wrappers around methods to
reduce the churn required if people want. So far, I'm only adding the ones
that I can't power through or handle with regular expression rewrites.

I'm working really hard to get this interim state cleaned up prior to the
branch.

-Chandler

On Wed, Jan 2, 2019 at 11:50 AM Philip Reames <listmail at philipreames.com>
wrote:

> 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190102/5cef6182/attachment.html>


More information about the llvm-commits mailing list