[llvm] r367961 - [Attributor] Provide a generic interface to check live instructions
Johannes Doerfert via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 5 17:32:43 PDT 2019
Author: jdoerfert
Date: Mon Aug 5 17:32:43 2019
New Revision: 367961
URL: http://llvm.org/viewvc/llvm-project?rev=367961&view=rev
Log:
[Attributor] Provide a generic interface to check live instructions
Summary:
Similar to `Attributor::checkForAllCallSites`, we now provide such
functionality for instructions of a certain opcode through
`Attributor::checkForAllInstructions` and the convenient wrapper
`Attributor::checkForAllCallLikeInstructions`. This cleans up code,
avoids duplication, and simplifies the usage of liveness information.
Reviewers: sstefan1, uenoku
Subscribers: hiraditya, bollu, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D65731
Modified:
llvm/trunk/include/llvm/Transforms/IPO/Attributor.h
llvm/trunk/lib/Transforms/IPO/Attributor.cpp
Modified: llvm/trunk/include/llvm/Transforms/IPO/Attributor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO/Attributor.h?rev=367961&r1=367960&r2=367961&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/IPO/Attributor.h (original)
+++ llvm/trunk/include/llvm/Transforms/IPO/Attributor.h Mon Aug 5 17:32:43 2019
@@ -266,7 +266,29 @@ struct Attributor {
/// true if \p Pred holds in every call sites. However, this is only possible
/// all call sites are known, hence the function has internal linkage.
bool checkForAllCallSites(Function &F, std::function<bool(CallSite)> &Pred,
- bool RequireAllCallSites, AbstractAttribute &AA);
+ AbstractAttribute &QueryingAA,
+ bool RequireAllCallSites);
+
+ /// Check \p Pred on all instructions with an opcode present in \p Opcodes.
+ ///
+ /// This method will evaluate \p Pred on all instructions with an opcode
+ /// present in \p Opcode and return true if \p Pred holds on all of them.
+ bool checkForAllInstructions(
+ const Function &F, const llvm::function_ref<bool(Instruction &)> &Pred,
+ AbstractAttribute &QueryingAA, InformationCache &InfoCache,
+ const ArrayRef<unsigned> &Opcodes);
+
+ /// Check \p Pred on all call-like instructions (=CallBased derived).
+ ///
+ /// See checkForAllCallLikeInstructions(...) for more information.
+ bool checkForAllCallLikeInstructions(
+ const Function &F, const llvm::function_ref<bool(Instruction &)> &Pred,
+ AbstractAttribute &QueryingAA, InformationCache &InfoCache) {
+ return checkForAllInstructions(F, Pred, QueryingAA, InfoCache,
+ {(unsigned)Instruction::Invoke,
+ (unsigned)Instruction::CallBr,
+ (unsigned)Instruction::Call});
+ }
private:
/// The set of all abstract attributes.
Modified: llvm/trunk/lib/Transforms/IPO/Attributor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Attributor.cpp?rev=367961&r1=367960&r2=367961&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/Attributor.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/Attributor.cpp Mon Aug 5 17:32:43 2019
@@ -422,29 +422,23 @@ ChangeStatus AANoUnwindImpl::updateImpl(
Function &F = getAnchorScope();
// The map from instruction opcodes to those instructions in the function.
- auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
auto Opcodes = {
(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
(unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet,
(unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
- auto *LivenessAA = A.getAAFor<AAIsDead>(*this, F);
-
- for (unsigned Opcode : Opcodes) {
- for (Instruction *I : OpcodeInstMap[Opcode]) {
- // Skip dead instructions.
- if (LivenessAA && LivenessAA->isAssumedDead(I))
- continue;
+ auto CheckForNoUnwind = [&](Instruction &I) {
+ if (!I.mayThrow())
+ return true;
- if (!I->mayThrow())
- continue;
+ auto *NoUnwindAA = A.getAAFor<AANoUnwind>(*this, I);
+ return NoUnwindAA && NoUnwindAA->isAssumedNoUnwind();
+ };
- auto *NoUnwindAA = A.getAAFor<AANoUnwind>(*this, *I);
+ if (!A.checkForAllInstructions(F, CheckForNoUnwind, *this, InfoCache,
+ Opcodes))
+ return indicatePessimisticFixpoint();
- if (!NoUnwindAA || !NoUnwindAA->isAssumedNoUnwind())
- return indicatePessimisticFixpoint();
- }
- }
return ChangeStatus::UNCHANGED;
}
@@ -968,30 +962,18 @@ ChangeStatus AANoSyncImpl::updateImpl(At
return indicatePessimisticFixpoint();
}
- auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
- auto Opcodes = {(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
- (unsigned)Instruction::Call};
-
- for (unsigned Opcode : Opcodes) {
- for (Instruction *I : OpcodeInstMap[Opcode]) {
- // Skip assumed dead instructions.
- if (LivenessAA && LivenessAA->isAssumedDead(I))
- continue;
- // At this point we handled all read/write effects and they are all
- // nosync, so they can be skipped.
- if (I->mayReadOrWriteMemory())
- continue;
-
- ImmutableCallSite ICS(I);
-
- // non-convergent and readnone imply nosync.
- if (!ICS.isConvergent())
- continue;
+ auto CheckForNoSync = [&](Instruction &I) {
+ // At this point we handled all read/write effects and they are all
+ // nosync, so they can be skipped.
+ if (I.mayReadOrWriteMemory())
+ return true;
- return indicatePessimisticFixpoint();
- }
- }
+ // non-convergent and readnone imply nosync.
+ return !ImmutableCallSite(&I).isConvergent();
+ };
+ if (!A.checkForAllCallLikeInstructions(F, CheckForNoSync, *this, InfoCache))
+ return indicatePessimisticFixpoint();
return ChangeStatus::UNCHANGED;
}
@@ -1029,26 +1011,16 @@ ChangeStatus AANoFreeImpl::updateImpl(At
InformationCache &InfoCache) {
Function &F = getAnchorScope();
- auto *LivenessAA = A.getAAFor<AAIsDead>(*this, F);
-
- // The map from instruction opcodes to those instructions in the function.
- auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
+ auto CheckForNoFree = [&](Instruction &I) {
+ if (ImmutableCallSite(&I).hasFnAttr(Attribute::NoFree))
+ return true;
- for (unsigned Opcode :
- {(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
- (unsigned)Instruction::Call}) {
- for (Instruction *I : OpcodeInstMap[Opcode]) {
- // Skip assumed dead instructions.
- if (LivenessAA && LivenessAA->isAssumedDead(I))
- continue;
- auto ICS = ImmutableCallSite(I);
- auto *NoFreeAA = A.getAAFor<AANoFreeImpl>(*this, *I);
+ auto *NoFreeAA = A.getAAFor<AANoFreeImpl>(*this, I);
+ return NoFreeAA && NoFreeAA->isAssumedNoFree();
+ };
- if ((!NoFreeAA || !NoFreeAA->isAssumedNoFree()) &&
- !ICS.hasFnAttr(Attribute::NoFree))
- return indicatePessimisticFixpoint();
- }
- }
+ if (!A.checkForAllCallLikeInstructions(F, CheckForNoFree, *this, InfoCache))
+ return indicatePessimisticFixpoint();
return ChangeStatus::UNCHANGED;
}
@@ -1215,7 +1187,7 @@ ChangeStatus AANonNullArgument::updateIm
return false;
};
- if (!A.checkForAllCallSites(F, CallSiteCheck, true, *this))
+ if (!A.checkForAllCallSites(F, CallSiteCheck, *this, true))
return indicatePessimisticFixpoint();
return ChangeStatus::UNCHANGED;
}
@@ -1303,41 +1275,29 @@ void AAWillReturnFunction::initialize(At
ChangeStatus AAWillReturnFunction::updateImpl(Attributor &A,
InformationCache &InfoCache) {
- Function &F = getAnchorScope();
-
+ const Function &F = getAnchorScope();
// The map from instruction opcodes to those instructions in the function.
- auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
- auto *LivenessAA = A.getAAFor<AAIsDead>(*this, F);
+ auto CheckForWillReturn = [&](Instruction &I) {
+ ImmutableCallSite ICS(&I);
+ if (ICS.hasFnAttr(Attribute::WillReturn))
+ return true;
- for (unsigned Opcode :
- {(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
- (unsigned)Instruction::Call}) {
- for (Instruction *I : OpcodeInstMap[Opcode]) {
- // Skip assumed dead instructions.
- if (LivenessAA && LivenessAA->isAssumedDead(I))
- continue;
+ auto *WillReturnAA = A.getAAFor<AAWillReturn>(*this, I);
+ if (!WillReturnAA || !WillReturnAA->isAssumedWillReturn())
+ return false;
- auto ICS = ImmutableCallSite(I);
+ // FIXME: Prohibit any recursion for now.
+ if (ICS.hasFnAttr(Attribute::NoRecurse))
+ return true;
- if (ICS.hasFnAttr(Attribute::WillReturn))
- continue;
+ auto *NoRecurseAA = A.getAAFor<AANoRecurse>(*this, I);
+ return NoRecurseAA && NoRecurseAA->isAssumedNoRecurse();
+ };
- auto *WillReturnAA = A.getAAFor<AAWillReturn>(*this, *I);
- if (!WillReturnAA || !WillReturnAA->isAssumedWillReturn())
- return indicatePessimisticFixpoint();
-
- auto *NoRecurseAA = A.getAAFor<AANoRecurse>(*this, *I);
-
- // FIXME: (i) Prohibit any recursion for now.
- // (ii) AANoRecurse isn't implemented yet so currently any call is
- // regarded as having recursion.
- // Code below should be
- // if ((!NoRecurseAA || !NoRecurseAA->isAssumedNoRecurse()) &&
- if (!NoRecurseAA && !ICS.hasFnAttr(Attribute::NoRecurse))
- return indicatePessimisticFixpoint();
- }
- }
+ if (!A.checkForAllCallLikeInstructions(F, CheckForWillReturn, *this,
+ InfoCache))
+ return indicatePessimisticFixpoint();
return ChangeStatus::UNCHANGED;
}
@@ -1969,7 +1929,7 @@ AADereferenceableArgument::updateImpl(At
return isValidState();
};
- if (!A.checkForAllCallSites(F, CallSiteCheck, true, *this))
+ if (!A.checkForAllCallSites(F, CallSiteCheck, *this, true))
return indicatePessimisticFixpoint();
updateAssumedNonNullGlobalState(IsNonNull, IsGlobal);
@@ -2155,7 +2115,7 @@ ChangeStatus AAAlignArgument::updateImpl
return isValidState();
};
- if (!A.checkForAllCallSites(F, CallSiteCheck, true, *this))
+ if (!A.checkForAllCallSites(F, CallSiteCheck, *this, true))
indicatePessimisticFixpoint();
return BeforeState == getAssumed() ? ChangeStatus::UNCHANGED
@@ -2230,21 +2190,11 @@ struct AANoReturnImpl : public AANoRetur
/// See AbstractAttribute::updateImpl(Attributor &A).
virtual ChangeStatus updateImpl(Attributor &A,
InformationCache &InfoCache) override {
- Function &F = getAnchorScope();
-
- // The map from instruction opcodes to those instructions in the function.
- auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
-
- // Look at all return instructions.
- auto &ReturnInsts = OpcodeInstMap[Instruction::Ret];
- if (ReturnInsts.empty())
- return indicateOptimisticFixpoint();
-
- auto *LivenessAA = A.getAAFor<AAIsDead>(*this, F);
- if (!LivenessAA ||
- LivenessAA->isLiveInstSet(ReturnInsts.begin(), ReturnInsts.end()))
+ const Function &F = getAnchorScope();
+ auto CheckForNoReturn = [](Instruction &) { return false; };
+ if (!A.checkForAllInstructions(F, CheckForNoReturn, *this, InfoCache,
+ {(unsigned)Instruction::Ret}))
return indicatePessimisticFixpoint();
-
return ChangeStatus::UNCHANGED;
}
};
@@ -2259,8 +2209,8 @@ struct AANoReturnFunction final : AANoRe
bool Attributor::checkForAllCallSites(Function &F,
std::function<bool(CallSite)> &Pred,
- bool RequireAllCallSites,
- AbstractAttribute &AA) {
+ AbstractAttribute &QueryingAA,
+ bool RequireAllCallSites) {
// We can try to determine information from
// the call sites. However, this is only possible all call sites are known,
// hence the function has internal linkage.
@@ -2276,7 +2226,7 @@ bool Attributor::checkForAllCallSites(Fu
Instruction *I = cast<Instruction>(U.getUser());
Function *AnchorValue = I->getParent()->getParent();
- auto *LivenessAA = getAAFor<AAIsDead>(AA, *AnchorValue);
+ auto *LivenessAA = getAAFor<AAIsDead>(QueryingAA, *AnchorValue);
// Skip dead calls.
if (LivenessAA && LivenessAA->isAssumedDead(I))
@@ -2301,6 +2251,28 @@ bool Attributor::checkForAllCallSites(Fu
}
return true;
+}
+
+bool Attributor::checkForAllInstructions(
+ const Function &F, const llvm::function_ref<bool(Instruction &)> &Pred,
+ AbstractAttribute &QueryingAA, InformationCache &InfoCache,
+ const ArrayRef<unsigned> &Opcodes) {
+
+ auto *LivenessAA = getAAFor<AAIsDead>(QueryingAA, F);
+
+ auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
+ for (unsigned Opcode : Opcodes) {
+ for (Instruction *I : OpcodeInstMap[Opcode]) {
+ // Skip dead instructions.
+ if (LivenessAA && LivenessAA->isAssumedDead(I))
+ continue;
+
+ if (!Pred(*I))
+ return false;
+ }
+ }
+
+ return true;
}
ChangeStatus Attributor::run(InformationCache &InfoCache) {
More information about the llvm-commits
mailing list