aboutsummaryrefslogtreecommitdiff
path: root/llvm
diff options
context:
space:
mode:
authorNikita Popov <npopov@redhat.com>2024-02-02 16:02:46 +0100
committerTom Stellard <tstellar@redhat.com>2024-02-20 16:44:46 -0800
commitdc0ed54ac582357c8e097b2610791b7f802bb0ad (patch)
treeda459d5bbc2b7def2f7a5c5c9233f7dfebc4f2d6 /llvm
parent4223b2264ce5e6d1855b9e7b32fe61152a681046 (diff)
downloadllvm-dc0ed54ac582357c8e097b2610791b7f802bb0ad.zip
llvm-dc0ed54ac582357c8e097b2610791b7f802bb0ad.tar.gz
llvm-dc0ed54ac582357c8e097b2610791b7f802bb0ad.tar.bz2
[SCEV] Move canReuseInstruction() helper into SCEV (NFC)
To allow reusing it in IndVars. (cherry picked from commit 43dd1e84df1ecdad872e1004af47b489e08fc228)
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/Analysis/ScalarEvolution.h7
-rw-r--r--llvm/lib/Analysis/ScalarEvolution.cpp62
-rw-r--r--llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp64
3 files changed, 70 insertions, 63 deletions
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index af3ad82..0880f9c 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -1314,6 +1314,13 @@ public:
void getPoisonGeneratingValues(SmallPtrSetImpl<const Value *> &Result,
const SCEV *S);
+ /// Check whether it is poison-safe to represent the expression S using the
+ /// instruction I. If such a replacement is performed, the poison flags of
+ /// instructions in DropPoisonGeneratingInsts must be dropped.
+ bool canReuseInstruction(
+ const SCEV *S, Instruction *I,
+ SmallVectorImpl<Instruction *> &DropPoisonGeneratingInsts);
+
class FoldID {
const SCEV *Op = nullptr;
const Type *Ty = nullptr;
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) {
diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
index e6f93e7..a3951fd 100644
--- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -1366,68 +1366,6 @@ Value *SCEVExpander::expandCodeFor(const SCEV *SH, Type *Ty) {
return V;
}
-static bool
-canReuseInstruction(ScalarEvolution &SE, 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;
- SE.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;
-}
-
Value *SCEVExpander::FindValueInExprValueMap(
const SCEV *S, const Instruction *InsertPt,
SmallVectorImpl<Instruction *> &DropPoisonGeneratingInsts) {
@@ -1455,7 +1393,7 @@ Value *SCEVExpander::FindValueInExprValueMap(
continue;
// Make sure reusing the instruction is poison-safe.
- if (canReuseInstruction(SE, S, EntInst, DropPoisonGeneratingInsts))
+ if (SE.canReuseInstruction(S, EntInst, DropPoisonGeneratingInsts))
return V;
DropPoisonGeneratingInsts.clear();
}