[llvm] r369142 - [Attributor] Introduce initialize calls and move code to keep attributes concise
Johannes Doerfert via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 16 12:36:17 PDT 2019
Author: jdoerfert
Date: Fri Aug 16 12:36:17 2019
New Revision: 369142
URL: http://llvm.org/viewvc/llvm-project?rev=369142&view=rev
Log:
[Attributor] Introduce initialize calls and move code to keep attributes concise
Summary:
This patch should not change the behavior except that the added
initialize methods might indicate an optimistic fixpoint earlier. The
code movement is done to keep the attribute definitions in a single
block where it makes sense. No functional changes intended there.
Reviewers: uenoku, sstefan1
Subscribers: hiraditya, bollu, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D66258
Modified:
llvm/trunk/lib/Transforms/IPO/Attributor.cpp
Modified: llvm/trunk/lib/Transforms/IPO/Attributor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Attributor.cpp?rev=369142&r1=369141&r2=369142&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/Attributor.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/Attributor.cpp Fri Aug 16 12:36:17 2019
@@ -457,12 +457,36 @@ void IRPosition::verify() {
struct AANoUnwindImpl : AANoUnwind {
AANoUnwindImpl(const IRPosition &IRP) : AANoUnwind(IRP) {}
+ /// See AbstractAttribute::initialize(...).
+ void initialize(Attributor &A) override {
+ if (hasAttr({Attribute::NoUnwind}))
+ indicateOptimisticFixpoint();
+ }
+
const std::string getAsStr() const override {
return getAssumed() ? "nounwind" : "may-unwind";
}
/// See AbstractAttribute::updateImpl(...).
- ChangeStatus updateImpl(Attributor &A) override;
+ ChangeStatus updateImpl(Attributor &A) override {
+ auto Opcodes = {
+ (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
+ (unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet,
+ (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
+
+ auto CheckForNoUnwind = [&](Instruction &I) {
+ if (!I.mayThrow())
+ return true;
+
+ auto *NoUnwindAA = A.getAAFor<AANoUnwind>(*this, IRPosition::value(I));
+ return NoUnwindAA && NoUnwindAA->isAssumedNoUnwind();
+ };
+
+ if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes))
+ return indicatePessimisticFixpoint();
+
+ return ChangeStatus::UNCHANGED;
+ }
};
struct AANoUnwindFunction final : public AANoUnwindImpl {
@@ -472,28 +496,6 @@ struct AANoUnwindFunction final : public
void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nounwind) }
};
-ChangeStatus AANoUnwindImpl::updateImpl(Attributor &A) {
-
- // The map from instruction opcodes to those instructions in the function.
- auto Opcodes = {
- (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
- (unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet,
- (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
-
- auto CheckForNoUnwind = [&](Instruction &I) {
- if (!I.mayThrow())
- return true;
-
- auto *NoUnwindAA = A.getAAFor<AANoUnwind>(*this, IRPosition::value(I));
- return NoUnwindAA && NoUnwindAA->isAssumedNoUnwind();
- };
-
- if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes))
- return indicatePessimisticFixpoint();
-
- return ChangeStatus::UNCHANGED;
-}
-
/// --------------------- Function Return Values -------------------------------
/// "Attribute" that collects all potential returned values and the return
@@ -834,6 +836,12 @@ struct AAReturnedValuesFunction final :
struct AANoSyncImpl : AANoSync {
AANoSyncImpl(const IRPosition &IRP) : AANoSync(IRP) {}
+ /// See AbstractAttribute::initialize(...).
+ void initialize(Attributor &A) override {
+ if (hasAttr({Attribute::NoSync}))
+ indicateOptimisticFixpoint();
+ }
+
const std::string getAsStr() const override {
return getAssumed() ? "nosync" : "may-sync";
}
@@ -998,13 +1006,33 @@ ChangeStatus AANoSyncImpl::updateImpl(At
struct AANoFreeImpl : public AANoFree {
AANoFreeImpl(const IRPosition &IRP) : AANoFree(IRP) {}
+ /// See AbstractAttribute::initialize(...).
+ void initialize(Attributor &A) override {
+ if (hasAttr({Attribute::NoFree}))
+ indicateOptimisticFixpoint();
+ }
+
+ /// See AbstractAttribute::updateImpl(...).
+ ChangeStatus updateImpl(Attributor &A) override {
+ auto CheckForNoFree = [&](Instruction &I) {
+ ImmutableCallSite ICS(&I);
+ if (ICS.hasFnAttr(Attribute::NoFree))
+ return true;
+
+ auto *NoFreeAA =
+ A.getAAFor<AANoFreeImpl>(*this, IRPosition::callsite_function(ICS));
+ return NoFreeAA && NoFreeAA->isAssumedNoFree();
+ };
+
+ if (!A.checkForAllCallLikeInstructions(CheckForNoFree, *this))
+ return indicatePessimisticFixpoint();
+ return ChangeStatus::UNCHANGED;
+ }
+
/// See AbstractAttribute::getAsStr().
const std::string getAsStr() const override {
return getAssumed() ? "nofree" : "may-free";
}
-
- /// See AbstractAttribute::updateImpl(...).
- ChangeStatus updateImpl(Attributor &A) override;
};
struct AANoFreeFunction final : public AANoFreeImpl {
@@ -1014,23 +1042,6 @@ struct AANoFreeFunction final : public A
void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nofree) }
};
-ChangeStatus AANoFreeImpl::updateImpl(Attributor &A) {
-
- auto CheckForNoFree = [&](Instruction &I) {
- ImmutableCallSite ICS(&I);
- if (ICS.hasFnAttr(Attribute::NoFree))
- return true;
-
- auto *NoFreeAA =
- A.getAAFor<AANoFreeImpl>(*this, IRPosition::callsite_function(ICS));
- return NoFreeAA && NoFreeAA->isAssumedNoFree();
- };
-
- if (!A.checkForAllCallLikeInstructions(CheckForNoFree, *this))
- return indicatePessimisticFixpoint();
- return ChangeStatus::UNCHANGED;
-}
-
/// ------------------------ NonNull Argument Attribute ------------------------
struct AANonNullImpl : AANonNull {
AANonNullImpl(const IRPosition &IRP) : AANonNull(IRP) {}
@@ -1084,28 +1095,53 @@ struct AANonNullReturned final : AANonNu
AANonNullReturned(const IRPosition &IRP) : AANonNullImpl(IRP) {}
/// See AbstractAttribute::updateImpl(...).
- ChangeStatus updateImpl(Attributor &A) override;
+ ChangeStatus updateImpl(Attributor &A) override {
+ std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)> Pred =
+ this->generatePredicate(A);
+
+ if (!A.checkForAllReturnedValuesAndReturnInsts(Pred, *this))
+ return indicatePessimisticFixpoint();
+ return ChangeStatus::UNCHANGED;
+ }
/// See AbstractAttribute::trackStatistics()
void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
};
-ChangeStatus AANonNullReturned::updateImpl(Attributor &A) {
-
- std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)> Pred =
- this->generatePredicate(A);
-
- if (!A.checkForAllReturnedValuesAndReturnInsts(Pred, *this))
- return indicatePessimisticFixpoint();
- return ChangeStatus::UNCHANGED;
-}
-
/// NonNull attribute for function argument.
struct AANonNullArgument final : AANonNullImpl {
AANonNullArgument(const IRPosition &IRP) : AANonNullImpl(IRP) {}
/// See AbstractAttribute::updateImpl(...).
- ChangeStatus updateImpl(Attributor &A) override;
+ ChangeStatus updateImpl(Attributor &A) override {
+ unsigned ArgNo = getArgNo();
+
+ // Callback function
+ std::function<bool(CallSite)> CallSiteCheck = [&](CallSite CS) {
+ assert(CS && "Sanity check: Call site was not initialized properly!");
+
+ IRPosition CSArgPos = IRPosition::callsite_argument(CS, ArgNo);
+ if (CSArgPos.hasAttr({Attribute::NonNull, Attribute::Dereferenceable}))
+ return true;
+
+ // Check that NonNullAA is AANonNullCallSiteArgument.
+ if (auto *NonNullAA = A.getAAFor<AANonNullImpl>(*this, CSArgPos)) {
+ ImmutableCallSite ICS(&NonNullAA->getAnchorValue());
+ if (ICS && CS.getInstruction() == ICS.getInstruction())
+ return NonNullAA->isAssumedNonNull();
+ return false;
+ }
+
+ Value *V = CS.getArgOperand(ArgNo);
+ if (isKnownNonZero(V, A.getDataLayout()))
+ return true;
+
+ return false;
+ };
+ if (!A.checkForAllCallSites(CallSiteCheck, *this, true))
+ return indicatePessimisticFixpoint();
+ return ChangeStatus::UNCHANGED;
+ }
/// See AbstractAttribute::trackStatistics()
void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nonnull) }
@@ -1124,82 +1160,29 @@ struct AANonNullCallSiteArgument final :
}
/// See AbstractAttribute::updateImpl(Attributor &A).
- ChangeStatus updateImpl(Attributor &A) override;
+ ChangeStatus updateImpl(Attributor &A) override {
+ // NOTE: Never look at the argument of the callee in this method.
+ // If we do this, "nonnull" is always deduced because of the
+ // assumption.
- /// See AbstractAttribute::trackStatistics()
- void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nonnull) }
-};
+ Value &V = getAssociatedValue();
+ auto *NonNullAA = A.getAAFor<AANonNull>(*this, IRPosition::value(V));
-ChangeStatus AANonNullArgument::updateImpl(Attributor &A) {
- unsigned ArgNo = getArgNo();
+ if (!NonNullAA || !NonNullAA->isAssumedNonNull())
+ return indicatePessimisticFixpoint();
- // Callback function
- std::function<bool(CallSite)> CallSiteCheck = [&](CallSite CS) {
- assert(CS && "Sanity check: Call site was not initialized properly!");
-
- IRPosition CSArgPos = IRPosition::callsite_argument(CS, ArgNo);
- if (CSArgPos.hasAttr({Attribute::NonNull, Attribute::Dereferenceable}))
- return true;
-
- // Check that NonNullAA is AANonNullCallSiteArgument.
- if (auto *NonNullAA = A.getAAFor<AANonNullImpl>(*this, CSArgPos)) {
- ImmutableCallSite ICS(&NonNullAA->getAnchorValue());
- if (ICS && CS.getInstruction() == ICS.getInstruction())
- return NonNullAA->isAssumedNonNull();
- return false;
- }
-
- Value *V = CS.getArgOperand(ArgNo);
- if (isKnownNonZero(V, A.getDataLayout()))
- return true;
-
- return false;
- };
- if (!A.checkForAllCallSites(CallSiteCheck, *this, true))
- return indicatePessimisticFixpoint();
- return ChangeStatus::UNCHANGED;
-}
-
-ChangeStatus AANonNullCallSiteArgument::updateImpl(Attributor &A) {
- // NOTE: Never look at the argument of the callee in this method.
- // If we do this, "nonnull" is always deduced because of the assumption.
-
- Value &V = getAssociatedValue();
- auto *NonNullAA = A.getAAFor<AANonNull>(*this, IRPosition::value(V));
-
- if (!NonNullAA || !NonNullAA->isAssumedNonNull())
- return indicatePessimisticFixpoint();
-
- return ChangeStatus::UNCHANGED;
-}
-
-/// ------------------------ Will-Return Attributes ----------------------------
-
-struct AAWillReturnImpl : public AAWillReturn {
- AAWillReturnImpl(const IRPosition &IRP) : AAWillReturn(IRP) {}
-
- /// See AbstractAttribute::getAsStr()
- const std::string getAsStr() const override {
- return getAssumed() ? "willreturn" : "may-noreturn";
+ return ChangeStatus::UNCHANGED;
}
-};
-
-struct AAWillReturnFunction final : AAWillReturnImpl {
- AAWillReturnFunction(const IRPosition &IRP) : AAWillReturnImpl(IRP) {}
-
- /// See AbstractAttribute::initialize(...).
- void initialize(Attributor &A) override;
-
- /// See AbstractAttribute::updateImpl(...).
- ChangeStatus updateImpl(Attributor &A) override;
/// See AbstractAttribute::trackStatistics()
- void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(norecurse) }
+ void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nonnull) }
};
+/// ------------------------ Will-Return Attributes ----------------------------
+
// Helper function that checks whether a function has any cycle.
// TODO: Replace with more efficent code
-bool containsCycle(Function &F) {
+static bool containsCycle(Function &F) {
SmallPtrSet<BasicBlock *, 32> Visited;
// Traverse BB by dfs and check whether successor is already visited.
@@ -1217,41 +1200,61 @@ bool containsCycle(Function &F) {
// endless loop
// FIXME: Any cycle is regarded as endless loop for now.
// We have to allow some patterns.
-bool containsPossiblyEndlessLoop(Function &F) { return containsCycle(F); }
+static bool containsPossiblyEndlessLoop(Function &F) {
+ return containsCycle(F);
+}
-void AAWillReturnFunction::initialize(Attributor &A) {
- Function &F = *getAnchorScope();
+struct AAWillReturnImpl : public AAWillReturn {
+ AAWillReturnImpl(const IRPosition &IRP) : AAWillReturn(IRP) {}
- if (containsPossiblyEndlessLoop(F))
- indicatePessimisticFixpoint();
-}
+ /// See AbstractAttribute::getAsStr()
+ const std::string getAsStr() const override {
+ return getAssumed() ? "willreturn" : "may-noreturn";
+ }
+};
-ChangeStatus AAWillReturnFunction::updateImpl(Attributor &A) {
- // The map from instruction opcodes to those instructions in the function.
+struct AAWillReturnFunction final : AAWillReturnImpl {
+ AAWillReturnFunction(const IRPosition &IRP) : AAWillReturnImpl(IRP) {}
- auto CheckForWillReturn = [&](Instruction &I) {
- ImmutableCallSite ICS(&I);
- if (ICS.hasFnAttr(Attribute::WillReturn))
- return true;
+ /// See AbstractAttribute::initialize(...).
+ void initialize(Attributor &A) override {
+ Function &F = *getAnchorScope();
- IRPosition IPos = IRPosition::callsite_function(ICS);
- auto *WillReturnAA = A.getAAFor<AAWillReturn>(*this, IPos);
- if (!WillReturnAA || !WillReturnAA->isAssumedWillReturn())
- return false;
+ if (containsPossiblyEndlessLoop(F))
+ indicatePessimisticFixpoint();
+ }
- // FIXME: Prohibit any recursion for now.
- if (ICS.hasFnAttr(Attribute::NoRecurse))
- return true;
+ /// See AbstractAttribute::updateImpl(...).
+ ChangeStatus updateImpl(Attributor &A) override {
+ // The map from instruction opcodes to those instructions in the function.
- auto *NoRecurseAA = A.getAAFor<AANoRecurse>(*this, IPos);
- return NoRecurseAA && NoRecurseAA->isAssumedNoRecurse();
- };
+ auto CheckForWillReturn = [&](Instruction &I) {
+ ImmutableCallSite ICS(&I);
+ if (ICS.hasFnAttr(Attribute::WillReturn))
+ return true;
- if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this))
- return indicatePessimisticFixpoint();
+ IRPosition IPos = IRPosition::callsite_function(ICS);
+ auto *WillReturnAA = A.getAAFor<AAWillReturn>(*this, IPos);
+ if (!WillReturnAA || !WillReturnAA->isAssumedWillReturn())
+ return false;
- return ChangeStatus::UNCHANGED;
-}
+ // FIXME: Prohibit any recursion for now.
+ if (ICS.hasFnAttr(Attribute::NoRecurse))
+ return true;
+
+ auto *NoRecurseAA = A.getAAFor<AANoRecurse>(*this, IPos);
+ return NoRecurseAA && NoRecurseAA->isAssumedNoRecurse();
+ };
+
+ if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this))
+ return indicatePessimisticFixpoint();
+
+ return ChangeStatus::UNCHANGED;
+ }
+
+ /// See AbstractAttribute::trackStatistics()
+ void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(norecurse) }
+};
/// ------------------------ NoAlias Argument Attribute ------------------------
@@ -1279,47 +1282,45 @@ struct AANoAliasReturned final : AANoAli
}
/// See AbstractAttribute::updateImpl(...).
- virtual ChangeStatus updateImpl(Attributor &A) override;
+ virtual ChangeStatus updateImpl(Attributor &A) override {
- /// See AbstractAttribute::trackStatistics()
- void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noalias) }
-};
-
-ChangeStatus AANoAliasReturned::updateImpl(Attributor &A) {
-
- auto CheckReturnValue = [&](Value &RV) -> bool {
- if (Constant *C = dyn_cast<Constant>(&RV))
- if (C->isNullValue() || isa<UndefValue>(C))
- return true;
+ auto CheckReturnValue = [&](Value &RV) -> bool {
+ if (Constant *C = dyn_cast<Constant>(&RV))
+ if (C->isNullValue() || isa<UndefValue>(C))
+ return true;
+
+ /// For now, we can only deduce noalias if we have call sites.
+ /// FIXME: add more support.
+ ImmutableCallSite ICS(&RV);
+ if (!ICS)
+ return false;
- /// For now, we can only deduce noalias if we have call sites.
- /// FIXME: add more support.
- ImmutableCallSite ICS(&RV);
- if (!ICS)
- return false;
+ if (!ICS.returnDoesNotAlias()) {
+ auto *NoAliasAA =
+ A.getAAFor<AANoAlias>(*this, IRPosition::callsite_returned(ICS));
+ if (!NoAliasAA || !NoAliasAA->isAssumedNoAlias())
+ return false;
+ }
- if (!ICS.returnDoesNotAlias()) {
- auto *NoAliasAA =
- A.getAAFor<AANoAlias>(*this, IRPosition::callsite_returned(ICS));
- if (!NoAliasAA || !NoAliasAA->isAssumedNoAlias())
+ /// FIXME: We can improve capture check in two ways:
+ /// 1. Use the AANoCapture facilities.
+ /// 2. Use the location of return insts for escape queries.
+ if (PointerMayBeCaptured(&RV, /* ReturnCaptures */ false,
+ /* StoreCaptures */ true))
return false;
- }
- /// FIXME: We can improve capture check in two ways:
- /// 1. Use the AANoCapture facilities.
- /// 2. Use the location of return insts for escape queries.
- if (PointerMayBeCaptured(&RV, /* ReturnCaptures */ false,
- /* StoreCaptures */ true))
- return false;
+ return true;
+ };
- return true;
- };
+ if (!A.checkForAllReturnedValues(CheckReturnValue, *this))
+ return indicatePessimisticFixpoint();
- if (!A.checkForAllReturnedValues(CheckReturnValue, *this))
- return indicatePessimisticFixpoint();
+ return ChangeStatus::UNCHANGED;
+ }
- return ChangeStatus::UNCHANGED;
-}
+ /// See AbstractAttribute::trackStatistics()
+ void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noalias) }
+};
/// -------------------AAIsDead Function Attribute-----------------------
More information about the llvm-commits
mailing list