forked from OSchip/llvm-project
[Attributor] Make the InformationCache an Attributor member
The functionality is not changed but the interfaces are simplified and repetition is removed. llvm-svn: 368621
This commit is contained in:
parent
7f9bbe0599
commit
ece8190497
|
@ -96,9 +96,9 @@
|
||||||
#ifndef LLVM_TRANSFORMS_IPO_ATTRIBUTOR_H
|
#ifndef LLVM_TRANSFORMS_IPO_ATTRIBUTOR_H
|
||||||
#define LLVM_TRANSFORMS_IPO_ATTRIBUTOR_H
|
#define LLVM_TRANSFORMS_IPO_ATTRIBUTOR_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/SetVector.h"
|
||||||
#include "llvm/IR/CallSite.h"
|
#include "llvm/IR/CallSite.h"
|
||||||
#include "llvm/IR/PassManager.h"
|
#include "llvm/IR/PassManager.h"
|
||||||
#include "llvm/ADT/SetVector.h"
|
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
@ -147,6 +147,7 @@ ChangeStatus operator&(ChangeStatus l, ChangeStatus r);
|
||||||
/// NOTE: The mechanics of adding a new "concrete" abstract attribute are
|
/// NOTE: The mechanics of adding a new "concrete" abstract attribute are
|
||||||
/// described in the file comment.
|
/// described in the file comment.
|
||||||
struct Attributor {
|
struct Attributor {
|
||||||
|
Attributor(InformationCache &InfoCache) : InfoCache(InfoCache) {}
|
||||||
~Attributor() { DeleteContainerPointers(AllAbstractAttributes); }
|
~Attributor() { DeleteContainerPointers(AllAbstractAttributes); }
|
||||||
|
|
||||||
/// Run the analyses until a fixpoint is reached or enforced (timeout).
|
/// Run the analyses until a fixpoint is reached or enforced (timeout).
|
||||||
|
@ -155,7 +156,7 @@ struct Attributor {
|
||||||
/// as the Attributor is not destroyed (it owns the attributes now).
|
/// as the Attributor is not destroyed (it owns the attributes now).
|
||||||
///
|
///
|
||||||
/// \Returns CHANGED if the IR was changed, otherwise UNCHANGED.
|
/// \Returns CHANGED if the IR was changed, otherwise UNCHANGED.
|
||||||
ChangeStatus run(InformationCache &InfoCache);
|
ChangeStatus run();
|
||||||
|
|
||||||
/// Lookup an abstract attribute of type \p AAType anchored at value \p V and
|
/// Lookup an abstract attribute of type \p AAType anchored at value \p V and
|
||||||
/// argument number \p ArgNo. If no attribute is found and \p V is a call base
|
/// argument number \p ArgNo. If no attribute is found and \p V is a call base
|
||||||
|
@ -244,11 +245,13 @@ struct Attributor {
|
||||||
return AA;
|
return AA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the internal information cache.
|
||||||
|
InformationCache &getInfoCache() { return InfoCache; }
|
||||||
|
|
||||||
/// Determine opportunities to derive 'default' attributes in \p F and create
|
/// Determine opportunities to derive 'default' attributes in \p F and create
|
||||||
/// abstract attribute objects for them.
|
/// abstract attribute objects for them.
|
||||||
///
|
///
|
||||||
/// \param F The function that is checked for attribute opportunities.
|
/// \param F The function that is checked for attribute opportunities.
|
||||||
/// \param InfoCache A cache for information queryable by the new attributes.
|
|
||||||
/// \param Whitelist If not null, a set limiting the attribute opportunities.
|
/// \param Whitelist If not null, a set limiting the attribute opportunities.
|
||||||
///
|
///
|
||||||
/// Note that abstract attribute instances are generally created even if the
|
/// Note that abstract attribute instances are generally created even if the
|
||||||
|
@ -257,8 +260,7 @@ struct Attributor {
|
||||||
/// instance, which can be queried without the need to look at the IR in
|
/// instance, which can be queried without the need to look at the IR in
|
||||||
/// various places.
|
/// various places.
|
||||||
void identifyDefaultAbstractAttributes(
|
void identifyDefaultAbstractAttributes(
|
||||||
Function &F, InformationCache &InfoCache,
|
Function &F, DenseSet<const char *> *Whitelist = nullptr);
|
||||||
DenseSet<const char *> *Whitelist = nullptr);
|
|
||||||
|
|
||||||
/// Check \p Pred on all function call sites.
|
/// Check \p Pred on all function call sites.
|
||||||
///
|
///
|
||||||
|
@ -294,16 +296,16 @@ struct Attributor {
|
||||||
bool checkForAllInstructions(const Function &F,
|
bool checkForAllInstructions(const Function &F,
|
||||||
const function_ref<bool(Instruction &)> &Pred,
|
const function_ref<bool(Instruction &)> &Pred,
|
||||||
const AbstractAttribute &QueryingAA,
|
const AbstractAttribute &QueryingAA,
|
||||||
InformationCache &InfoCache,
|
|
||||||
const ArrayRef<unsigned> &Opcodes);
|
const ArrayRef<unsigned> &Opcodes);
|
||||||
|
|
||||||
/// Check \p Pred on all call-like instructions (=CallBased derived).
|
/// Check \p Pred on all call-like instructions (=CallBased derived).
|
||||||
///
|
///
|
||||||
/// See checkForAllCallLikeInstructions(...) for more information.
|
/// See checkForAllCallLikeInstructions(...) for more information.
|
||||||
bool checkForAllCallLikeInstructions(
|
bool
|
||||||
const Function &F, const function_ref<bool(Instruction &)> &Pred,
|
checkForAllCallLikeInstructions(const Function &F,
|
||||||
const AbstractAttribute &QueryingAA, InformationCache &InfoCache) {
|
const function_ref<bool(Instruction &)> &Pred,
|
||||||
return checkForAllInstructions(F, Pred, QueryingAA, InfoCache,
|
const AbstractAttribute &QueryingAA) {
|
||||||
|
return checkForAllInstructions(F, Pred, QueryingAA,
|
||||||
{(unsigned)Instruction::Invoke,
|
{(unsigned)Instruction::Invoke,
|
||||||
(unsigned)Instruction::CallBr,
|
(unsigned)Instruction::CallBr,
|
||||||
(unsigned)Instruction::Call});
|
(unsigned)Instruction::Call});
|
||||||
|
@ -312,11 +314,11 @@ struct Attributor {
|
||||||
/// Check \p Pred on all Read/Write instructions.
|
/// Check \p Pred on all Read/Write instructions.
|
||||||
///
|
///
|
||||||
/// This method will evaluate \p Pred on all instructions that read or write
|
/// This method will evaluate \p Pred on all instructions that read or write
|
||||||
/// to memory present in \p InfoCache and return true if \p Pred holds on all
|
/// to memory present in the information cache and return true if \p Pred
|
||||||
/// of them.
|
/// holds on all of them.
|
||||||
bool checkForAllReadWriteInstructions(
|
bool checkForAllReadWriteInstructions(
|
||||||
const Function &F, const llvm::function_ref<bool(Instruction &)> &Pred,
|
const Function &F, const llvm::function_ref<bool(Instruction &)> &Pred,
|
||||||
AbstractAttribute &QueryingAA, InformationCache &InfoCache);
|
AbstractAttribute &QueryingAA);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// The set of all abstract attributes.
|
/// The set of all abstract attributes.
|
||||||
|
@ -341,6 +343,9 @@ private:
|
||||||
DenseMap<AbstractAttribute *, SetVector<AbstractAttribute *>>;
|
DenseMap<AbstractAttribute *, SetVector<AbstractAttribute *>>;
|
||||||
QueryMapTy QueryMap;
|
QueryMapTy QueryMap;
|
||||||
///}
|
///}
|
||||||
|
|
||||||
|
/// The information cache that holds pre-processed (LLVM-IR) information.
|
||||||
|
InformationCache &InfoCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Data structure to hold cached (LLVM-IR) information.
|
/// Data structure to hold cached (LLVM-IR) information.
|
||||||
|
@ -356,6 +361,8 @@ private:
|
||||||
/// reusable, it is advised to inherit from the InformationCache and cast the
|
/// reusable, it is advised to inherit from the InformationCache and cast the
|
||||||
/// instance down in the abstract attributes.
|
/// instance down in the abstract attributes.
|
||||||
struct InformationCache {
|
struct InformationCache {
|
||||||
|
InformationCache(const DataLayout &DL) : DL(DL) {}
|
||||||
|
|
||||||
/// A map type from opcodes to instructions with this opcode.
|
/// A map type from opcodes to instructions with this opcode.
|
||||||
using OpcodeInstMapTy = DenseMap<unsigned, SmallVector<Instruction *, 32>>;
|
using OpcodeInstMapTy = DenseMap<unsigned, SmallVector<Instruction *, 32>>;
|
||||||
|
|
||||||
|
@ -387,6 +394,9 @@ private:
|
||||||
/// A map from functions to their instructions that may read or write memory.
|
/// A map from functions to their instructions that may read or write memory.
|
||||||
FuncRWInstsMapTy FuncRWInstsMap;
|
FuncRWInstsMapTy FuncRWInstsMap;
|
||||||
|
|
||||||
|
/// The datalayout used in the module.
|
||||||
|
const DataLayout &DL;
|
||||||
|
|
||||||
/// Give the Attributor access to the members so
|
/// Give the Attributor access to the members so
|
||||||
/// Attributor::identifyDefaultAbstractAttributes(...) can initialize them.
|
/// Attributor::identifyDefaultAbstractAttributes(...) can initialize them.
|
||||||
friend struct Attributor;
|
friend struct Attributor;
|
||||||
|
@ -705,8 +715,7 @@ struct StateWrapper : public StateTy, public Base {
|
||||||
|
|
||||||
/// Helper class that provides common functionality to manifest IR attributes.
|
/// Helper class that provides common functionality to manifest IR attributes.
|
||||||
template <Attribute::AttrKind AK, typename Base>
|
template <Attribute::AttrKind AK, typename Base>
|
||||||
struct IRAttribute : public IRPosition,
|
struct IRAttribute : public IRPosition, public Base {
|
||||||
public Base {
|
|
||||||
~IRAttribute() {}
|
~IRAttribute() {}
|
||||||
|
|
||||||
/// Constructors for the IRPosition.
|
/// Constructors for the IRPosition.
|
||||||
|
@ -796,7 +805,7 @@ struct AbstractAttribute {
|
||||||
/// - perform any work that is not going to change over time, e.g., determine
|
/// - perform any work that is not going to change over time, e.g., determine
|
||||||
/// a subset of the IR, or attributes in-flight, that have to be looked at
|
/// a subset of the IR, or attributes in-flight, that have to be looked at
|
||||||
/// in the `updateImpl` method.
|
/// in the `updateImpl` method.
|
||||||
virtual void initialize(Attributor &A, InformationCache &InfoCache) {}
|
virtual void initialize(Attributor &A) {}
|
||||||
|
|
||||||
/// Return the internal abstract state for inspection.
|
/// Return the internal abstract state for inspection.
|
||||||
virtual StateType &getState() = 0;
|
virtual StateType &getState() = 0;
|
||||||
|
@ -824,7 +833,7 @@ protected:
|
||||||
/// otherwise it delegates to `AbstractAttribute::updateImpl`.
|
/// otherwise it delegates to `AbstractAttribute::updateImpl`.
|
||||||
///
|
///
|
||||||
/// \Return CHANGED if the internal state changed, otherwise UNCHANGED.
|
/// \Return CHANGED if the internal state changed, otherwise UNCHANGED.
|
||||||
ChangeStatus update(Attributor &A, InformationCache &InfoCache);
|
ChangeStatus update(Attributor &A);
|
||||||
|
|
||||||
/// Hook for the Attributor to trigger the manifestation of the information
|
/// Hook for the Attributor to trigger the manifestation of the information
|
||||||
/// represented by the abstract attribute in the LLVM-IR.
|
/// represented by the abstract attribute in the LLVM-IR.
|
||||||
|
@ -851,8 +860,7 @@ protected:
|
||||||
/// the current information is still valid or adjust it otherwise.
|
/// the current information is still valid or adjust it otherwise.
|
||||||
///
|
///
|
||||||
/// \Return CHANGED if the internal state changed, otherwise UNCHANGED.
|
/// \Return CHANGED if the internal state changed, otherwise UNCHANGED.
|
||||||
virtual ChangeStatus updateImpl(Attributor &A,
|
virtual ChangeStatus updateImpl(Attributor &A) = 0;
|
||||||
InformationCache &InfoCache) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Forward declarations of output streams for debug purposes.
|
/// Forward declarations of output streams for debug purposes.
|
||||||
|
|
|
@ -247,15 +247,14 @@ static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr,
|
||||||
llvm_unreachable("Expected enum or string attribute!");
|
llvm_unreachable("Expected enum or string attribute!");
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangeStatus AbstractAttribute::update(Attributor &A,
|
ChangeStatus AbstractAttribute::update(Attributor &A) {
|
||||||
InformationCache &InfoCache) {
|
|
||||||
ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
|
ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
|
||||||
if (getState().isAtFixpoint())
|
if (getState().isAtFixpoint())
|
||||||
return HasChanged;
|
return HasChanged;
|
||||||
|
|
||||||
LLVM_DEBUG(dbgs() << "[Attributor] Update: " << *this << "\n");
|
LLVM_DEBUG(dbgs() << "[Attributor] Update: " << *this << "\n");
|
||||||
|
|
||||||
HasChanged = updateImpl(A, InfoCache);
|
HasChanged = updateImpl(A);
|
||||||
|
|
||||||
LLVM_DEBUG(dbgs() << "[Attributor] Update " << HasChanged << " " << *this
|
LLVM_DEBUG(dbgs() << "[Attributor] Update " << HasChanged << " " << *this
|
||||||
<< "\n");
|
<< "\n");
|
||||||
|
@ -324,7 +323,7 @@ struct AANoUnwindImpl : AANoUnwind {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See AbstractAttribute::updateImpl(...).
|
/// See AbstractAttribute::updateImpl(...).
|
||||||
ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
|
ChangeStatus updateImpl(Attributor &A) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AANoUnwindFunction final : public AANoUnwindImpl {
|
struct AANoUnwindFunction final : public AANoUnwindImpl {
|
||||||
|
@ -336,8 +335,7 @@ struct AANoUnwindFunction final : public AANoUnwindImpl {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ChangeStatus AANoUnwindImpl::updateImpl(Attributor &A,
|
ChangeStatus AANoUnwindImpl::updateImpl(Attributor &A) {
|
||||||
InformationCache &InfoCache) {
|
|
||||||
Function &F = getAnchorScope();
|
Function &F = getAnchorScope();
|
||||||
|
|
||||||
// The map from instruction opcodes to those instructions in the function.
|
// The map from instruction opcodes to those instructions in the function.
|
||||||
|
@ -354,8 +352,7 @@ ChangeStatus AANoUnwindImpl::updateImpl(Attributor &A,
|
||||||
return NoUnwindAA && NoUnwindAA->isAssumedNoUnwind();
|
return NoUnwindAA && NoUnwindAA->isAssumedNoUnwind();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!A.checkForAllInstructions(F, CheckForNoUnwind, *this, InfoCache,
|
if (!A.checkForAllInstructions(F, CheckForNoUnwind, *this, Opcodes))
|
||||||
Opcodes))
|
|
||||||
return indicatePessimisticFixpoint();
|
return indicatePessimisticFixpoint();
|
||||||
|
|
||||||
return ChangeStatus::UNCHANGED;
|
return ChangeStatus::UNCHANGED;
|
||||||
|
@ -411,7 +408,7 @@ public:
|
||||||
IRPositionConstructorForward(AAReturnedValuesImpl, AAReturnedValues);
|
IRPositionConstructorForward(AAReturnedValuesImpl, AAReturnedValues);
|
||||||
|
|
||||||
/// See AbstractAttribute::initialize(...).
|
/// See AbstractAttribute::initialize(...).
|
||||||
void initialize(Attributor &A, InformationCache &InfoCache) override {
|
void initialize(Attributor &A) override {
|
||||||
// Reset the state.
|
// Reset the state.
|
||||||
setAssociatedValue(nullptr);
|
setAssociatedValue(nullptr);
|
||||||
IsFixed = false;
|
IsFixed = false;
|
||||||
|
@ -422,7 +419,7 @@ public:
|
||||||
Function &F = getAnchorScope();
|
Function &F = getAnchorScope();
|
||||||
|
|
||||||
// The map from instruction opcodes to those instructions in the function.
|
// The map from instruction opcodes to those instructions in the function.
|
||||||
auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
|
auto &OpcodeInstMap = A.getInfoCache().getOpcodeInstMapForFunction(F);
|
||||||
|
|
||||||
// Look through all arguments, if one is marked as returned we are done.
|
// Look through all arguments, if one is marked as returned we are done.
|
||||||
for (Argument &Arg : F.args()) {
|
for (Argument &Arg : F.args()) {
|
||||||
|
@ -456,7 +453,7 @@ public:
|
||||||
const AbstractState &getState() const override { return *this; }
|
const AbstractState &getState() const override { return *this; }
|
||||||
|
|
||||||
/// See AbstractAttribute::updateImpl(Attributor &A).
|
/// See AbstractAttribute::updateImpl(Attributor &A).
|
||||||
ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
|
ChangeStatus updateImpl(Attributor &A) override;
|
||||||
|
|
||||||
/// Return the number of potential return values, -1 if unknown.
|
/// Return the number of potential return values, -1 if unknown.
|
||||||
size_t getNumReturnValues() const {
|
size_t getNumReturnValues() const {
|
||||||
|
@ -595,8 +592,7 @@ bool AAReturnedValuesImpl::checkForAllReturnedValuesAndReturnInsts(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A,
|
ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) {
|
||||||
InformationCache &InfoCache) {
|
|
||||||
|
|
||||||
// Check if we know of any values returned by the associated function,
|
// Check if we know of any values returned by the associated function,
|
||||||
// if not, we are done.
|
// if not, we are done.
|
||||||
|
@ -726,7 +722,7 @@ struct AANoSyncImpl : AANoSync {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See AbstractAttribute::updateImpl(...).
|
/// See AbstractAttribute::updateImpl(...).
|
||||||
ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
|
ChangeStatus updateImpl(Attributor &A) override;
|
||||||
|
|
||||||
/// Helper function used to determine whether an instruction is non-relaxed
|
/// Helper function used to determine whether an instruction is non-relaxed
|
||||||
/// atomic. In other words, if an atomic instruction does not have unordered
|
/// atomic. In other words, if an atomic instruction does not have unordered
|
||||||
|
@ -837,8 +833,7 @@ bool AANoSyncImpl::isVolatile(Instruction *I) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangeStatus AANoSyncImpl::updateImpl(Attributor &A,
|
ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {
|
||||||
InformationCache &InfoCache) {
|
|
||||||
Function &F = getAnchorScope();
|
Function &F = getAnchorScope();
|
||||||
|
|
||||||
auto CheckRWInstForNoSync = [&](Instruction &I) {
|
auto CheckRWInstForNoSync = [&](Instruction &I) {
|
||||||
|
@ -874,9 +869,8 @@ ChangeStatus AANoSyncImpl::updateImpl(Attributor &A,
|
||||||
return !ImmutableCallSite(&I).isConvergent();
|
return !ImmutableCallSite(&I).isConvergent();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!A.checkForAllReadWriteInstructions(F, CheckRWInstForNoSync, *this,
|
if (!A.checkForAllReadWriteInstructions(F, CheckRWInstForNoSync, *this) ||
|
||||||
InfoCache) ||
|
!A.checkForAllCallLikeInstructions(F, CheckForNoSync, *this))
|
||||||
!A.checkForAllCallLikeInstructions(F, CheckForNoSync, *this, InfoCache))
|
|
||||||
return indicatePessimisticFixpoint();
|
return indicatePessimisticFixpoint();
|
||||||
|
|
||||||
return ChangeStatus::UNCHANGED;
|
return ChangeStatus::UNCHANGED;
|
||||||
|
@ -893,7 +887,7 @@ struct AANoFreeImpl : public AANoFree {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See AbstractAttribute::updateImpl(...).
|
/// See AbstractAttribute::updateImpl(...).
|
||||||
ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
|
ChangeStatus updateImpl(Attributor &A) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AANoFreeFunction final : public AANoFreeImpl {
|
struct AANoFreeFunction final : public AANoFreeImpl {
|
||||||
|
@ -903,8 +897,7 @@ struct AANoFreeFunction final : public AANoFreeImpl {
|
||||||
void trackStatistics() const override { STATS_DECL_AND_TRACK_FN_ATTR(nofree) }
|
void trackStatistics() const override { STATS_DECL_AND_TRACK_FN_ATTR(nofree) }
|
||||||
};
|
};
|
||||||
|
|
||||||
ChangeStatus AANoFreeImpl::updateImpl(Attributor &A,
|
ChangeStatus AANoFreeImpl::updateImpl(Attributor &A) {
|
||||||
InformationCache &InfoCache) {
|
|
||||||
Function &F = getAnchorScope();
|
Function &F = getAnchorScope();
|
||||||
|
|
||||||
auto CheckForNoFree = [&](Instruction &I) {
|
auto CheckForNoFree = [&](Instruction &I) {
|
||||||
|
@ -915,7 +908,7 @@ ChangeStatus AANoFreeImpl::updateImpl(Attributor &A,
|
||||||
return NoFreeAA && NoFreeAA->isAssumedNoFree();
|
return NoFreeAA && NoFreeAA->isAssumedNoFree();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!A.checkForAllCallLikeInstructions(F, CheckForNoFree, *this, InfoCache))
|
if (!A.checkForAllCallLikeInstructions(F, CheckForNoFree, *this))
|
||||||
return indicatePessimisticFixpoint();
|
return indicatePessimisticFixpoint();
|
||||||
return ChangeStatus::UNCHANGED;
|
return ChangeStatus::UNCHANGED;
|
||||||
}
|
}
|
||||||
|
@ -972,7 +965,7 @@ struct AANonNullReturned final : AANonNullImpl {
|
||||||
AANonNullReturned(Function &F) : AANonNullImpl(F, IRP_RETURNED) {}
|
AANonNullReturned(Function &F) : AANonNullImpl(F, IRP_RETURNED) {}
|
||||||
|
|
||||||
/// See AbstractAttribute::initialize(...).
|
/// See AbstractAttribute::initialize(...).
|
||||||
void initialize(Attributor &A, InformationCache &InfoCache) override {
|
void initialize(Attributor &A) override {
|
||||||
Function &F = getAnchorScope();
|
Function &F = getAnchorScope();
|
||||||
|
|
||||||
// Already nonnull.
|
// Already nonnull.
|
||||||
|
@ -984,7 +977,7 @@ struct AANonNullReturned final : AANonNullImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See AbstractAttribute::updateImpl(...).
|
/// See AbstractAttribute::updateImpl(...).
|
||||||
ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
|
ChangeStatus updateImpl(Attributor &A) override;
|
||||||
|
|
||||||
/// See AbstractAttribute::trackStatistics()
|
/// See AbstractAttribute::trackStatistics()
|
||||||
void trackStatistics() const override {
|
void trackStatistics() const override {
|
||||||
|
@ -992,8 +985,7 @@ struct AANonNullReturned final : AANonNullImpl {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ChangeStatus AANonNullReturned::updateImpl(Attributor &A,
|
ChangeStatus AANonNullReturned::updateImpl(Attributor &A) {
|
||||||
InformationCache &InfoCache) {
|
|
||||||
Function &F = getAnchorScope();
|
Function &F = getAnchorScope();
|
||||||
|
|
||||||
std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)> Pred =
|
std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)> Pred =
|
||||||
|
@ -1009,14 +1001,14 @@ struct AANonNullArgument final : AANonNullImpl {
|
||||||
AANonNullArgument(Argument &A) : AANonNullImpl(A) {}
|
AANonNullArgument(Argument &A) : AANonNullImpl(A) {}
|
||||||
|
|
||||||
/// See AbstractAttriubute::initialize(...).
|
/// See AbstractAttriubute::initialize(...).
|
||||||
void initialize(Attributor &A, InformationCache &InfoCache) override {
|
void initialize(Attributor &A) override {
|
||||||
Argument *Arg = cast<Argument>(getAssociatedValue());
|
Argument *Arg = cast<Argument>(getAssociatedValue());
|
||||||
if (Arg->hasNonNullAttr())
|
if (Arg->hasNonNullAttr())
|
||||||
indicateOptimisticFixpoint();
|
indicateOptimisticFixpoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See AbstractAttribute::updateImpl(...).
|
/// See AbstractAttribute::updateImpl(...).
|
||||||
ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
|
ChangeStatus updateImpl(Attributor &A) override;
|
||||||
|
|
||||||
/// See AbstractAttribute::trackStatistics()
|
/// See AbstractAttribute::trackStatistics()
|
||||||
void trackStatistics() const override {
|
void trackStatistics() const override {
|
||||||
|
@ -1030,7 +1022,7 @@ struct AANonNullCallSiteArgument final : AANonNullImpl {
|
||||||
: AANonNullImpl(CallSite(&I).getArgOperand(ArgNo), I, ArgNo) {}
|
: AANonNullImpl(CallSite(&I).getArgOperand(ArgNo), I, ArgNo) {}
|
||||||
|
|
||||||
/// See AbstractAttribute::initialize(...).
|
/// See AbstractAttribute::initialize(...).
|
||||||
void initialize(Attributor &A, InformationCache &InfoCache) override {
|
void initialize(Attributor &A) override {
|
||||||
CallSite CS(&getAnchorValue());
|
CallSite CS(&getAnchorValue());
|
||||||
if (CS.paramHasAttr(getArgNo(), getAttrKind()) ||
|
if (CS.paramHasAttr(getArgNo(), getAttrKind()) ||
|
||||||
CS.paramHasAttr(getArgNo(), Attribute::Dereferenceable) ||
|
CS.paramHasAttr(getArgNo(), Attribute::Dereferenceable) ||
|
||||||
|
@ -1040,7 +1032,7 @@ struct AANonNullCallSiteArgument final : AANonNullImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See AbstractAttribute::updateImpl(Attributor &A).
|
/// See AbstractAttribute::updateImpl(Attributor &A).
|
||||||
ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
|
ChangeStatus updateImpl(Attributor &A) override;
|
||||||
|
|
||||||
/// See AbstractAttribute::trackStatistics()
|
/// See AbstractAttribute::trackStatistics()
|
||||||
void trackStatistics() const override {
|
void trackStatistics() const override {
|
||||||
|
@ -1048,8 +1040,7 @@ struct AANonNullCallSiteArgument final : AANonNullImpl {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ChangeStatus AANonNullArgument::updateImpl(Attributor &A,
|
ChangeStatus AANonNullArgument::updateImpl(Attributor &A) {
|
||||||
InformationCache &InfoCache) {
|
|
||||||
Function &F = getAnchorScope();
|
Function &F = getAnchorScope();
|
||||||
unsigned ArgNo = getArgNo();
|
unsigned ArgNo = getArgNo();
|
||||||
|
|
||||||
|
@ -1082,9 +1073,7 @@ ChangeStatus AANonNullArgument::updateImpl(Attributor &A,
|
||||||
return ChangeStatus::UNCHANGED;
|
return ChangeStatus::UNCHANGED;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangeStatus
|
ChangeStatus AANonNullCallSiteArgument::updateImpl(Attributor &A) {
|
||||||
AANonNullCallSiteArgument::updateImpl(Attributor &A,
|
|
||||||
InformationCache &InfoCache) {
|
|
||||||
// NOTE: Never look at the argument of the callee in this method.
|
// NOTE: Never look at the argument of the callee in this method.
|
||||||
// If we do this, "nonnull" is always deduced because of the assumption.
|
// If we do this, "nonnull" is always deduced because of the assumption.
|
||||||
|
|
||||||
|
@ -1113,10 +1102,10 @@ struct AAWillReturnFunction final : AAWillReturnImpl {
|
||||||
AAWillReturnFunction(Function &F) : AAWillReturnImpl(F, IRP_FUNCTION) {}
|
AAWillReturnFunction(Function &F) : AAWillReturnImpl(F, IRP_FUNCTION) {}
|
||||||
|
|
||||||
/// See AbstractAttribute::initialize(...).
|
/// See AbstractAttribute::initialize(...).
|
||||||
void initialize(Attributor &A, InformationCache &InfoCache) override;
|
void initialize(Attributor &A) override;
|
||||||
|
|
||||||
/// See AbstractAttribute::updateImpl(...).
|
/// See AbstractAttribute::updateImpl(...).
|
||||||
ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
|
ChangeStatus updateImpl(Attributor &A) override;
|
||||||
|
|
||||||
/// See AbstractAttribute::trackStatistics()
|
/// See AbstractAttribute::trackStatistics()
|
||||||
void trackStatistics() const override {
|
void trackStatistics() const override {
|
||||||
|
@ -1146,16 +1135,14 @@ bool containsCycle(Function &F) {
|
||||||
// We have to allow some patterns.
|
// We have to allow some patterns.
|
||||||
bool containsPossiblyEndlessLoop(Function &F) { return containsCycle(F); }
|
bool containsPossiblyEndlessLoop(Function &F) { return containsCycle(F); }
|
||||||
|
|
||||||
void AAWillReturnFunction::initialize(Attributor &A,
|
void AAWillReturnFunction::initialize(Attributor &A) {
|
||||||
InformationCache &InfoCache) {
|
|
||||||
Function &F = getAnchorScope();
|
Function &F = getAnchorScope();
|
||||||
|
|
||||||
if (containsPossiblyEndlessLoop(F))
|
if (containsPossiblyEndlessLoop(F))
|
||||||
indicatePessimisticFixpoint();
|
indicatePessimisticFixpoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangeStatus AAWillReturnFunction::updateImpl(Attributor &A,
|
ChangeStatus AAWillReturnFunction::updateImpl(Attributor &A) {
|
||||||
InformationCache &InfoCache) {
|
|
||||||
const Function &F = getAnchorScope();
|
const Function &F = getAnchorScope();
|
||||||
// The map from instruction opcodes to those instructions in the function.
|
// The map from instruction opcodes to those instructions in the function.
|
||||||
|
|
||||||
|
@ -1176,8 +1163,7 @@ ChangeStatus AAWillReturnFunction::updateImpl(Attributor &A,
|
||||||
return NoRecurseAA && NoRecurseAA->isAssumedNoRecurse();
|
return NoRecurseAA && NoRecurseAA->isAssumedNoRecurse();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!A.checkForAllCallLikeInstructions(F, CheckForWillReturn, *this,
|
if (!A.checkForAllCallLikeInstructions(F, CheckForWillReturn, *this))
|
||||||
InfoCache))
|
|
||||||
return indicatePessimisticFixpoint();
|
return indicatePessimisticFixpoint();
|
||||||
|
|
||||||
return ChangeStatus::UNCHANGED;
|
return ChangeStatus::UNCHANGED;
|
||||||
|
@ -1198,7 +1184,7 @@ struct AANoAliasReturned final : AANoAliasImpl {
|
||||||
AANoAliasReturned(Function &F) : AANoAliasImpl(F, IRP_RETURNED) {}
|
AANoAliasReturned(Function &F) : AANoAliasImpl(F, IRP_RETURNED) {}
|
||||||
|
|
||||||
/// See AbstractAttriubute::initialize(...).
|
/// See AbstractAttriubute::initialize(...).
|
||||||
void initialize(Attributor &A, InformationCache &InfoCache) override {
|
void initialize(Attributor &A) override {
|
||||||
Function &F = getAnchorScope();
|
Function &F = getAnchorScope();
|
||||||
|
|
||||||
// Already noalias.
|
// Already noalias.
|
||||||
|
@ -1209,8 +1195,7 @@ struct AANoAliasReturned final : AANoAliasImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See AbstractAttribute::updateImpl(...).
|
/// See AbstractAttribute::updateImpl(...).
|
||||||
virtual ChangeStatus updateImpl(Attributor &A,
|
virtual ChangeStatus updateImpl(Attributor &A) override;
|
||||||
InformationCache &InfoCache) override;
|
|
||||||
|
|
||||||
/// See AbstractAttribute::trackStatistics()
|
/// See AbstractAttribute::trackStatistics()
|
||||||
void trackStatistics() const override {
|
void trackStatistics() const override {
|
||||||
|
@ -1218,8 +1203,7 @@ struct AANoAliasReturned final : AANoAliasImpl {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ChangeStatus AANoAliasReturned::updateImpl(Attributor &A,
|
ChangeStatus AANoAliasReturned::updateImpl(Attributor &A) {
|
||||||
InformationCache &InfoCache) {
|
|
||||||
Function &F = getAnchorScope();
|
Function &F = getAnchorScope();
|
||||||
|
|
||||||
auto CheckReturnValue = [&](Value &RV) -> bool {
|
auto CheckReturnValue = [&](Value &RV) -> bool {
|
||||||
|
@ -1260,7 +1244,7 @@ ChangeStatus AANoAliasReturned::updateImpl(Attributor &A,
|
||||||
struct AAIsDeadImpl : public AAIsDead {
|
struct AAIsDeadImpl : public AAIsDead {
|
||||||
IRPositionConstructorForward(AAIsDeadImpl, AAIsDead);
|
IRPositionConstructorForward(AAIsDeadImpl, AAIsDead);
|
||||||
|
|
||||||
void initialize(Attributor &A, InformationCache &InfoCache) override {
|
void initialize(Attributor &A) override {
|
||||||
const Function &F = getAnchorScope();
|
const Function &F = getAnchorScope();
|
||||||
|
|
||||||
ToBeExploredPaths.insert(&(F.getEntryBlock().front()));
|
ToBeExploredPaths.insert(&(F.getEntryBlock().front()));
|
||||||
|
@ -1351,7 +1335,7 @@ struct AAIsDeadImpl : public AAIsDead {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See AbstractAttribute::updateImpl(...).
|
/// See AbstractAttribute::updateImpl(...).
|
||||||
ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
|
ChangeStatus updateImpl(Attributor &A) override;
|
||||||
|
|
||||||
/// See AAIsDead::isAssumedDead(BasicBlock *).
|
/// See AAIsDead::isAssumedDead(BasicBlock *).
|
||||||
bool isAssumedDead(const BasicBlock *BB) const override {
|
bool isAssumedDead(const BasicBlock *BB) const override {
|
||||||
|
@ -1484,8 +1468,7 @@ const Instruction *AAIsDeadImpl::findNextNoReturn(Attributor &A,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangeStatus AAIsDeadImpl::updateImpl(Attributor &A,
|
ChangeStatus AAIsDeadImpl::updateImpl(Attributor &A) {
|
||||||
InformationCache &InfoCache) {
|
|
||||||
// Temporary collection to iterate over existing noreturn instructions. This
|
// Temporary collection to iterate over existing noreturn instructions. This
|
||||||
// will alow easier modification of NoReturnCalls collection
|
// will alow easier modification of NoReturnCalls collection
|
||||||
SmallVector<const Instruction *, 8> NoReturnChanged;
|
SmallVector<const Instruction *, 8> NoReturnChanged;
|
||||||
|
@ -1662,7 +1645,7 @@ struct AADereferenceableImpl : AADereferenceable, DerefState {
|
||||||
uint64_t computeAssumedDerefenceableBytes(Attributor &A, Value &V,
|
uint64_t computeAssumedDerefenceableBytes(Attributor &A, Value &V,
|
||||||
bool &IsNonNull, bool &IsGlobal);
|
bool &IsNonNull, bool &IsGlobal);
|
||||||
|
|
||||||
void initialize(Attributor &A, InformationCache &InfoCache) override {
|
void initialize(Attributor &A) override {
|
||||||
Function &F = getAnchorScope();
|
Function &F = getAnchorScope();
|
||||||
unsigned AttrIdx = getIRPosition().getAttrIdx();
|
unsigned AttrIdx = getIRPosition().getAttrIdx();
|
||||||
|
|
||||||
|
@ -1689,7 +1672,7 @@ struct AADereferenceableReturned final : AADereferenceableImpl {
|
||||||
: AADereferenceableImpl(F, IRP_RETURNED) {}
|
: AADereferenceableImpl(F, IRP_RETURNED) {}
|
||||||
|
|
||||||
/// See AbstractAttribute::updateImpl(...).
|
/// See AbstractAttribute::updateImpl(...).
|
||||||
ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
|
ChangeStatus updateImpl(Attributor &A) override;
|
||||||
|
|
||||||
/// See AbstractAttribute::trackStatistics()
|
/// See AbstractAttribute::trackStatistics()
|
||||||
void trackStatistics() const override {
|
void trackStatistics() const override {
|
||||||
|
@ -1743,9 +1726,7 @@ uint64_t AADereferenceableImpl::computeAssumedDerefenceableBytes(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangeStatus
|
ChangeStatus AADereferenceableReturned::updateImpl(Attributor &A) {
|
||||||
AADereferenceableReturned::updateImpl(Attributor &A,
|
|
||||||
InformationCache &InfoCache) {
|
|
||||||
Function &F = getAnchorScope();
|
Function &F = getAnchorScope();
|
||||||
auto BeforeState = static_cast<DerefState>(*this);
|
auto BeforeState = static_cast<DerefState>(*this);
|
||||||
|
|
||||||
|
@ -1773,7 +1754,7 @@ struct AADereferenceableArgument final : AADereferenceableImpl {
|
||||||
AADereferenceableArgument(Argument &A) : AADereferenceableImpl(A) {}
|
AADereferenceableArgument(Argument &A) : AADereferenceableImpl(A) {}
|
||||||
|
|
||||||
/// See AbstractAttribute::updateImpl(...).
|
/// See AbstractAttribute::updateImpl(...).
|
||||||
ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
|
ChangeStatus updateImpl(Attributor &A) override;
|
||||||
|
|
||||||
/// See AbstractAttribute::trackStatistics()
|
/// See AbstractAttribute::trackStatistics()
|
||||||
void trackStatistics() const override {
|
void trackStatistics() const override {
|
||||||
|
@ -1781,9 +1762,7 @@ struct AADereferenceableArgument final : AADereferenceableImpl {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ChangeStatus
|
ChangeStatus AADereferenceableArgument::updateImpl(Attributor &A) {
|
||||||
AADereferenceableArgument::updateImpl(Attributor &A,
|
|
||||||
InformationCache &InfoCache) {
|
|
||||||
Function &F = getAnchorScope();
|
Function &F = getAnchorScope();
|
||||||
Argument &Arg = cast<Argument>(getAnchorValue());
|
Argument &Arg = cast<Argument>(getAnchorValue());
|
||||||
|
|
||||||
|
@ -1835,7 +1814,7 @@ struct AADereferenceableCallSiteArgument final : AADereferenceableImpl {
|
||||||
: AADereferenceableImpl(CallSite(&I).getArgOperand(ArgNo), I, ArgNo) {}
|
: AADereferenceableImpl(CallSite(&I).getArgOperand(ArgNo), I, ArgNo) {}
|
||||||
|
|
||||||
/// See AbstractAttribute::initialize(...).
|
/// See AbstractAttribute::initialize(...).
|
||||||
void initialize(Attributor &A, InformationCache &InfoCache) override {
|
void initialize(Attributor &A) override {
|
||||||
CallSite CS(&getAnchorValue());
|
CallSite CS(&getAnchorValue());
|
||||||
if (CS.paramHasAttr(getArgNo(), Attribute::Dereferenceable))
|
if (CS.paramHasAttr(getArgNo(), Attribute::Dereferenceable))
|
||||||
takeKnownDerefBytesMaximum(CS.getDereferenceableBytes(getArgNo()));
|
takeKnownDerefBytesMaximum(CS.getDereferenceableBytes(getArgNo()));
|
||||||
|
@ -1845,7 +1824,7 @@ struct AADereferenceableCallSiteArgument final : AADereferenceableImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See AbstractAttribute::updateImpl(Attributor &A).
|
/// See AbstractAttribute::updateImpl(Attributor &A).
|
||||||
ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
|
ChangeStatus updateImpl(Attributor &A) override;
|
||||||
|
|
||||||
/// See AbstractAttribute::trackStatistics()
|
/// See AbstractAttribute::trackStatistics()
|
||||||
void trackStatistics() const override {
|
void trackStatistics() const override {
|
||||||
|
@ -1853,9 +1832,7 @@ struct AADereferenceableCallSiteArgument final : AADereferenceableImpl {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ChangeStatus
|
ChangeStatus AADereferenceableCallSiteArgument::updateImpl(Attributor &A) {
|
||||||
AADereferenceableCallSiteArgument::updateImpl(Attributor &A,
|
|
||||||
InformationCache &InfoCache) {
|
|
||||||
// NOTE: Never look at the argument of the callee in this method.
|
// NOTE: Never look at the argument of the callee in this method.
|
||||||
// If we do this, "dereferenceable" is always deduced because of the
|
// If we do this, "dereferenceable" is always deduced because of the
|
||||||
// assumption.
|
// assumption.
|
||||||
|
@ -1891,7 +1868,7 @@ struct AAAlignImpl : AAAlign {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See AbstractAttriubute::initialize(...).
|
/// See AbstractAttriubute::initialize(...).
|
||||||
void initialize(Attributor &A, InformationCache &InfoCache) override {
|
void initialize(Attributor &A) override {
|
||||||
takeAssumedMinimum(MAX_ALIGN);
|
takeAssumedMinimum(MAX_ALIGN);
|
||||||
|
|
||||||
Function &F = getAnchorScope();
|
Function &F = getAnchorScope();
|
||||||
|
@ -1916,7 +1893,7 @@ struct AAAlignReturned final : AAAlignImpl {
|
||||||
AAAlignReturned(Function &F) : AAAlignImpl(F, IRP_RETURNED) {}
|
AAAlignReturned(Function &F) : AAAlignImpl(F, IRP_RETURNED) {}
|
||||||
|
|
||||||
/// See AbstractAttribute::updateImpl(...).
|
/// See AbstractAttribute::updateImpl(...).
|
||||||
ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
|
ChangeStatus updateImpl(Attributor &A) override;
|
||||||
|
|
||||||
/// See AbstractAttribute::trackStatistics()
|
/// See AbstractAttribute::trackStatistics()
|
||||||
void trackStatistics() const override {
|
void trackStatistics() const override {
|
||||||
|
@ -1924,8 +1901,7 @@ struct AAAlignReturned final : AAAlignImpl {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ChangeStatus AAAlignReturned::updateImpl(Attributor &A,
|
ChangeStatus AAAlignReturned::updateImpl(Attributor &A) {
|
||||||
InformationCache &InfoCache) {
|
|
||||||
Function &F = getAnchorScope();
|
Function &F = getAnchorScope();
|
||||||
|
|
||||||
// Currently, align<n> is deduced if alignments in return values are assumed
|
// Currently, align<n> is deduced if alignments in return values are assumed
|
||||||
|
@ -1960,15 +1936,13 @@ struct AAAlignArgument final : AAAlignImpl {
|
||||||
AAAlignArgument(Argument &A) : AAAlignImpl(A) {}
|
AAAlignArgument(Argument &A) : AAAlignImpl(A) {}
|
||||||
|
|
||||||
/// See AbstractAttribute::updateImpl(...).
|
/// See AbstractAttribute::updateImpl(...).
|
||||||
virtual ChangeStatus updateImpl(Attributor &A,
|
virtual ChangeStatus updateImpl(Attributor &A) override;
|
||||||
InformationCache &InfoCache) override;
|
|
||||||
|
|
||||||
/// See AbstractAttribute::trackStatistics()
|
/// See AbstractAttribute::trackStatistics()
|
||||||
void trackStatistics() const override{STATS_DECL_AND_TRACK_ARG_ATTR(aligned)};
|
void trackStatistics() const override{STATS_DECL_AND_TRACK_ARG_ATTR(aligned)};
|
||||||
};
|
};
|
||||||
|
|
||||||
ChangeStatus AAAlignArgument::updateImpl(Attributor &A,
|
ChangeStatus AAAlignArgument::updateImpl(Attributor &A) {
|
||||||
InformationCache &InfoCache) {
|
|
||||||
|
|
||||||
Function &F = getAnchorScope();
|
Function &F = getAnchorScope();
|
||||||
Argument &Arg = cast<Argument>(getAnchorValue());
|
Argument &Arg = cast<Argument>(getAnchorValue());
|
||||||
|
@ -2010,14 +1984,14 @@ struct AAAlignCallSiteArgument final : AAAlignImpl {
|
||||||
: AAAlignImpl(CallSite(&I).getArgOperand(ArgNo), I, ArgNo) {}
|
: AAAlignImpl(CallSite(&I).getArgOperand(ArgNo), I, ArgNo) {}
|
||||||
|
|
||||||
/// See AbstractAttribute::initialize(...).
|
/// See AbstractAttribute::initialize(...).
|
||||||
void initialize(Attributor &A, InformationCache &InfoCache) override {
|
void initialize(Attributor &A) override {
|
||||||
CallSite CS(&getAnchorValue());
|
CallSite CS(&getAnchorValue());
|
||||||
takeKnownMaximum(getAssociatedValue()->getPointerAlignment(
|
takeKnownMaximum(getAssociatedValue()->getPointerAlignment(
|
||||||
getAnchorScope().getParent()->getDataLayout()));
|
getAnchorScope().getParent()->getDataLayout()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See AbstractAttribute::updateImpl(Attributor &A).
|
/// See AbstractAttribute::updateImpl(Attributor &A).
|
||||||
ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
|
ChangeStatus updateImpl(Attributor &A) override;
|
||||||
|
|
||||||
/// See AbstractAttribute::trackStatistics()
|
/// See AbstractAttribute::trackStatistics()
|
||||||
void trackStatistics() const override {
|
void trackStatistics() const override {
|
||||||
|
@ -2025,8 +1999,7 @@ struct AAAlignCallSiteArgument final : AAAlignImpl {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ChangeStatus AAAlignCallSiteArgument::updateImpl(Attributor &A,
|
ChangeStatus AAAlignCallSiteArgument::updateImpl(Attributor &A) {
|
||||||
InformationCache &InfoCache) {
|
|
||||||
// NOTE: Never look at the argument of the callee in this method.
|
// NOTE: Never look at the argument of the callee in this method.
|
||||||
// If we do this, "align" is always deduced because of the assumption.
|
// If we do this, "align" is always deduced because of the assumption.
|
||||||
|
|
||||||
|
@ -2055,18 +2028,17 @@ struct AANoReturnImpl : public AANoReturn {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See AbstractAttribute::initialize(...).
|
/// See AbstractAttribute::initialize(...).
|
||||||
void initialize(Attributor &A, InformationCache &InfoCache) override {
|
void initialize(Attributor &A) override {
|
||||||
Function &F = getAnchorScope();
|
Function &F = getAnchorScope();
|
||||||
if (F.hasFnAttribute(getAttrKind()))
|
if (F.hasFnAttribute(getAttrKind()))
|
||||||
indicateOptimisticFixpoint();
|
indicateOptimisticFixpoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See AbstractAttribute::updateImpl(Attributor &A).
|
/// See AbstractAttribute::updateImpl(Attributor &A).
|
||||||
virtual ChangeStatus updateImpl(Attributor &A,
|
virtual ChangeStatus updateImpl(Attributor &A) override {
|
||||||
InformationCache &InfoCache) override {
|
|
||||||
const Function &F = getAnchorScope();
|
const Function &F = getAnchorScope();
|
||||||
auto CheckForNoReturn = [](Instruction &) { return false; };
|
auto CheckForNoReturn = [](Instruction &) { return false; };
|
||||||
if (!A.checkForAllInstructions(F, CheckForNoReturn, *this, InfoCache,
|
if (!A.checkForAllInstructions(F, CheckForNoReturn, *this,
|
||||||
{(unsigned)Instruction::Ret}))
|
{(unsigned)Instruction::Ret}))
|
||||||
return indicatePessimisticFixpoint();
|
return indicatePessimisticFixpoint();
|
||||||
return ChangeStatus::UNCHANGED;
|
return ChangeStatus::UNCHANGED;
|
||||||
|
@ -2187,8 +2159,7 @@ bool Attributor::checkForAllReturnedValues(
|
||||||
|
|
||||||
bool Attributor::checkForAllInstructions(
|
bool Attributor::checkForAllInstructions(
|
||||||
const Function &F, const llvm::function_ref<bool(Instruction &)> &Pred,
|
const Function &F, const llvm::function_ref<bool(Instruction &)> &Pred,
|
||||||
const AbstractAttribute &QueryingAA, InformationCache &InfoCache,
|
const AbstractAttribute &QueryingAA, const ArrayRef<unsigned> &Opcodes) {
|
||||||
const ArrayRef<unsigned> &Opcodes) {
|
|
||||||
|
|
||||||
auto *LivenessAA = getAAFor<AAIsDead>(QueryingAA, F);
|
auto *LivenessAA = getAAFor<AAIsDead>(QueryingAA, F);
|
||||||
|
|
||||||
|
@ -2209,7 +2180,7 @@ bool Attributor::checkForAllInstructions(
|
||||||
|
|
||||||
bool Attributor::checkForAllReadWriteInstructions(
|
bool Attributor::checkForAllReadWriteInstructions(
|
||||||
const Function &F, const llvm::function_ref<bool(Instruction &)> &Pred,
|
const Function &F, const llvm::function_ref<bool(Instruction &)> &Pred,
|
||||||
AbstractAttribute &QueryingAA, InformationCache &InfoCache) {
|
AbstractAttribute &QueryingAA) {
|
||||||
|
|
||||||
auto *LivenessAA = getAAFor<AAIsDead>(QueryingAA, F);
|
auto *LivenessAA = getAAFor<AAIsDead>(QueryingAA, F);
|
||||||
|
|
||||||
|
@ -2225,10 +2196,10 @@ bool Attributor::checkForAllReadWriteInstructions(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangeStatus Attributor::run(InformationCache &InfoCache) {
|
ChangeStatus Attributor::run() {
|
||||||
// Initialize all abstract attributes.
|
// Initialize all abstract attributes.
|
||||||
for (AbstractAttribute *AA : AllAbstractAttributes)
|
for (AbstractAttribute *AA : AllAbstractAttributes)
|
||||||
AA->initialize(*this, InfoCache);
|
AA->initialize(*this);
|
||||||
|
|
||||||
LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized "
|
LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized "
|
||||||
<< AllAbstractAttributes.size()
|
<< AllAbstractAttributes.size()
|
||||||
|
@ -2260,7 +2231,7 @@ ChangeStatus Attributor::run(InformationCache &InfoCache) {
|
||||||
// Update all abstract attribute in the work list and record the ones that
|
// Update all abstract attribute in the work list and record the ones that
|
||||||
// changed.
|
// changed.
|
||||||
for (AbstractAttribute *AA : Worklist)
|
for (AbstractAttribute *AA : Worklist)
|
||||||
if (AA->update(*this, InfoCache) == ChangeStatus::CHANGED)
|
if (AA->update(*this) == ChangeStatus::CHANGED)
|
||||||
ChangedAAs.push_back(AA);
|
ChangedAAs.push_back(AA);
|
||||||
|
|
||||||
// Reset the work list and repopulate with the changed abstract attributes.
|
// Reset the work list and repopulate with the changed abstract attributes.
|
||||||
|
@ -2347,7 +2318,7 @@ ChangeStatus Attributor::run(InformationCache &InfoCache) {
|
||||||
if (VerifyAttributor && FinishedAtFixpoint &&
|
if (VerifyAttributor && FinishedAtFixpoint &&
|
||||||
ManifestChange == ChangeStatus::CHANGED) {
|
ManifestChange == ChangeStatus::CHANGED) {
|
||||||
VerifyAttributor = false;
|
VerifyAttributor = false;
|
||||||
ChangeStatus VerifyStatus = run(InfoCache);
|
ChangeStatus VerifyStatus = run();
|
||||||
if (VerifyStatus != ChangeStatus::UNCHANGED)
|
if (VerifyStatus != ChangeStatus::UNCHANGED)
|
||||||
llvm_unreachable(
|
llvm_unreachable(
|
||||||
"Attributor verification failed, re-run did result in an IR change "
|
"Attributor verification failed, re-run did result in an IR change "
|
||||||
|
@ -2381,8 +2352,7 @@ static AAType *checkAndRegisterAA(const Function &F, Attributor &A,
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attributor::identifyDefaultAbstractAttributes(
|
void Attributor::identifyDefaultAbstractAttributes(
|
||||||
Function &F, InformationCache &InfoCache,
|
Function &F, DenseSet<const char *> *Whitelist) {
|
||||||
DenseSet<const char *> *Whitelist) {
|
|
||||||
|
|
||||||
// Check for dead BasicBlocks in every function.
|
// Check for dead BasicBlocks in every function.
|
||||||
// We need dead instruction detection because we do not want to deal with
|
// We need dead instruction detection because we do not want to deal with
|
||||||
|
@ -2556,8 +2526,8 @@ static bool runAttributorOnModule(Module &M) {
|
||||||
|
|
||||||
// Create an Attributor and initially empty information cache that is filled
|
// Create an Attributor and initially empty information cache that is filled
|
||||||
// while we identify default attribute opportunities.
|
// while we identify default attribute opportunities.
|
||||||
Attributor A;
|
InformationCache InfoCache(M.getDataLayout());
|
||||||
InformationCache InfoCache;
|
Attributor A(InfoCache);
|
||||||
|
|
||||||
for (Function &F : M) {
|
for (Function &F : M) {
|
||||||
// TODO: Not all attributes require an exact definition. Find a way to
|
// TODO: Not all attributes require an exact definition. Find a way to
|
||||||
|
@ -2581,10 +2551,10 @@ static bool runAttributorOnModule(Module &M) {
|
||||||
|
|
||||||
// Populate the Attributor with abstract attribute opportunities in the
|
// Populate the Attributor with abstract attribute opportunities in the
|
||||||
// function and the information cache with IR information.
|
// function and the information cache with IR information.
|
||||||
A.identifyDefaultAbstractAttributes(F, InfoCache);
|
A.identifyDefaultAbstractAttributes(F);
|
||||||
}
|
}
|
||||||
|
|
||||||
return A.run(InfoCache) == ChangeStatus::CHANGED;
|
return A.run() == ChangeStatus::CHANGED;
|
||||||
}
|
}
|
||||||
|
|
||||||
PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) {
|
PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) {
|
||||||
|
|
Loading…
Reference in New Issue