1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

[IR] Abstract away ArgNo+1 attribute indexing as much as possible

Summary:
Do three things to help with that:
- Add AttributeList::FirstArgIndex, which is an enumerator currently set
  to 1. It allows us to change the indexing scheme with fewer changes.
- Add addParamAttr/removeParamAttr. This just shortens addAttribute call
  sites that would otherwise need to spell out FirstArgIndex.
- Remove some attribute-specific getters and setters from Function that
  take attribute list indices.  Most of these were only used from
  BuildLibCalls, and doesNotAlias was only used to test or set if the
  return value is malloc-like.

I'm happy to split the patch, but I think they are probably easier to
review when taken together.

This patch should be NFC, but it sets the stage to change the indexing
scheme to this, which is more convenient when indexing into an array:
  0: func attrs
  1: retattrs
  2...: arg attrs

Reviewers: chandlerc, pete, javed.absar

Subscribers: david2050, llvm-commits

Differential Revision: https://reviews.llvm.org/D32811

llvm-svn: 302060
This commit is contained in:
Reid Kleckner 2017-05-03 18:17:31 +00:00
parent eed883ed5d
commit 822117c56d
25 changed files with 323 additions and 298 deletions

View File

@ -285,7 +285,8 @@ class AttributeList {
public:
enum AttrIndex : unsigned {
ReturnIndex = 0U,
FunctionIndex = ~0U
FunctionIndex = ~0U,
FirstArgIndex = 1,
};
private:
@ -336,6 +337,13 @@ public:
static AttributeList get(LLVMContext &C, unsigned Index,
const AttrBuilder &B);
/// Add an argument attribute to the list. Returns a new list because
/// attribute lists are immutable.
AttributeList addParamAttribute(LLVMContext &C, unsigned ArgNo,
Attribute::AttrKind Kind) const {
return addAttribute(C, ArgNo + FirstArgIndex, Kind);
}
/// \brief Add an attribute to the attribute set at the given index. Because
/// attribute sets are immutable, this returns a new set.
AttributeList addAttribute(LLVMContext &C, unsigned Index,
@ -433,7 +441,7 @@ public:
/// may be faster.
bool hasFnAttribute(StringRef Kind) const;
/// \brief Equivalent to hasAttribute(ArgNo + 1, Kind).
/// \brief Equivalent to hasAttribute(ArgNo + FirstArgIndex, Kind).
bool hasParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const;
/// \brief Return true if the specified attribute is set for at least one

View File

@ -339,6 +339,10 @@ public:
CALLSITE_DELEGATE_SETTER(addAttribute(i, Attr));
}
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
CALLSITE_DELEGATE_SETTER(addParamAttr(ArgNo, Kind));
}
void removeAttribute(unsigned i, Attribute::AttrKind Kind) {
CALLSITE_DELEGATE_SETTER(removeAttribute(i, Kind));
}
@ -347,6 +351,10 @@ public:
CALLSITE_DELEGATE_SETTER(removeAttribute(i, Kind));
}
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
CALLSITE_DELEGATE_SETTER(removeParamAttr(ArgNo, Kind));
}
/// Return true if this function has the given attribute.
bool hasFnAttr(Attribute::AttrKind Kind) const {
CALLSITE_DELEGATE_GETTER(hasFnAttr(Kind));
@ -408,11 +416,9 @@ public:
CALLSITE_DELEGATE_GETTER(getDereferenceableOrNullBytes(i));
}
/// Determine if the parameter or return value is marked with NoAlias
/// attribute.
/// @param n The parameter to check. 1 is the first parameter, 0 is the return
bool doesNotAlias(unsigned n) const {
CALLSITE_DELEGATE_GETTER(doesNotAlias(n));
/// Determine if the return value is marked with NoAlias attribute.
bool returnDoesNotAlias() const {
CALLSITE_DELEGATE_GETTER(returnDoesNotAlias());
}
/// Return true if the call should not be treated as a call to a builtin.

View File

@ -204,6 +204,10 @@ public:
addAttribute(AttributeList::FunctionIndex, Attr);
}
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
addAttribute(ArgNo + AttributeList::FirstArgIndex, Kind);
}
/// @brief Remove function attributes from this function.
void removeFnAttr(Attribute::AttrKind Kind) {
removeAttribute(AttributeList::FunctionIndex, Kind);
@ -211,10 +215,14 @@ public:
/// @brief Remove function attribute from this function.
void removeFnAttr(StringRef Kind) {
setAttributes(AttributeSets.removeAttribute(
setAttributes(getAttributes().removeAttribute(
getContext(), AttributeList::FunctionIndex, Kind));
}
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
removeAttribute(ArgNo + AttributeList::FirstArgIndex, Kind);
}
/// \brief Set the entry count for this function.
///
/// Entry count is the number of times this function was executed based on
@ -459,35 +467,12 @@ public:
/// @brief Determine if the parameter or return value is marked with NoAlias
/// attribute.
/// @param n The parameter to check. 1 is the first parameter, 0 is the return
bool doesNotAlias(unsigned n) const {
return AttributeSets.hasAttribute(n, Attribute::NoAlias);
bool returnDoesNotAlias() const {
return AttributeSets.hasAttribute(AttributeList::ReturnIndex,
Attribute::NoAlias);
}
void setDoesNotAlias(unsigned n) {
addAttribute(n, Attribute::NoAlias);
}
/// @brief Determine if the parameter can be captured.
/// @param n The parameter to check. 1 is the first parameter, 0 is the return
bool doesNotCapture(unsigned n) const {
return AttributeSets.hasAttribute(n, Attribute::NoCapture);
}
void setDoesNotCapture(unsigned n) {
addAttribute(n, Attribute::NoCapture);
}
bool doesNotAccessMemory(unsigned n) const {
return AttributeSets.hasAttribute(n, Attribute::ReadNone);
}
void setDoesNotAccessMemory(unsigned n) {
addAttribute(n, Attribute::ReadNone);
}
bool onlyReadsMemory(unsigned n) const {
return doesNotAccessMemory(n) ||
AttributeSets.hasAttribute(n, Attribute::ReadOnly);
}
void setOnlyReadsMemory(unsigned n) {
addAttribute(n, Attribute::ReadOnly);
void setReturnDoesNotAlias() {
addAttribute(AttributeList::ReturnIndex, Attribute::NoAlias);
}
/// Optimize this function for minimum size (-Oz).

View File

@ -1658,12 +1658,18 @@ public:
/// adds the attribute to the list of attributes.
void addAttribute(unsigned i, Attribute Attr);
/// Adds the attribute to the indicated argument
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
/// removes the attribute from the list of attributes.
void removeAttribute(unsigned i, Attribute::AttrKind Kind);
/// removes the attribute from the list of attributes.
void removeAttribute(unsigned i, StringRef Kind);
/// Removes the attribute from the given argument
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
/// adds the dereferenceable attribute to the list of attributes.
void addDereferenceableAttr(unsigned i, uint64_t Bytes);
@ -1734,11 +1740,9 @@ public:
return Attrs.getDereferenceableOrNullBytes(i);
}
/// @brief Determine if the parameter or return value is marked with NoAlias
/// attribute.
/// @param n The parameter to check. 1 is the first parameter, 0 is the return
bool doesNotAlias(unsigned n) const {
return Attrs.hasAttribute(n, Attribute::NoAlias);
/// @brief Determine if the return value is marked with NoAlias attribute.
bool returnDoesNotAlias() const {
return Attrs.hasAttribute(AttributeList::ReturnIndex, Attribute::NoAlias);
}
/// Return true if the call should not be treated as a call to a
@ -3750,12 +3754,18 @@ public:
/// adds the attribute to the list of attributes.
void addAttribute(unsigned i, Attribute Attr);
/// Adds the attribute to the indicated argument
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
/// removes the attribute from the list of attributes.
void removeAttribute(unsigned i, Attribute::AttrKind Kind);
/// removes the attribute from the list of attributes.
void removeAttribute(unsigned i, StringRef Kind);
/// Removes the attribute from the given argument
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind);
/// adds the dereferenceable attribute to the list of attributes.
void addDereferenceableAttr(unsigned i, uint64_t Bytes);
@ -3827,11 +3837,9 @@ public:
return Attrs.getDereferenceableOrNullBytes(i);
}
/// @brief Determine if the parameter or return value is marked with NoAlias
/// attribute.
/// @param n The parameter to check. 1 is the first parameter, 0 is the return
bool doesNotAlias(unsigned n) const {
return Attrs.hasAttribute(n, Attribute::NoAlias);
/// @brief Determine if the return value is marked with NoAlias attribute.
bool returnDoesNotAlias() const {
return Attrs.hasAttribute(AttributeList::ReturnIndex, Attribute::NoAlias);
}
/// Return true if the call should not be treated as a call to a

View File

@ -429,7 +429,7 @@ template <typename CFLAA> class CFLGraphBuilder {
if (Inst->getType()->isPointerTy()) {
auto *Fn = CS.getCalledFunction();
if (Fn == nullptr || !Fn->doesNotAlias(AttributeList::ReturnIndex))
if (Fn == nullptr || !Fn->returnDoesNotAlias())
// No need to call addNode() since we've added Inst at the
// beginning of this function and we know it is not a global.
Graph.addAttr(InstantiatedValue{Inst, 0}, getAttrUnknown());

View File

@ -37,7 +37,7 @@ bool CallLowering::lowerCall(
for (auto &Arg : CS.args()) {
ArgInfo OrigArg{ArgRegs[i], Arg->getType(), ISD::ArgFlagsTy{},
i < NumFixedArgs};
setArgFlags(OrigArg, i + 1, DL, CS);
setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, CS);
OrigArgs.push_back(OrigArg);
++i;
}

View File

@ -1123,7 +1123,7 @@ AttributeList::addAllocSizeAttr(LLVMContext &C, unsigned Index,
LLVMContext &AttributeList::getContext() const { return pImpl->getContext(); }
AttributeSet AttributeList::getParamAttributes(unsigned ArgNo) const {
return getAttributes(ArgNo + 1);
return getAttributes(ArgNo + FirstArgIndex);
}
AttributeSet AttributeList::getRetAttributes() const {
@ -1189,7 +1189,7 @@ unsigned AttributeList::getRetAlignment() const {
}
unsigned AttributeList::getParamAlignment(unsigned ArgNo) const {
return getAttributes(ArgNo + 1).getAlignment();
return getAttributes(ArgNo + FirstArgIndex).getAlignment();
}
unsigned AttributeList::getStackAlignment(unsigned Index) const {

View File

@ -90,13 +90,15 @@ unsigned Argument::getParamAlignment() const {
uint64_t Argument::getDereferenceableBytes() const {
assert(getType()->isPointerTy() &&
"Only pointers have dereferenceable bytes");
return getParent()->getDereferenceableBytes(getArgNo()+1);
return getParent()->getDereferenceableBytes(getArgNo() +
AttributeList::FirstArgIndex);
}
uint64_t Argument::getDereferenceableOrNullBytes() const {
assert(getType()->isPointerTy() &&
"Only pointers have dereferenceable bytes");
return getParent()->getDereferenceableOrNullBytes(getArgNo()+1);
return getParent()->getDereferenceableOrNullBytes(
getArgNo() + AttributeList::FirstArgIndex);
}
bool Argument::hasNestAttr() const {
@ -139,20 +141,21 @@ bool Argument::onlyReadsMemory() const {
void Argument::addAttrs(AttrBuilder &B) {
AttributeList AL = getParent()->getAttributes();
AL = AL.addAttributes(Parent->getContext(), getArgNo() + 1, B);
AL = AL.addAttributes(Parent->getContext(),
getArgNo() + AttributeList::FirstArgIndex, B);
getParent()->setAttributes(AL);
}
void Argument::addAttr(Attribute::AttrKind Kind) {
getParent()->addAttribute(getArgNo() + 1, Kind);
getParent()->addAttribute(getArgNo() + AttributeList::FirstArgIndex, Kind);
}
void Argument::addAttr(Attribute Attr) {
getParent()->addAttribute(getArgNo() + 1, Attr);
getParent()->addAttribute(getArgNo() + AttributeList::FirstArgIndex, Attr);
}
void Argument::removeAttr(Attribute::AttrKind Kind) {
getParent()->removeAttribute(getArgNo() + 1, Kind);
getParent()->removeAttribute(getArgNo() + AttributeList::FirstArgIndex, Kind);
}
bool Argument::hasAttribute(Attribute::AttrKind Kind) const {

View File

@ -335,12 +335,12 @@ Value *CallInst::getReturnedArgOperand() const {
unsigned Index;
if (Attrs.hasAttrSomewhere(Attribute::Returned, &Index) && Index)
return getArgOperand(Index-1);
return getArgOperand(Index - AttributeList::FirstArgIndex);
if (const Function *F = getCalledFunction())
if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) &&
Index)
return getArgOperand(Index-1);
return getArgOperand(Index - AttributeList::FirstArgIndex);
return nullptr;
}
@ -356,6 +356,10 @@ void CallInst::addAttribute(unsigned i, Attribute Attr) {
setAttributes(PAL);
}
void CallInst::addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
addAttribute(ArgNo + AttributeList::FirstArgIndex, Kind);
}
void CallInst::removeAttribute(unsigned i, Attribute::AttrKind Kind) {
AttributeList PAL = getAttributes();
PAL = PAL.removeAttribute(getContext(), i, Kind);
@ -368,6 +372,10 @@ void CallInst::removeAttribute(unsigned i, StringRef Kind) {
setAttributes(PAL);
}
void CallInst::removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
removeAttribute(ArgNo + AttributeList::FirstArgIndex, Kind);
}
void CallInst::addDereferenceableAttr(unsigned i, uint64_t Bytes) {
AttributeList PAL = getAttributes();
PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes);
@ -501,8 +509,8 @@ static Instruction *createMalloc(Instruction *InsertBefore,
MCall->setTailCall();
if (Function *F = dyn_cast<Function>(MallocFunc)) {
MCall->setCallingConv(F->getCallingConv());
if (!F->doesNotAlias(AttributeList::ReturnIndex))
F->setDoesNotAlias(AttributeList::ReturnIndex);
if (!F->returnDoesNotAlias())
F->setReturnDoesNotAlias();
}
assert(!MCall->getType()->isVoidTy() && "Malloc has void return type");
@ -695,12 +703,12 @@ Value *InvokeInst::getReturnedArgOperand() const {
unsigned Index;
if (Attrs.hasAttrSomewhere(Attribute::Returned, &Index) && Index)
return getArgOperand(Index-1);
return getArgOperand(Index - AttributeList::FirstArgIndex);
if (const Function *F = getCalledFunction())
if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) &&
Index)
return getArgOperand(Index-1);
return getArgOperand(Index - AttributeList::FirstArgIndex);
return nullptr;
}
@ -756,6 +764,10 @@ void InvokeInst::addAttribute(unsigned i, Attribute Attr) {
setAttributes(PAL);
}
void InvokeInst::addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
addAttribute(ArgNo + AttributeList::FirstArgIndex, Kind);
}
void InvokeInst::removeAttribute(unsigned i, Attribute::AttrKind Kind) {
AttributeList PAL = getAttributes();
PAL = PAL.removeAttribute(getContext(), i, Kind);
@ -768,6 +780,10 @@ void InvokeInst::removeAttribute(unsigned i, StringRef Kind) {
setAttributes(PAL);
}
void InvokeInst::removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
removeAttribute(ArgNo + AttributeList::FirstArgIndex, Kind);
}
void InvokeInst::addDereferenceableAttr(unsigned i, uint64_t Bytes) {
AttributeList PAL = getAttributes();
PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes);

View File

@ -247,7 +247,7 @@ bool AArch64CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
unsigned i = 0;
for (auto &Arg : F.args()) {
ArgInfo OrigArg{VRegs[i], Arg.getType()};
setArgFlags(OrigArg, i + 1, DL, F);
setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, F);
bool Split = false;
LLT Ty = MRI.getType(VRegs[i]);
unsigned Dst = VRegs[i];

View File

@ -354,7 +354,7 @@ bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
unsigned Idx = 0;
for (auto &Arg : F.args()) {
ArgInfo AInfo(VRegs[Idx], Arg.getType());
setArgFlags(AInfo, Idx + 1, DL, F);
setArgFlags(AInfo, Idx + AttributeList::FirstArgIndex, DL, F);
splitToValueTypes(AInfo, ArgInfos, DL, MF.getRegInfo());
Idx++;
}

View File

@ -412,7 +412,7 @@ Function *WinEHStatePass::generateLSDAInEAXThunk(Function *ParentFunc) {
// Can't use musttail due to prototype mismatch, but we can use tail.
Call->setTailCall(true);
// Set inreg so we pass it in EAX.
Call->addAttribute(1, Attribute::InReg);
Call->addParamAttr(0, Attribute::InReg);
Builder.CreateRet(Call);
return Trampoline;
}

View File

@ -216,8 +216,8 @@ static Function *createClone(Function &F, Twine Suffix, coro::Shape &Shape,
Function *NewF =
Function::Create(FnTy, GlobalValue::LinkageTypes::InternalLinkage,
F.getName() + Suffix, M);
NewF->addAttribute(1, Attribute::NonNull);
NewF->addAttribute(1, Attribute::NoAlias);
NewF->addParamAttr(0, Attribute::NonNull);
NewF->addParamAttr(0, Attribute::NoAlias);
ValueToValueMapTy VMap;
// Replace all args with undefs. The buildCoroutineFrame algorithm already

View File

@ -839,12 +839,12 @@ promoteArguments(Function *F, function_ref<AAResults &(Function &F)> AARGetter,
// avoiding a register copy.
if (PtrArg->hasStructRetAttr()) {
unsigned ArgNo = PtrArg->getArgNo();
F->removeAttribute(ArgNo + 1, Attribute::StructRet);
F->addAttribute(ArgNo + 1, Attribute::NoAlias);
F->removeParamAttr(ArgNo, Attribute::StructRet);
F->addParamAttr(ArgNo, Attribute::NoAlias);
for (Use &U : F->uses()) {
CallSite CS(U.getUser());
CS.removeAttribute(ArgNo + 1, Attribute::StructRet);
CS.addAttribute(ArgNo + 1, Attribute::NoAlias);
CS.removeParamAttr(ArgNo, Attribute::StructRet);
CS.addParamAttr(ArgNo, Attribute::NoAlias);
}
}

View File

@ -835,7 +835,7 @@ static bool addNoAliasAttrs(const SCCNodeSet &SCCNodes) {
// pointers.
for (Function *F : SCCNodes) {
// Already noalias.
if (F->doesNotAlias(0))
if (F->returnDoesNotAlias())
continue;
// We can infer and propagate function attributes only when we know that the
@ -855,11 +855,11 @@ static bool addNoAliasAttrs(const SCCNodeSet &SCCNodes) {
bool MadeChange = false;
for (Function *F : SCCNodes) {
if (F->doesNotAlias(AttributeList::ReturnIndex) ||
if (F->returnDoesNotAlias() ||
!F->getReturnType()->isPointerTy())
continue;
F->setDoesNotAlias(AttributeList::ReturnIndex);
F->setReturnDoesNotAlias();
++NumNoAlias;
MadeChange = true;
}

View File

@ -3845,7 +3845,7 @@ Instruction *InstCombiner::visitCallSite(CallSite CS) {
if (V->getType()->isPointerTy() &&
!CS.paramHasAttr(ArgNo, Attribute::NonNull) &&
isKnownNonNullAt(V, CS.getInstruction(), &DT))
Indices.push_back(ArgNo + 1);
Indices.push_back(ArgNo + AttributeList::FirstArgIndex);
ArgNo++;
}

View File

@ -625,16 +625,16 @@ bool DataFlowSanitizer::runOnModule(Module &M) {
F->addAttribute(AttributeList::FunctionIndex, Attribute::NoUnwind);
F->addAttribute(AttributeList::FunctionIndex, Attribute::ReadNone);
F->addAttribute(AttributeList::ReturnIndex, Attribute::ZExt);
F->addAttribute(1, Attribute::ZExt);
F->addAttribute(2, Attribute::ZExt);
F->addParamAttr(0, Attribute::ZExt);
F->addParamAttr(1, Attribute::ZExt);
}
DFSanCheckedUnionFn = Mod->getOrInsertFunction("dfsan_union", DFSanUnionFnTy);
if (Function *F = dyn_cast<Function>(DFSanCheckedUnionFn)) {
F->addAttribute(AttributeList::FunctionIndex, Attribute::NoUnwind);
F->addAttribute(AttributeList::FunctionIndex, Attribute::ReadNone);
F->addAttribute(AttributeList::ReturnIndex, Attribute::ZExt);
F->addAttribute(1, Attribute::ZExt);
F->addAttribute(2, Attribute::ZExt);
F->addParamAttr(0, Attribute::ZExt);
F->addParamAttr(1, Attribute::ZExt);
}
DFSanUnionLoadFn =
Mod->getOrInsertFunction("__dfsan_union_load", DFSanUnionLoadFnTy);
@ -648,7 +648,7 @@ bool DataFlowSanitizer::runOnModule(Module &M) {
DFSanSetLabelFn =
Mod->getOrInsertFunction("__dfsan_set_label", DFSanSetLabelFnTy);
if (Function *F = dyn_cast<Function>(DFSanSetLabelFn)) {
F->addAttribute(1, Attribute::ZExt);
F->addParamAttr(0, Attribute::ZExt);
}
DFSanNonzeroLabelFn =
Mod->getOrInsertFunction("__dfsan_nonzero_label", DFSanNonzeroLabelFnTy);
@ -982,8 +982,8 @@ Value *DFSanFunction::combineShadows(Value *V1, Value *V2, Instruction *Pos) {
if (AvoidNewBlocks) {
CallInst *Call = IRB.CreateCall(DFS.DFSanCheckedUnionFn, {V1, V2});
Call->addAttribute(AttributeList::ReturnIndex, Attribute::ZExt);
Call->addAttribute(1, Attribute::ZExt);
Call->addAttribute(2, Attribute::ZExt);
Call->addParamAttr(0, Attribute::ZExt);
Call->addParamAttr(1, Attribute::ZExt);
CCS.Block = Pos->getParent();
CCS.Shadow = Call;
@ -995,8 +995,8 @@ Value *DFSanFunction::combineShadows(Value *V1, Value *V2, Instruction *Pos) {
IRBuilder<> ThenIRB(BI);
CallInst *Call = ThenIRB.CreateCall(DFS.DFSanUnionFn, {V1, V2});
Call->addAttribute(AttributeList::ReturnIndex, Attribute::ZExt);
Call->addAttribute(1, Attribute::ZExt);
Call->addAttribute(2, Attribute::ZExt);
Call->addParamAttr(0, Attribute::ZExt);
Call->addParamAttr(1, Attribute::ZExt);
BasicBlock *Tail = BI->getSuccessor(0);
PHINode *Phi = PHINode::Create(DFS.ShadowTy, 2, "", &Tail->front());

View File

@ -241,7 +241,7 @@ static Constant *getOrInsertValueProfilingCall(Module &M,
if (Function *FunRes = dyn_cast<Function>(Res)) {
if (auto AK = TLI.getExtAttrForI32Param(false))
FunRes->addAttribute(3, AK);
FunRes->addParamAttr(2, AK);
}
return Res;
}
@ -292,7 +292,7 @@ void InstrProfiling::lowerValueProfileInst(InstrProfValueProfileInst *Ind) {
Builder.CreateCall(getOrInsertValueProfilingCall(*M, *TLI, true), Args);
}
if (auto AK = TLI->getExtAttrForI32Param(false))
Call->addAttribute(3, AK);
Call->addParamAttr(2, AK);
Ind->replaceAllUsesWith(Call);
Ind->eraseFromParent();
}

View File

@ -163,7 +163,7 @@ private:
AttributeList Attr = AttributeList().addAttribute(
C, AttributeList::FunctionIndex, Attribute::NoUnwind);
Attr = Attr.addAttribute(C, 1, Attribute::NoCapture);
Attr = Attr.addParamAttribute(C, 0, Attribute::NoCapture);
FunctionType *Fty = FunctionType::get(Type::getVoidTy(C), Params,
/*isVarArg=*/false);

View File

@ -318,7 +318,7 @@ static bool processCallSite(CallSite CS, LazyValueInfo *LVI) {
LVI->getPredicateAt(ICmpInst::ICMP_EQ, V,
ConstantPointerNull::get(Type),
CS.getInstruction()) == LazyValueInfo::False)
Indices.push_back(ArgNo + 1);
Indices.push_back(ArgNo + AttributeList::FirstArgIndex);
ArgNo++;
}

View File

@ -2286,7 +2286,7 @@ static void RemoveNonValidAttrAtIndex(LLVMContext &Ctx, AttrHolder &AH,
if (AH.getDereferenceableOrNullBytes(Index))
R.addAttribute(Attribute::get(Ctx, Attribute::DereferenceableOrNull,
AH.getDereferenceableOrNullBytes(Index)));
if (AH.doesNotAlias(Index))
if (AH.getAttributes().hasAttribute(Index, Attribute::NoAlias))
R.addAttribute(Attribute::NoAlias);
if (!R.empty())
@ -2299,7 +2299,8 @@ RewriteStatepointsForGC::stripNonValidAttributesFromPrototype(Function &F) {
for (Argument &A : F.args())
if (isa<PointerType>(A.getType()))
RemoveNonValidAttrAtIndex(Ctx, F, A.getArgNo() + 1);
RemoveNonValidAttrAtIndex(Ctx, F,
A.getArgNo() + AttributeList::FirstArgIndex);
if (isa<PointerType>(F.getReturnType()))
RemoveNonValidAttrAtIndex(Ctx, F, AttributeList::ReturnIndex);
@ -2335,7 +2336,7 @@ void RewriteStatepointsForGC::stripNonValidAttributesFromBody(Function &F) {
if (CallSite CS = CallSite(&I)) {
for (int i = 0, e = CS.arg_size(); i != e; i++)
if (isa<PointerType>(CS.getArgument(i)->getType()))
RemoveNonValidAttrAtIndex(Ctx, CS, i + 1);
RemoveNonValidAttrAtIndex(Ctx, CS, i + AttributeList::FirstArgIndex);
if (isa<PointerType>(CS.getType()))
RemoveNonValidAttrAtIndex(Ctx, CS, AttributeList::ReturnIndex);
}

View File

@ -58,7 +58,7 @@ static bool setOnlyReadsMemory(Function &F) {
static bool setOnlyAccessesArgMemory(Function &F) {
if (F.onlyAccessesArgMemory())
return false;
F.setOnlyAccessesArgMemory ();
F.setOnlyAccessesArgMemory();
++NumArgMemOnly;
return true;
}
@ -71,37 +71,36 @@ static bool setDoesNotThrow(Function &F) {
return true;
}
static bool setDoesNotCapture(Function &F, unsigned n) {
if (F.doesNotCapture(n))
static bool setRetDoesNotAlias(Function &F) {
if (F.hasAttribute(AttributeList::ReturnIndex, Attribute::NoAlias))
return false;
F.setDoesNotCapture(n);
++NumNoCapture;
return true;
}
static bool setOnlyReadsMemory(Function &F, unsigned n) {
if (F.onlyReadsMemory(n))
return false;
F.setOnlyReadsMemory(n);
++NumReadOnlyArg;
return true;
}
static bool setDoesNotAlias(Function &F, unsigned n) {
if (F.doesNotAlias(n))
return false;
F.setDoesNotAlias(n);
F.addAttribute(AttributeList::ReturnIndex, Attribute::NoAlias);
++NumNoAlias;
return true;
}
static bool setNonNull(Function &F, unsigned n) {
assert(
(n != AttributeList::ReturnIndex || F.getReturnType()->isPointerTy()) &&
"nonnull applies only to pointers");
if (F.getAttributes().hasAttribute(n, Attribute::NonNull))
static bool setDoesNotCapture(Function &F, unsigned ArgNo) {
if (F.hasParamAttribute(ArgNo, Attribute::NoCapture))
return false;
F.addAttribute(n, Attribute::NonNull);
F.addParamAttr(ArgNo, Attribute::NoCapture);
++NumNoCapture;
return true;
}
static bool setOnlyReadsMemory(Function &F, unsigned ArgNo) {
if (F.hasParamAttribute(ArgNo, Attribute::ReadOnly))
return false;
F.addParamAttr(ArgNo, Attribute::ReadOnly);
++NumReadOnlyArg;
return true;
}
static bool setRetNonNull(Function &F) {
assert(F.getReturnType()->isPointerTy() &&
"nonnull applies only to pointers");
if (F.hasAttribute(AttributeList::ReturnIndex, Attribute::NonNull))
return false;
F.addAttribute(AttributeList::ReturnIndex, Attribute::NonNull);
++NumNonNull;
return true;
}
@ -116,7 +115,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
case LibFunc_strlen:
Changed |= setOnlyReadsMemory(F);
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 0);
return Changed;
case LibFunc_strchr:
case LibFunc_strrchr:
@ -131,8 +130,8 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
case LibFunc_strtold:
case LibFunc_strtoull:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_strcpy:
case LibFunc_stpcpy:
@ -141,14 +140,14 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
case LibFunc_strncpy:
case LibFunc_stpncpy:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 2);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
return Changed;
case LibFunc_strxfrm:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 2);
Changed |= setOnlyReadsMemory(F, 1);
return Changed;
case LibFunc_strcmp: // 0,1
case LibFunc_strspn: // 0,1
@ -159,84 +158,84 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
case LibFunc_strncasecmp: //
Changed |= setOnlyReadsMemory(F);
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
return Changed;
case LibFunc_strstr:
case LibFunc_strpbrk:
Changed |= setOnlyReadsMemory(F);
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 2);
Changed |= setDoesNotCapture(F, 1);
return Changed;
case LibFunc_strtok:
case LibFunc_strtok_r:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 2);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
return Changed;
case LibFunc_scanf:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_setbuf:
case LibFunc_setvbuf:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 0);
return Changed;
case LibFunc_strdup:
case LibFunc_strndup:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotAlias(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setRetDoesNotAlias(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_stat:
case LibFunc_statvfs:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_sscanf:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 0);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setOnlyReadsMemory(F, 2);
return Changed;
case LibFunc_sprintf:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 2);
return Changed;
case LibFunc_snprintf:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 3);
Changed |= setOnlyReadsMemory(F, 3);
return Changed;
case LibFunc_setitimer:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 2);
Changed |= setDoesNotCapture(F, 3);
Changed |= setOnlyReadsMemory(F, 2);
return Changed;
case LibFunc_system:
// May throw; "system" is a valid pthread cancellation point.
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
return Changed;
case LibFunc_snprintf:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 2);
return Changed;
case LibFunc_setitimer:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 1);
return Changed;
case LibFunc_system:
// May throw; "system" is a valid pthread cancellation point.
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_malloc:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotAlias(F, 0);
Changed |= setRetDoesNotAlias(F);
return Changed;
case LibFunc_memcmp:
Changed |= setOnlyReadsMemory(F);
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
return Changed;
case LibFunc_memchr:
case LibFunc_memrchr:
@ -247,100 +246,100 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
case LibFunc_modff:
case LibFunc_modfl:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 2);
Changed |= setDoesNotCapture(F, 1);
return Changed;
case LibFunc_memcpy:
case LibFunc_mempcpy:
case LibFunc_memccpy:
case LibFunc_memmove:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 2);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
return Changed;
case LibFunc_memcpy_chk:
Changed |= setDoesNotThrow(F);
return Changed;
case LibFunc_memalign:
Changed |= setDoesNotAlias(F, 0);
Changed |= setRetDoesNotAlias(F);
return Changed;
case LibFunc_mkdir:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_mktime:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 0);
return Changed;
case LibFunc_realloc:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotAlias(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setRetDoesNotAlias(F);
Changed |= setDoesNotCapture(F, 0);
return Changed;
case LibFunc_read:
// May throw; "read" is a valid pthread cancellation point.
Changed |= setDoesNotCapture(F, 2);
Changed |= setDoesNotCapture(F, 1);
return Changed;
case LibFunc_rewind:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 0);
return Changed;
case LibFunc_rmdir:
case LibFunc_remove:
case LibFunc_realpath:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_rename:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 0);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setOnlyReadsMemory(F, 2);
return Changed;
case LibFunc_readlink:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_write:
// May throw; "write" is a valid pthread cancellation point.
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 2);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
return Changed;
case LibFunc_bcopy:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_bcmp:
Changed |= setDoesNotThrow(F);
Changed |= setOnlyReadsMemory(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
return Changed;
case LibFunc_bzero:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 0);
return Changed;
case LibFunc_calloc:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotAlias(F, 0);
Changed |= setRetDoesNotAlias(F);
return Changed;
case LibFunc_chmod:
case LibFunc_chown:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_ctermid:
case LibFunc_clearerr:
case LibFunc_closedir:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 0);
return Changed;
case LibFunc_atoi:
case LibFunc_atol:
@ -348,26 +347,26 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
case LibFunc_atoll:
Changed |= setDoesNotThrow(F);
Changed |= setOnlyReadsMemory(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 0);
return Changed;
case LibFunc_access:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_fopen:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotAlias(F, 0);
Changed |= setRetDoesNotAlias(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 0);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setOnlyReadsMemory(F, 2);
return Changed;
case LibFunc_fdopen:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotAlias(F, 0);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 2);
Changed |= setRetDoesNotAlias(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
return Changed;
case LibFunc_feof:
case LibFunc_free:
@ -384,11 +383,11 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
case LibFunc_funlockfile:
case LibFunc_ftrylockfile:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 0);
return Changed;
case LibFunc_ferror:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F);
return Changed;
case LibFunc_fputc:
@ -398,51 +397,51 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
case LibFunc_frexpl:
case LibFunc_fstatvfs:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 2);
Changed |= setDoesNotCapture(F, 1);
return Changed;
case LibFunc_fgets:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 3);
Changed |= setDoesNotCapture(F, 2);
return Changed;
case LibFunc_fread:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 4);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 3);
return Changed;
case LibFunc_fwrite:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 4);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 3);
// FIXME: readonly #1?
return Changed;
case LibFunc_fputs:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_fscanf:
case LibFunc_fprintf:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 2);
Changed |= setOnlyReadsMemory(F, 1);
return Changed;
case LibFunc_fgetpos:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
return Changed;
case LibFunc_getc:
case LibFunc_getlogin_r:
case LibFunc_getc_unlocked:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 0);
return Changed;
case LibFunc_getenv:
Changed |= setDoesNotThrow(F);
Changed |= setOnlyReadsMemory(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 0);
return Changed;
case LibFunc_gets:
case LibFunc_getchar:
@ -450,132 +449,132 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
return Changed;
case LibFunc_getitimer:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 2);
Changed |= setDoesNotCapture(F, 1);
return Changed;
case LibFunc_getpwnam:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_ungetc:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 2);
Changed |= setDoesNotCapture(F, 1);
return Changed;
case LibFunc_uname:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 0);
return Changed;
case LibFunc_unlink:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_unsetenv:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_utime:
case LibFunc_utimes:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 0);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setOnlyReadsMemory(F, 2);
return Changed;
case LibFunc_putc:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 2);
Changed |= setDoesNotCapture(F, 1);
return Changed;
case LibFunc_puts:
case LibFunc_printf:
case LibFunc_perror:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_pread:
// May throw; "pread" is a valid pthread cancellation point.
Changed |= setDoesNotCapture(F, 2);
Changed |= setDoesNotCapture(F, 1);
return Changed;
case LibFunc_pwrite:
// May throw; "pwrite" is a valid pthread cancellation point.
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 2);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
return Changed;
case LibFunc_putchar:
Changed |= setDoesNotThrow(F);
return Changed;
case LibFunc_popen:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotAlias(F, 0);
Changed |= setRetDoesNotAlias(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 0);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setOnlyReadsMemory(F, 2);
return Changed;
case LibFunc_pclose:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 0);
return Changed;
case LibFunc_vscanf:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_vsscanf:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 0);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setOnlyReadsMemory(F, 2);
return Changed;
case LibFunc_vfscanf:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 2);
Changed |= setOnlyReadsMemory(F, 1);
return Changed;
case LibFunc_valloc:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotAlias(F, 0);
Changed |= setRetDoesNotAlias(F);
return Changed;
case LibFunc_vprintf:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_vfprintf:
case LibFunc_vsprintf:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 2);
Changed |= setOnlyReadsMemory(F, 1);
return Changed;
case LibFunc_vsnprintf:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 3);
Changed |= setOnlyReadsMemory(F, 3);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 2);
return Changed;
case LibFunc_open:
// May throw; "open" is a valid pthread cancellation point.
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_opendir:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotAlias(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setRetDoesNotAlias(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_tmpfile:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotAlias(F, 0);
Changed |= setRetDoesNotAlias(F);
return Changed;
case LibFunc_times:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 0);
return Changed;
case LibFunc_htonl:
case LibFunc_htons:
@ -586,93 +585,93 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
return Changed;
case LibFunc_lstat:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_lchown:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_qsort:
// May throw; places call through function pointer.
Changed |= setDoesNotCapture(F, 4);
Changed |= setDoesNotCapture(F, 3);
return Changed;
case LibFunc_dunder_strdup:
case LibFunc_dunder_strndup:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotAlias(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setRetDoesNotAlias(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_dunder_strtok_r:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 2);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
return Changed;
case LibFunc_under_IO_getc:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 0);
return Changed;
case LibFunc_under_IO_putc:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 2);
Changed |= setDoesNotCapture(F, 1);
return Changed;
case LibFunc_dunder_isoc99_scanf:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_stat64:
case LibFunc_lstat64:
case LibFunc_statvfs64:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_dunder_isoc99_sscanf:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 0);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setOnlyReadsMemory(F, 2);
return Changed;
case LibFunc_fopen64:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotAlias(F, 0);
Changed |= setRetDoesNotAlias(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 0);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setOnlyReadsMemory(F, 2);
return Changed;
case LibFunc_fseeko64:
case LibFunc_ftello64:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 0);
return Changed;
case LibFunc_tmpfile64:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotAlias(F, 0);
Changed |= setRetDoesNotAlias(F);
return Changed;
case LibFunc_fstat64:
case LibFunc_fstatvfs64:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 2);
Changed |= setDoesNotCapture(F, 1);
return Changed;
case LibFunc_open64:
// May throw; "open" is a valid pthread cancellation point.
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyReadsMemory(F, 0);
return Changed;
case LibFunc_gettimeofday:
// Currently some platforms have the restrict keyword on the arguments to
// gettimeofday. To be conservative, do not add noalias to gettimeofday's
// arguments.
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
return Changed;
case LibFunc_Znwj: // new(unsigned int)
case LibFunc_Znwm: // new(unsigned long)
@ -683,17 +682,17 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
case LibFunc_msvc_new_array_int: // new[](unsigned int)
case LibFunc_msvc_new_array_longlong: // new[](unsigned long long)
// Operator new always returns a nonnull noalias pointer
Changed |= setNonNull(F, AttributeList::ReturnIndex);
Changed |= setDoesNotAlias(F, AttributeList::ReturnIndex);
Changed |= setRetNonNull(F);
Changed |= setRetDoesNotAlias(F);
return Changed;
//TODO: add LibFunc entries for:
//case LibFunc_memset_pattern4:
//case LibFunc_memset_pattern8:
case LibFunc_memset_pattern16:
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setDoesNotCapture(F, 2);
Changed |= setOnlyReadsMemory(F, 2);
Changed |= setOnlyReadsMemory(F, 1);
return Changed;
// int __nvvm_reflect(const char *)
case LibFunc_nvvm_reflect:

View File

@ -537,7 +537,7 @@ Value *LibCallSimplifier::optimizeStrTo(CallInst *CI, IRBuilder<> &B) {
if (isa<ConstantPointerNull>(EndPtr)) {
// With a null EndPtr, this function won't capture the main argument.
// It would be readonly too, except that it still may write to errno.
CI->addAttribute(1, Attribute::NoCapture);
CI->addParamAttr(0, Attribute::NoCapture);
}
return nullptr;

View File

@ -20,17 +20,15 @@ TEST(IndirectionUtilsTest, MakeStub) {
LLVMContext Context;
ModuleBuilder MB(Context, "x86_64-apple-macosx10.10", "");
Function *F = MB.createFunctionDecl<void(DummyStruct, DummyStruct)>("");
SmallVector<AttributeList, 4> Attrs;
Attrs.push_back(
AttributeList::get(MB.getModule()->getContext(), 1U,
AttrBuilder().addAttribute(Attribute::StructRet)));
Attrs.push_back(
AttributeList::get(MB.getModule()->getContext(), 2U,
AttrBuilder().addAttribute(Attribute::ByVal)));
Attrs.push_back(
AttributeList::get(MB.getModule()->getContext(), ~0U,
AttrBuilder().addAttribute(Attribute::NoUnwind)));
F->setAttributes(AttributeList::get(MB.getModule()->getContext(), Attrs));
AttributeSet FnAttrs = AttributeSet::get(
Context, AttrBuilder().addAttribute(Attribute::NoUnwind));
AttributeSet RetAttrs; // None
AttributeSet ArgAttrs[2] = {
AttributeSet::get(Context,
AttrBuilder().addAttribute(Attribute::StructRet)),
AttributeSet::get(Context, AttrBuilder().addAttribute(Attribute::ByVal)),
};
F->setAttributes(AttributeList::get(Context, FnAttrs, RetAttrs, ArgAttrs));
auto ImplPtr = orc::createImplPointer(*F->getType(), *MB.getModule(), "", nullptr);
orc::makeStub(*F, *ImplPtr);

View File

@ -563,8 +563,9 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
if (ae) {
while (ai != ae) {
unsigned argNo = intrinsic.ArgumentAttributes[ai].first;
unsigned attrIdx = argNo + 1; // Must match AttributeList::FirstArgIndex
OS << " const Attribute::AttrKind AttrParam" << argNo + 1 <<"[]= {";
OS << " const Attribute::AttrKind AttrParam" << attrIdx << "[]= {";
bool addComma = false;
do {
@ -605,7 +606,7 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
} while (ai != ae && intrinsic.ArgumentAttributes[ai].first == argNo);
OS << "};\n";
OS << " AS[" << numAttrs++ << "] = AttributeList::get(C, "
<< argNo + 1 << ", AttrParam" << argNo + 1 << ");\n";
<< attrIdx << ", AttrParam" << attrIdx << ");\n";
}
}