Skip to content

Commit

Permalink
Add getReturnedArgOperand to Call/InvokeInst, CallSite
Browse files Browse the repository at this point in the history
In order to make the optimizer smarter about using the 'returned' argument
attribute (generally, but motivated by my llvm.noalias intrinsic work), add a
utility function to Call/InvokeInst, and CallSite, to make it easy to get the
returned call argument (when one exists).

P.S. There is already an unfortunate amount of code duplication between
CallInst and InvokeInst, and this adds to it. We should probably clean that up
separately.

Differential Revision: http://reviews.llvm.org/D22204

llvm-svn: 275031
  • Loading branch information
Hal Finkel committed Jul 10, 2016
1 parent d7e03a5 commit e87ad54
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 4 deletions.
6 changes: 4 additions & 2 deletions llvm/include/llvm/IR/Attributes.h
Expand Up @@ -338,8 +338,10 @@ class AttributeSet {
bool hasFnAttribute(Attribute::AttrKind Kind) const;

/// \brief Return true if the specified attribute is set for at least one
/// parameter or for the return value.
bool hasAttrSomewhere(Attribute::AttrKind Kind) const;
/// parameter or for the return value. If Index is not nullptr, the index
/// of a parameter with the specified attribute is provided.
bool hasAttrSomewhere(Attribute::AttrKind Kind,
unsigned *Index = nullptr) const;

/// \brief Return the attribute object that exists at the given index.
Attribute getAttribute(unsigned Index, Attribute::AttrKind Kind) const;
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/IR/CallSite.h
Expand Up @@ -273,6 +273,10 @@ class CallSiteBase {
CALLSITE_DELEGATE_GETTER(getArgOperand(i));
}

ValTy *getReturnedArgOperand() const {
CALLSITE_DELEGATE_GETTER(getReturnedArgOperand());
}

bool isInlineAsm() const {
if (isCall())
return cast<CallInst>(getInstruction())->isInlineAsm();
Expand Down
8 changes: 8 additions & 0 deletions llvm/include/llvm/IR/Instructions.h
Expand Up @@ -1597,6 +1597,10 @@ class CallInst : public Instruction,
return getOperandUse(i);
}

/// If one of the arguments has the 'returned' attribute, return its
/// operand value. Otherwise, return nullptr.
Value *getReturnedArgOperand() const;

/// getCallingConv/setCallingConv - Get or set the calling convention of this
/// function call.
CallingConv::ID getCallingConv() const {
Expand Down Expand Up @@ -3566,6 +3570,10 @@ class InvokeInst : public TerminatorInst,
return getOperandUse(i);
}

/// If one of the arguments has the 'returned' attribute, return its
/// operand value. Otherwise, return nullptr.
Value *getReturnedArgOperand() const;

/// getCallingConv/setCallingConv - Get or set the calling convention of this
/// function call.
CallingConv::ID getCallingConv() const {
Expand Down
7 changes: 5 additions & 2 deletions llvm/lib/IR/Attributes.cpp
Expand Up @@ -1108,14 +1108,17 @@ bool AttributeSet::hasFnAttribute(Attribute::AttrKind Kind) const {
return pImpl && pImpl->hasFnAttribute(Kind);
}

bool AttributeSet::hasAttrSomewhere(Attribute::AttrKind Attr) const {
bool AttributeSet::hasAttrSomewhere(Attribute::AttrKind Attr,
unsigned *Index) const {
if (!pImpl) return false;

for (unsigned I = 0, E = pImpl->getNumSlots(); I != E; ++I)
for (AttributeSetImpl::iterator II = pImpl->begin(I),
IE = pImpl->end(I); II != IE; ++II)
if (II->hasAttribute(Attr))
if (II->hasAttribute(Attr)) {
if (Index) *Index = pImpl->getSlotIndex(I);
return true;
}

return false;
}
Expand Down
26 changes: 26 additions & 0 deletions llvm/lib/IR/Instructions.cpp
Expand Up @@ -331,6 +331,19 @@ CallInst *CallInst::Create(CallInst *CI, ArrayRef<OperandBundleDef> OpB,
return NewCI;
}

Value *CallInst::getReturnedArgOperand() const {
unsigned Index;

if (AttributeList.hasAttrSomewhere(Attribute::Returned, &Index) && Index)
return getArgOperand(Index-1);
if (const Function *F = getCalledFunction())
if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) &&
Index)
return getArgOperand(Index-1);

return nullptr;
}

void CallInst::addAttribute(unsigned i, Attribute::AttrKind Kind) {
AttributeSet PAL = getAttributes();
PAL = PAL.addAttribute(getContext(), i, Kind);
Expand Down Expand Up @@ -688,6 +701,19 @@ void InvokeInst::setSuccessorV(unsigned idx, BasicBlock *B) {
return setSuccessor(idx, B);
}

Value *InvokeInst::getReturnedArgOperand() const {
unsigned Index;

if (AttributeList.hasAttrSomewhere(Attribute::Returned, &Index) && Index)
return getArgOperand(Index-1);
if (const Function *F = getCalledFunction())
if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) &&
Index)
return getArgOperand(Index-1);

return nullptr;
}

bool InvokeInst::paramHasAttr(unsigned i, Attribute::AttrKind Kind) const {
assert(i < (getNumArgOperands() + 1) && "Param index out of bounds!");

Expand Down

0 comments on commit e87ad54

Please sign in to comment.