mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-06 09:06:21 +01:00
[NFC][Attributor] Expose getOrCreateAAFor and lookupAAFor
We are starting to use the Attributor outside the Attributor itself and we need these to be able to seed and querry AAs.
This commit is contained in:
@@ -872,6 +872,88 @@ struct Attributor {
|
||||
/* ForceUpdate */ true);
|
||||
}
|
||||
|
||||
/// The version of getAAFor that allows to omit a querying abstract
|
||||
/// attribute. Using this after Attributor started running is restricted to
|
||||
/// only the Attributor itself. Initial seeding of AAs can be done via this
|
||||
/// function.
|
||||
template <typename AAType>
|
||||
const AAType &getOrCreateAAFor(const IRPosition &IRP,
|
||||
const AbstractAttribute *QueryingAA = nullptr,
|
||||
bool TrackDependence = false,
|
||||
DepClassTy DepClass = DepClassTy::OPTIONAL,
|
||||
bool ForceUpdate = false) {
|
||||
if (AAType *AAPtr = lookupAAFor<AAType>(IRP, QueryingAA, TrackDependence)) {
|
||||
if (ForceUpdate)
|
||||
updateAA(*AAPtr);
|
||||
return *AAPtr;
|
||||
}
|
||||
|
||||
// No matching attribute found, create one.
|
||||
// Use the static create method.
|
||||
auto &AA = AAType::createForPosition(IRP, *this);
|
||||
registerAA(AA);
|
||||
|
||||
// For now we ignore naked and optnone functions.
|
||||
bool Invalidate = Whitelist && !Whitelist->count(&AAType::ID);
|
||||
const Function *FnScope = IRP.getAnchorScope();
|
||||
if (FnScope)
|
||||
Invalidate |= FnScope->hasFnAttribute(Attribute::Naked) ||
|
||||
FnScope->hasFnAttribute(Attribute::OptimizeNone);
|
||||
|
||||
// Bootstrap the new attribute with an initial update to propagate
|
||||
// information, e.g., function -> call site. If it is not on a given
|
||||
// whitelist we will not perform updates at all.
|
||||
if (Invalidate) {
|
||||
AA.getState().indicatePessimisticFixpoint();
|
||||
return AA;
|
||||
}
|
||||
|
||||
AA.initialize(*this);
|
||||
|
||||
// We can initialize (=look at) code outside the current function set but
|
||||
// not call update because that would again spawn new abstract attributes in
|
||||
// potentially unconnected code regions (=SCCs).
|
||||
if (FnScope && !Functions.count(const_cast<Function *>(FnScope))) {
|
||||
AA.getState().indicatePessimisticFixpoint();
|
||||
return AA;
|
||||
}
|
||||
|
||||
updateAA(AA);
|
||||
|
||||
if (TrackDependence && AA.getState().isValidState())
|
||||
recordDependence(AA, const_cast<AbstractAttribute &>(*QueryingAA),
|
||||
DepClass);
|
||||
return AA;
|
||||
}
|
||||
|
||||
/// Return the attribute of \p AAType for \p IRP if existing. This also allows
|
||||
/// non-AA users lookup.
|
||||
template <typename AAType>
|
||||
AAType *lookupAAFor(const IRPosition &IRP,
|
||||
const AbstractAttribute *QueryingAA = nullptr,
|
||||
bool TrackDependence = false,
|
||||
DepClassTy DepClass = DepClassTy::OPTIONAL) {
|
||||
static_assert(std::is_base_of<AbstractAttribute, AAType>::value,
|
||||
"Cannot query an attribute with a type not derived from "
|
||||
"'AbstractAttribute'!");
|
||||
assert((QueryingAA || !TrackDependence) &&
|
||||
"Cannot track dependences without a QueryingAA!");
|
||||
|
||||
// Lookup the abstract attribute of type AAType. If found, return it after
|
||||
// registering a dependence of QueryingAA on the one returned attribute.
|
||||
AbstractAttribute *AAPtr = AAMap.lookup({&AAType::ID, IRP});
|
||||
if (!AAPtr)
|
||||
return nullptr;
|
||||
|
||||
AAType *AA = static_cast<AAType *>(AAPtr);
|
||||
|
||||
// Do not register a dependence on an attribute with an invalid state.
|
||||
if (TrackDependence && AA->getState().isValidState())
|
||||
recordDependence(*AA, const_cast<AbstractAttribute &>(*QueryingAA),
|
||||
DepClass);
|
||||
return AA;
|
||||
}
|
||||
|
||||
/// Explicitly record a dependence from \p FromAA to \p ToAA, that is if
|
||||
/// \p FromAA changes \p ToAA should be updated as well.
|
||||
///
|
||||
@@ -1249,85 +1331,6 @@ private:
|
||||
const AbstractAttribute *QueryingAA,
|
||||
bool &AllCallSitesKnown);
|
||||
|
||||
/// The private version of getAAFor that allows to omit a querying abstract
|
||||
/// attribute. See also the public getAAFor method.
|
||||
template <typename AAType>
|
||||
const AAType &getOrCreateAAFor(const IRPosition &IRP,
|
||||
const AbstractAttribute *QueryingAA = nullptr,
|
||||
bool TrackDependence = false,
|
||||
DepClassTy DepClass = DepClassTy::OPTIONAL,
|
||||
bool ForceUpdate = false) {
|
||||
if (AAType *AAPtr = lookupAAFor<AAType>(IRP, QueryingAA, TrackDependence)) {
|
||||
if (ForceUpdate)
|
||||
updateAA(*AAPtr);
|
||||
return *AAPtr;
|
||||
}
|
||||
|
||||
// No matching attribute found, create one.
|
||||
// Use the static create method.
|
||||
auto &AA = AAType::createForPosition(IRP, *this);
|
||||
registerAA(AA);
|
||||
|
||||
// For now we ignore naked and optnone functions.
|
||||
bool Invalidate = Whitelist && !Whitelist->count(&AAType::ID);
|
||||
const Function *FnScope = IRP.getAnchorScope();
|
||||
if (FnScope)
|
||||
Invalidate |= FnScope->hasFnAttribute(Attribute::Naked) ||
|
||||
FnScope->hasFnAttribute(Attribute::OptimizeNone);
|
||||
|
||||
// Bootstrap the new attribute with an initial update to propagate
|
||||
// information, e.g., function -> call site. If it is not on a given
|
||||
// whitelist we will not perform updates at all.
|
||||
if (Invalidate) {
|
||||
AA.getState().indicatePessimisticFixpoint();
|
||||
return AA;
|
||||
}
|
||||
|
||||
AA.initialize(*this);
|
||||
|
||||
// We can initialize (=look at) code outside the current function set but
|
||||
// not call update because that would again spawn new abstract attributes in
|
||||
// potentially unconnected code regions (=SCCs).
|
||||
if (FnScope && !Functions.count(const_cast<Function *>(FnScope))) {
|
||||
AA.getState().indicatePessimisticFixpoint();
|
||||
return AA;
|
||||
}
|
||||
|
||||
updateAA(AA);
|
||||
|
||||
if (TrackDependence && AA.getState().isValidState())
|
||||
recordDependence(AA, const_cast<AbstractAttribute &>(*QueryingAA),
|
||||
DepClass);
|
||||
return AA;
|
||||
}
|
||||
|
||||
/// Return the attribute of \p AAType for \p IRP if existing.
|
||||
template <typename AAType>
|
||||
AAType *lookupAAFor(const IRPosition &IRP,
|
||||
const AbstractAttribute *QueryingAA = nullptr,
|
||||
bool TrackDependence = false,
|
||||
DepClassTy DepClass = DepClassTy::OPTIONAL) {
|
||||
static_assert(std::is_base_of<AbstractAttribute, AAType>::value,
|
||||
"Cannot query an attribute with a type not derived from "
|
||||
"'AbstractAttribute'!");
|
||||
assert((QueryingAA || !TrackDependence) &&
|
||||
"Cannot track dependences without a QueryingAA!");
|
||||
|
||||
// Lookup the abstract attribute of type AAType. If found, return it after
|
||||
// registering a dependence of QueryingAA on the one returned attribute.
|
||||
AbstractAttribute *AAPtr = AAMap.lookup({&AAType::ID, IRP});
|
||||
if (!AAPtr)
|
||||
return nullptr;
|
||||
|
||||
AAType *AA = static_cast<AAType *>(AAPtr);
|
||||
|
||||
// Do not register a dependence on an attribute with an invalid state.
|
||||
if (TrackDependence && AA->getState().isValidState())
|
||||
recordDependence(*AA, const_cast<AbstractAttribute &>(*QueryingAA),
|
||||
DepClass);
|
||||
return AA;
|
||||
}
|
||||
|
||||
/// Apply all requested function signature rewrites
|
||||
/// (\see registerFunctionSignatureRewrite) and return Changed if the module
|
||||
/// was altered.
|
||||
|
||||
Reference in New Issue
Block a user