mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-19 01:46:49 +00:00
[SCEV] Move canReuseInstruction() helper into SCEV (NFC)
To allow reusing it in IndVars. (cherry picked from commit 43dd1e84df1ecdad872e1004af47b489e08fc228)
This commit is contained in:
parent
4223b2264c
commit
dc0ed54ac5
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user