diff options
Diffstat (limited to 'llvm/lib/Transforms/IPO/Attributor.cpp')
-rw-r--r-- | llvm/lib/Transforms/IPO/Attributor.cpp | 70 |
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()) { |