diff options
| author | Johannes Doerfert <jdoerfert@anl.gov> | 2019-08-06 00:32:43 +0000 |
|---|---|---|
| committer | Johannes Doerfert <jdoerfert@anl.gov> | 2019-08-06 00:32:43 +0000 |
| commit | d0f6400978347cb8169a2bd853c4afb0135511e4 (patch) | |
| tree | 977a74970fb3264fd82455be9f2c0fd4bc0e8600 /llvm/lib | |
| parent | b12056bd3390d8fd32782f5e3fee1fd16c136def (diff) | |
| download | bcm5719-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.cpp | 180 |
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) |

