summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHal Finkel <hfinkel@anl.gov>2016-07-10 23:01:32 +0000
committerHal Finkel <hfinkel@anl.gov>2016-07-10 23:01:32 +0000
commit9a51ef1a5960fc2aa1f306e6e8f38798c8a0a253 (patch)
tree98c66dd5a5846c63bc766b4167181c352cde81b8
parent668cef03499627bb3c59011074bb55d557024481 (diff)
Add getReturnedArgOperand to Call/InvokeInst, CallSite
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@275031 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/IR/Attributes.h6
-rw-r--r--include/llvm/IR/CallSite.h4
-rw-r--r--include/llvm/IR/Instructions.h8
-rw-r--r--lib/IR/Attributes.cpp7
-rw-r--r--lib/IR/Instructions.cpp26
5 files changed, 47 insertions, 4 deletions
diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h
index 52d1a46602a..af1bf0a354e 100644
--- a/include/llvm/IR/Attributes.h
+++ b/include/llvm/IR/Attributes.h
@@ -338,8 +338,10 @@ public:
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;
diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h
index 3229d86651a..9c977aef941 100644
--- a/include/llvm/IR/CallSite.h
+++ b/include/llvm/IR/CallSite.h
@@ -273,6 +273,10 @@ public:
CALLSITE_DELEGATE_GETTER(getArgOperand(i));
}
+ ValTy *getReturnedArgOperand() const {
+ CALLSITE_DELEGATE_GETTER(getReturnedArgOperand());
+ }
+
bool isInlineAsm() const {
if (isCall())
return cast<CallInst>(getInstruction())->isInlineAsm();
diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h
index 15623ab0a71..be077725f7b 100644
--- a/include/llvm/IR/Instructions.h
+++ b/include/llvm/IR/Instructions.h
@@ -1597,6 +1597,10 @@ public:
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 {
@@ -3566,6 +3570,10 @@ public:
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 {
diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp
index b0a4cb6be55..d774c1ae9df 100644
--- a/lib/IR/Attributes.cpp
+++ b/lib/IR/Attributes.cpp
@@ -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;
}
diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp
index 6f60d15c52c..b9c693ff19a 100644
--- a/lib/IR/Instructions.cpp
+++ b/lib/IR/Instructions.cpp
@@ -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);
@@ -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!");