Skip to content

Commit f35740d

Browse files
author
Stefan Stipanovic
committed
NoFree argument attribute.
Summary: Deducing nofree atrribute for function arguments. Reviewers: jdoerfert Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D67886
1 parent 095d2a4 commit f35740d

23 files changed

+374
-189
lines changed

llvm/docs/LangRef.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,10 @@ Currently, only the following parameter attributes are defined:
11331133
attribute for return values. Addresses used in volatile operations
11341134
are considered to be captured.
11351135

1136+
``nofree``
1137+
This indicates that callee does not free the pointer argument. This is not
1138+
a valid attribute for return values.
1139+
11361140
.. _nest:
11371141

11381142
``nest``

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,6 +1636,7 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) {
16361636
case lltok::kw_nest: B.addAttribute(Attribute::Nest); break;
16371637
case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break;
16381638
case lltok::kw_nocapture: B.addAttribute(Attribute::NoCapture); break;
1639+
case lltok::kw_nofree: B.addAttribute(Attribute::NoFree); break;
16391640
case lltok::kw_nonnull: B.addAttribute(Attribute::NonNull); break;
16401641
case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break;
16411642
case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break;

llvm/lib/IR/Verifier.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,7 +1506,6 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
15061506
case Attribute::NoCfCheck:
15071507
case Attribute::NoUnwind:
15081508
case Attribute::NoInline:
1509-
case Attribute::NoFree:
15101509
case Attribute::AlwaysInline:
15111510
case Attribute::OptimizeForSize:
15121511
case Attribute::StackProtect:
@@ -1555,7 +1554,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
15551554
/// arguments.
15561555
static bool isFuncOrArgAttr(Attribute::AttrKind Kind) {
15571556
return Kind == Attribute::ReadOnly || Kind == Attribute::WriteOnly ||
1558-
Kind == Attribute::ReadNone;
1557+
Kind == Attribute::ReadNone || Kind == Attribute::NoFree;
15591558
}
15601559

15611560
void Verifier::verifyAttributeTypes(AttributeSet Attrs, bool IsFunction,
@@ -1702,11 +1701,12 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs,
17021701
!RetAttrs.hasAttribute(Attribute::Nest) &&
17031702
!RetAttrs.hasAttribute(Attribute::StructRet) &&
17041703
!RetAttrs.hasAttribute(Attribute::NoCapture) &&
1704+
!RetAttrs.hasAttribute(Attribute::NoFree) &&
17051705
!RetAttrs.hasAttribute(Attribute::Returned) &&
17061706
!RetAttrs.hasAttribute(Attribute::InAlloca) &&
17071707
!RetAttrs.hasAttribute(Attribute::SwiftSelf) &&
17081708
!RetAttrs.hasAttribute(Attribute::SwiftError)),
1709-
"Attributes 'byval', 'inalloca', 'nest', 'sret', 'nocapture', "
1709+
"Attributes 'byval', 'inalloca', 'nest', 'sret', 'nocapture', 'nofree'"
17101710
"'returned', 'swiftself', and 'swifterror' do not apply to return "
17111711
"values!",
17121712
V);

llvm/lib/Transforms/IPO/Attributor.cpp

Lines changed: 151 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,8 @@ struct AAComposeTwoGenericDeduction
584584

585585
/// See AbstractAttribute::updateImpl(...).
586586
ChangeStatus updateImpl(Attributor &A) override {
587-
ChangeStatus ChangedF = F<AAType, G<AAType, Base, StateType>, StateType>::updateImpl(A);
587+
ChangeStatus ChangedF =
588+
F<AAType, G<AAType, Base, StateType>, StateType>::updateImpl(A);
588589
ChangeStatus ChangedG = G<AAType, Base, StateType>::updateImpl(A);
589590
return ChangedF | ChangedG;
590591
}
@@ -731,7 +732,7 @@ struct AAFromMustBeExecutedContext : public Base {
731732
A.getInfoCache().getMustBeExecutedContextExplorer();
732733

733734
auto EIt = Explorer.begin(CtxI), EEnd = Explorer.end(CtxI);
734-
for (unsigned u = 0 ; u < Uses.size(); ++u) {
735+
for (unsigned u = 0; u < Uses.size(); ++u) {
735736
const Use *U = Uses[u];
736737
if (const Instruction *UserI = dyn_cast<Instruction>(U->getUser())) {
737738
bool Found = Explorer.findInContextOf(UserI, EIt, EEnd);
@@ -1524,6 +1525,138 @@ struct AANoFreeCallSite final : AANoFreeImpl {
15241525
void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nofree); }
15251526
};
15261527

1528+
/// NoFree attribute for floating values.
1529+
struct AANoFreeFloating : AANoFreeImpl {
1530+
AANoFreeFloating(const IRPosition &IRP) : AANoFreeImpl(IRP) {}
1531+
1532+
/// See AbstractAttribute::trackStatistics()
1533+
void trackStatistics() const override{STATS_DECLTRACK_FLOATING_ATTR(nofree)}
1534+
1535+
/// See Abstract Attribute::updateImpl(...).
1536+
ChangeStatus updateImpl(Attributor &A) override {
1537+
const IRPosition &IRP = getIRPosition();
1538+
Function *F = IRP.getAnchorScope();
1539+
1540+
const AAIsDead &LivenessAA =
1541+
A.getAAFor<AAIsDead>(*this, IRPosition::function(*F));
1542+
1543+
const auto &NoFreeAA =
1544+
A.getAAFor<AANoFree>(*this, IRPosition::function_scope(IRP));
1545+
if (NoFreeAA.isAssumedNoFree())
1546+
return ChangeStatus::UNCHANGED;
1547+
1548+
SmallPtrSet<const Use *, 8> Visited;
1549+
SmallVector<const Use *, 8> Worklist;
1550+
1551+
Value &AssociatedValue = getIRPosition().getAssociatedValue();
1552+
for (Use &U : AssociatedValue.uses())
1553+
Worklist.push_back(&U);
1554+
1555+
while (!Worklist.empty()) {
1556+
const Use *U = Worklist.pop_back_val();
1557+
if (!Visited.insert(U).second)
1558+
continue;
1559+
1560+
auto *UserI = U->getUser();
1561+
if (!UserI)
1562+
continue;
1563+
1564+
if (LivenessAA.isAssumedDead(cast<Instruction>(UserI)))
1565+
continue;
1566+
1567+
if (auto *CB = dyn_cast<CallBase>(UserI)) {
1568+
if (CB->isBundleOperand(U))
1569+
return indicatePessimisticFixpoint();
1570+
if (!CB->isArgOperand(U))
1571+
continue;
1572+
1573+
unsigned ArgNo = U - CB->arg_begin();
1574+
1575+
const auto &NoFreeArg = A.getAAFor<AANoFree>(
1576+
*this, IRPosition::callsite_argument(*CB, ArgNo));
1577+
1578+
if (NoFreeArg.isAssumedNoFree())
1579+
continue;
1580+
1581+
return indicatePessimisticFixpoint();
1582+
}
1583+
1584+
if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI) ||
1585+
isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
1586+
for (Use &U : UserI->uses())
1587+
Worklist.push_back(&U);
1588+
continue;
1589+
}
1590+
1591+
// Unknown user.
1592+
return indicatePessimisticFixpoint();
1593+
}
1594+
return ChangeStatus::UNCHANGED;
1595+
}
1596+
};
1597+
1598+
/// NoFree attribute for a call site argument.
1599+
struct AANoFreeArgument final : AANoFreeFloating {
1600+
AANoFreeArgument(const IRPosition &IRP) : AANoFreeFloating(IRP) {}
1601+
1602+
/// See AbstractAttribute::trackStatistics()
1603+
void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofree) }
1604+
};
1605+
1606+
/// NoFree attribute for call site arguments.
1607+
struct AANoFreeCallSiteArgument final : AANoFreeFloating {
1608+
AANoFreeCallSiteArgument(const IRPosition &IRP) : AANoFreeFloating(IRP) {}
1609+
1610+
/// See AbstractAttribute::updateImpl(...).
1611+
ChangeStatus updateImpl(Attributor &A) override {
1612+
// TODO: Once we have call site specific value information we can provide
1613+
// call site specific liveness information and then it makes
1614+
// sense to specialize attributes for call sites arguments instead of
1615+
// redirecting requests to the callee argument.
1616+
Argument *Arg = getAssociatedArgument();
1617+
if (!Arg)
1618+
return indicatePessimisticFixpoint();
1619+
const IRPosition &ArgPos = IRPosition::argument(*Arg);
1620+
auto &ArgAA = A.getAAFor<AANoFree>(*this, ArgPos);
1621+
return clampStateAndIndicateChange(
1622+
getState(), static_cast<const AANoFree::StateType &>(ArgAA.getState()));
1623+
}
1624+
1625+
/// See AbstractAttribute::trackStatistics()
1626+
void trackStatistics() const override{STATS_DECLTRACK_CSARG_ATTR(nofree)};
1627+
};
1628+
1629+
/// NoFree attribute for function return value.
1630+
struct AANoFreeReturned final : AANoFreeFloating {
1631+
AANoFreeReturned(const IRPosition &IRP) : AANoFreeFloating(IRP) {
1632+
llvm_unreachable("NoFree is not applicable to function returns!");
1633+
}
1634+
1635+
/// See AbstractAttribute::initialize(...).
1636+
void initialize(Attributor &A) override {
1637+
llvm_unreachable("NoFree is not applicable to function returns!");
1638+
}
1639+
1640+
/// See AbstractAttribute::updateImpl(...).
1641+
ChangeStatus updateImpl(Attributor &A) override {
1642+
llvm_unreachable("NoFree is not applicable to function returns!");
1643+
}
1644+
1645+
/// See AbstractAttribute::trackStatistics()
1646+
void trackStatistics() const override {}
1647+
};
1648+
1649+
/// NoFree attribute deduction for a call site return value.
1650+
struct AANoFreeCallSiteReturned final : AANoFreeFloating {
1651+
AANoFreeCallSiteReturned(const IRPosition &IRP) : AANoFreeFloating(IRP) {}
1652+
1653+
ChangeStatus manifest(Attributor &A) override {
1654+
return ChangeStatus::UNCHANGED;
1655+
}
1656+
/// See AbstractAttribute::trackStatistics()
1657+
void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nofree) }
1658+
};
1659+
15271660
/// ------------------------ NonNull Argument Attribute ------------------------
15281661
static int64_t getKnownNonNullAndDerefBytesForUse(
15291662
Attributor &A, AbstractAttribute &QueryingAA, Value &AssociatedValue,
@@ -1646,7 +1779,8 @@ struct AANonNullFloating
16461779
return Change;
16471780

16481781
if (!NullIsDefined) {
1649-
const auto &DerefAA = A.getAAFor<AADereferenceable>(*this, getIRPosition());
1782+
const auto &DerefAA =
1783+
A.getAAFor<AADereferenceable>(*this, getIRPosition());
16501784
if (DerefAA.getAssumedDereferenceableBytes())
16511785
return Change;
16521786
}
@@ -3250,7 +3384,7 @@ struct AANoCaptureImpl : public AANoCapture {
32503384
// Check existing "returned" attributes.
32513385
int ArgNo = IRP.getArgNo();
32523386
if (F.doesNotThrow() && ArgNo >= 0) {
3253-
for (unsigned u = 0, e = F.arg_size(); u< e; ++u)
3387+
for (unsigned u = 0, e = F.arg_size(); u < e; ++u)
32543388
if (F.hasParamAttribute(u, Attribute::Returned)) {
32553389
if (u == unsigned(ArgNo))
32563390
State.removeAssumedBits(NOT_CAPTURED_IN_RET);
@@ -4053,7 +4187,7 @@ ChangeStatus AAHeapToStackImpl::updateImpl(Attributor &A) {
40534187
if (auto *Num = dyn_cast<ConstantInt>(I.getOperand(0)))
40544188
if (auto *Size = dyn_cast<ConstantInt>(I.getOperand(1)))
40554189
if ((Size->getValue().umul_ov(Num->getValue(), Overflow))
4056-
.sle(MaxHeapToStackSize))
4190+
.sle(MaxHeapToStackSize))
40574191
if (!Overflow && (UsesCheck(I) || FreeCheck(I))) {
40584192
MallocCalls.insert(&I);
40594193
return true;
@@ -4244,7 +4378,6 @@ struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
42444378
return AAMemoryBehaviorFloating::manifest(A);
42454379
}
42464380

4247-
42484381
/// See AbstractAttribute::trackStatistics()
42494382
void trackStatistics() const override {
42504383
if (isAssumedReadNone())
@@ -4654,8 +4787,7 @@ bool Attributor::checkForAllCallSites(
46544787
for (const Use &U : Fn.uses()) {
46554788
AbstractCallSite ACS(&U);
46564789
if (!ACS) {
4657-
LLVM_DEBUG(dbgs() << "[Attributor] Function "
4658-
<< Fn.getName()
4790+
LLVM_DEBUG(dbgs() << "[Attributor] Function " << Fn.getName()
46594791
<< " has non call site use " << *U.get() << " in "
46604792
<< *U.getUser() << "\n");
46614793
// BlockAddress users are allowed.
@@ -4669,7 +4801,7 @@ bool Attributor::checkForAllCallSites(
46694801

46704802
const auto *LivenessAA =
46714803
lookupAAFor<AAIsDead>(IRPosition::function(*Caller), QueryingAA,
4672-
/* TrackDependence */ false);
4804+
/* TrackDependence */ false);
46734805

46744806
// Skip dead calls.
46754807
if (LivenessAA && LivenessAA->isAssumedDead(I)) {
@@ -4686,8 +4818,7 @@ bool Attributor::checkForAllCallSites(
46864818
if (!RequireAllCallSites)
46874819
continue;
46884820
LLVM_DEBUG(dbgs() << "[Attributor] User " << EffectiveUse->getUser()
4689-
<< " is an invalid use of "
4690-
<< Fn.getName() << "\n");
4821+
<< " is an invalid use of " << Fn.getName() << "\n");
46914822
return false;
46924823
}
46934824

@@ -5006,7 +5137,8 @@ ChangeStatus Attributor::run(Module &M) {
50065137
<< " instead of " << *OldV << "\n");
50075138
U->set(NewV);
50085139
if (Instruction *I = dyn_cast<Instruction>(OldV))
5009-
if (!isa<PHINode>(I) && !ToBeDeletedInsts.count(I) && isInstructionTriviallyDead(I)) {
5140+
if (!isa<PHINode>(I) && !ToBeDeletedInsts.count(I) &&
5141+
isInstructionTriviallyDead(I)) {
50105142
DeadInsts.push_back(I);
50115143
}
50125144
if (isa<Constant>(NewV) && isa<BranchInst>(U->getUser())) {
@@ -5242,6 +5374,9 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) {
52425374
// Every argument with pointer type might be marked
52435375
// "readnone/readonly/writeonly/..."
52445376
getOrCreateAAFor<AAMemoryBehavior>(ArgPos);
5377+
5378+
// Every argument with pointer type might be marked nofree.
5379+
getOrCreateAAFor<AANoFree>(ArgPos);
52455380
}
52465381
}
52475382

@@ -5284,6 +5419,9 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) {
52845419

52855420
// Call site argument attribute "align".
52865421
getOrCreateAAFor<AAAlign>(CSArgPos);
5422+
5423+
// Call site argument attribute "nofree".
5424+
getOrCreateAAFor<AANoFree>(CSArgPos);
52875425
}
52885426
}
52895427
return true;
@@ -5564,7 +5702,6 @@ const char AAMemoryBehavior::ID = 0;
55645702

55655703
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUnwind)
55665704
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoSync)
5567-
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFree)
55685705
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoRecurse)
55695706
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAWillReturn)
55705707
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoReturn)
@@ -5578,6 +5715,7 @@ CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoCapture)
55785715

55795716
CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueSimplify)
55805717
CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIsDead)
5718+
CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFree)
55815719

55825720
CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAHeapToStack)
55835721

0 commit comments

Comments
 (0)