summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/IPO/Attributor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/IPO/Attributor.cpp')
-rw-r--r--llvm/lib/Transforms/IPO/Attributor.cpp70
1 files changed, 70 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp
index 9b8fc6a8c33..86fc48b04bb 100644
--- a/llvm/lib/Transforms/IPO/Attributor.cpp
+++ b/llvm/lib/Transforms/IPO/Attributor.cpp
@@ -50,6 +50,7 @@ STATISTIC(NumFnKnownReturns, "Number of function with known return values");
STATISTIC(NumFnArgumentReturned,
"Number of function arguments marked returned");
STATISTIC(NumFnNoSync, "Number of functions marked nosync");
+STATISTIC(NumFnNoFree, "Number of functions marked nofree");
// TODO: Determine a good default value.
//
@@ -104,6 +105,9 @@ static void bookkeeping(AbstractAttribute::ManifestPosition MP,
case Attribute::NoSync:
NumFnNoSync++;
break;
+ case Attribute::NoFree:
+ NumFnNoFree++;
+ break;
default:
return;
}
@@ -909,6 +913,69 @@ ChangeStatus AANoSyncFunction::updateImpl(Attributor &A) {
return ChangeStatus::UNCHANGED;
}
+/// ------------------------ No-Free Attributes ----------------------------
+
+struct AANoFreeFunction : AbstractAttribute, BooleanState {
+
+ /// See AbstractAttribute::AbstractAttribute(...).
+ AANoFreeFunction(Function &F, InformationCache &InfoCache)
+ : AbstractAttribute(F, InfoCache) {}
+
+ /// See AbstractAttribute::getState()
+ ///{
+ AbstractState &getState() override { return *this; }
+ const AbstractState &getState() const override { return *this; }
+ ///}
+
+ /// See AbstractAttribute::getManifestPosition().
+ ManifestPosition getManifestPosition() const override { return MP_FUNCTION; }
+
+ /// See AbstractAttribute::getAsStr().
+ const std::string getAsStr() const override {
+ return getAssumed() ? "nofree" : "may-free";
+ }
+
+ /// See AbstractAttribute::updateImpl(...).
+ ChangeStatus updateImpl(Attributor &A) override;
+
+ /// See AbstractAttribute::getAttrKind().
+ Attribute::AttrKind getAttrKind() const override { return ID; }
+
+ /// Return true if "nofree" is assumed.
+ bool isAssumedNoFree() const { return getAssumed(); }
+
+ /// Return true if "nofree" is known.
+ bool isKnownNoFree() const { return getKnown(); }
+
+ /// The identifier used by the Attributor for this class of attributes.
+ static constexpr Attribute::AttrKind ID = Attribute::NoFree;
+};
+
+ChangeStatus AANoFreeFunction::updateImpl(Attributor &A) {
+ Function &F = getAnchorScope();
+
+ // The map from instruction opcodes to those instructions in the function.
+ auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
+
+ for (unsigned Opcode :
+ {(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
+ (unsigned)Instruction::Call}) {
+ for (Instruction *I : OpcodeInstMap[Opcode]) {
+
+ auto ICS = ImmutableCallSite(I);
+ auto *NoFreeAA = A.getAAFor<AANoFreeFunction>(*this, *I);
+
+ if ((!NoFreeAA || !NoFreeAA->isValidState() ||
+ !NoFreeAA->isAssumedNoFree()) &&
+ !ICS.hasFnAttr(Attribute::NoFree)) {
+ indicatePessimisticFixpoint();
+ return ChangeStatus::CHANGED;
+ }
+ }
+ }
+ return ChangeStatus::UNCHANGED;
+}
+
/// ----------------------------------------------------------------------------
/// Attributor
/// ----------------------------------------------------------------------------
@@ -1057,6 +1124,9 @@ void Attributor::identifyDefaultAbstractAttributes(
// Every function might be marked "nosync"
registerAA(*new AANoSyncFunction(F, InfoCache));
+ // Every function might be "no-free".
+ registerAA(*new AANoFreeFunction(F, InfoCache));
+
// Return attributes are only appropriate if the return type is non void.
Type *ReturnType = F.getReturnType();
if (!ReturnType->isVoidTy()) {
OpenPOWER on IntegriCloud