diff options
author | Nikita Popov <npopov@redhat.com> | 2024-02-02 16:02:46 +0100 |
---|---|---|
committer | Nikita Popov <npopov@redhat.com> | 2024-02-02 16:48:00 +0100 |
commit | 43dd1e84df1ecdad872e1004af47b489e08fc228 (patch) | |
tree | f539465949714b2dc6dec93860eb1ec5d9553e32 /llvm/lib/Analysis/ScalarEvolution.cpp | |
parent | 46b6756255029f442165148115bad99d04057622 (diff) | |
download | llvm-43dd1e84df1ecdad872e1004af47b489e08fc228.zip llvm-43dd1e84df1ecdad872e1004af47b489e08fc228.tar.gz llvm-43dd1e84df1ecdad872e1004af47b489e08fc228.tar.bz2 |
[SCEV] Move canReuseInstruction() helper into SCEV (NFC)
To allow reusing it in IndVars.
Diffstat (limited to 'llvm/lib/Analysis/ScalarEvolution.cpp')
-rw-r--r-- | llvm/lib/Analysis/ScalarEvolution.cpp | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 2acb458..4b2db80 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -4184,6 +4184,68 @@ void ScalarEvolution::getPoisonGeneratingValues( Result.insert(SU->getValue()); } +bool ScalarEvolution::canReuseInstruction( + const SCEV *S, Instruction *I, + SmallVectorImpl<Instruction *> &DropPoisonGeneratingInsts) { + // If the instruction cannot be poison, it's always safe to reuse. + if (programUndefinedIfPoison(I)) + return true; + + // Otherwise, it is possible that I is more poisonous that S. Collect the + // poison-contributors of S, and then check whether I has any additional + // poison-contributors. Poison that is contributed through poison-generating + // flags is handled by dropping those flags instead. + SmallPtrSet<const Value *, 8> PoisonVals; + getPoisonGeneratingValues(PoisonVals, S); + + SmallVector<Value *> Worklist; + SmallPtrSet<Value *, 8> Visited; + Worklist.push_back(I); + while (!Worklist.empty()) { + Value *V = Worklist.pop_back_val(); + if (!Visited.insert(V).second) + continue; + + // Avoid walking large instruction graphs. + if (Visited.size() > 16) + return false; + + // Either the value can't be poison, or the S would also be poison if it + // is. + if (PoisonVals.contains(V) || isGuaranteedNotToBePoison(V)) + continue; + + auto *I = dyn_cast<Instruction>(V); + if (!I) + return false; + + // Disjoint or instructions are interpreted as adds by SCEV. However, we + // can't replace an arbitrary add with disjoint or, even if we drop the + // flag. We would need to convert the or into an add. + if (auto *PDI = dyn_cast<PossiblyDisjointInst>(I)) + if (PDI->isDisjoint()) + return false; + + // FIXME: Ignore vscale, even though it technically could be poison. Do this + // because SCEV currently assumes it can't be poison. Remove this special + // case once we proper model when vscale can be poison. + if (auto *II = dyn_cast<IntrinsicInst>(I); + II && II->getIntrinsicID() == Intrinsic::vscale) + continue; + + if (canCreatePoison(cast<Operator>(I), /*ConsiderFlagsAndMetadata*/ false)) + return false; + + // If the instruction can't create poison, we can recurse to its operands. + if (I->hasPoisonGeneratingFlagsOrMetadata()) + DropPoisonGeneratingInsts.push_back(I); + + for (Value *Op : I->operands()) + Worklist.push_back(Op); + } + return true; +} + const SCEV * ScalarEvolution::getSequentialMinMaxExpr(SCEVTypes Kind, SmallVectorImpl<const SCEV *> &Ops) { |