summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorJohannes Doerfert <jdoerfert@anl.gov>2019-08-06 00:32:43 +0000
committerJohannes Doerfert <jdoerfert@anl.gov>2019-08-06 00:32:43 +0000
commitd0f6400978347cb8169a2bd853c4afb0135511e4 (patch)
tree977a74970fb3264fd82455be9f2c0fd4bc0e8600 /llvm/lib
parentb12056bd3390d8fd32782f5e3fee1fd16c136def (diff)
downloadbcm5719-llvm-d0f6400978347cb8169a2bd853c4afb0135511e4.tar.gz
bcm5719-llvm-d0f6400978347cb8169a2bd853c4afb0135511e4.zip
[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 llvm-svn: 367961
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Transforms/IPO/Attributor.cpp180
1 files changed, 76 insertions, 104 deletions
diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp
index 6cbe47c184e..3656d77414c 100644
--- a/llvm/lib/Transforms/IPO/Attributor.cpp
+++ b/llvm/lib/Transforms/IPO/Attributor.cpp
@@ -422,29 +422,23 @@ ChangeStatus AANoUnwindImpl::updateImpl(Attributor &A,
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(Attributor &A,
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(Attributor &A,
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::updateImpl(Attributor &A,
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(Attributor &A,
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);
- 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 CheckForWillReturn = [&](Instruction &I) {
+ ImmutableCallSite ICS(&I);
+ if (ICS.hasFnAttr(Attribute::WillReturn))
+ return true;
- if (ICS.hasFnAttr(Attribute::WillReturn))
- continue;
+ auto *WillReturnAA = A.getAAFor<AAWillReturn>(*this, I);
+ if (!WillReturnAA || !WillReturnAA->isAssumedWillReturn())
+ return false;
- auto *WillReturnAA = A.getAAFor<AAWillReturn>(*this, *I);
- if (!WillReturnAA || !WillReturnAA->isAssumedWillReturn())
- return indicatePessimisticFixpoint();
+ // FIXME: Prohibit any recursion for now.
+ if (ICS.hasFnAttr(Attribute::NoRecurse))
+ return true;
- auto *NoRecurseAA = A.getAAFor<AANoRecurse>(*this, *I);
+ auto *NoRecurseAA = A.getAAFor<AANoRecurse>(*this, I);
+ return NoRecurseAA && NoRecurseAA->isAssumedNoRecurse();
+ };
- // 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(Attributor &A,
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(Attributor &A,
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 AANoReturn, BooleanState {
/// 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 : AANoReturnImpl {
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(Function &F,
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))
@@ -2303,6 +2253,28 @@ bool Attributor::checkForAllCallSites(Function &F,
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) {
// Initialize all abstract attributes.
for (AbstractAttribute *AA : AllAbstractAttributes)
OpenPOWER on IntegriCloud