[llvm] 43dd1e8 - [SCEV] Move canReuseInstruction() helper into SCEV (NFC)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 2 07:48:08 PST 2024
Author: Nikita Popov
Date: 2024-02-02T16:48:00+01:00
New Revision: 43dd1e84df1ecdad872e1004af47b489e08fc228
URL: https://github.com/llvm/llvm-project/commit/43dd1e84df1ecdad872e1004af47b489e08fc228
DIFF: https://github.com/llvm/llvm-project/commit/43dd1e84df1ecdad872e1004af47b489e08fc228.diff
LOG: [SCEV] Move canReuseInstruction() helper into SCEV (NFC)
To allow reusing it in IndVars.
Added:
Modified:
llvm/include/llvm/Analysis/ScalarEvolution.h
llvm/lib/Analysis/ScalarEvolution.cpp
llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index af3ad822e0b0d..0880f9c65aa45 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -1314,6 +1314,13 @@ class ScalarEvolution {
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 2acb45837c480..4b2db80bc1ec3 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 34597e6b6e83a..58dbac0e85fb0 100644
--- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -1363,68 +1363,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) {
@@ -1452,7 +1390,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();
}
More information about the llvm-commits
mailing list