Skip to content

Commit 43dd1e8

Browse files
committed
[SCEV] Move canReuseInstruction() helper into SCEV (NFC)
To allow reusing it in IndVars.
1 parent 46b6756 commit 43dd1e8

File tree

3 files changed

+70
-63
lines changed

3 files changed

+70
-63
lines changed

llvm/include/llvm/Analysis/ScalarEvolution.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,13 @@ class ScalarEvolution {
13141314
void getPoisonGeneratingValues(SmallPtrSetImpl<const Value *> &Result,
13151315
const SCEV *S);
13161316

1317+
/// Check whether it is poison-safe to represent the expression S using the
1318+
/// instruction I. If such a replacement is performed, the poison flags of
1319+
/// instructions in DropPoisonGeneratingInsts must be dropped.
1320+
bool canReuseInstruction(
1321+
const SCEV *S, Instruction *I,
1322+
SmallVectorImpl<Instruction *> &DropPoisonGeneratingInsts);
1323+
13171324
class FoldID {
13181325
const SCEV *Op = nullptr;
13191326
const Type *Ty = nullptr;

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4184,6 +4184,68 @@ void ScalarEvolution::getPoisonGeneratingValues(
41844184
Result.insert(SU->getValue());
41854185
}
41864186

4187+
bool ScalarEvolution::canReuseInstruction(
4188+
const SCEV *S, Instruction *I,
4189+
SmallVectorImpl<Instruction *> &DropPoisonGeneratingInsts) {
4190+
// If the instruction cannot be poison, it's always safe to reuse.
4191+
if (programUndefinedIfPoison(I))
4192+
return true;
4193+
4194+
// Otherwise, it is possible that I is more poisonous that S. Collect the
4195+
// poison-contributors of S, and then check whether I has any additional
4196+
// poison-contributors. Poison that is contributed through poison-generating
4197+
// flags is handled by dropping those flags instead.
4198+
SmallPtrSet<const Value *, 8> PoisonVals;
4199+
getPoisonGeneratingValues(PoisonVals, S);
4200+
4201+
SmallVector<Value *> Worklist;
4202+
SmallPtrSet<Value *, 8> Visited;
4203+
Worklist.push_back(I);
4204+
while (!Worklist.empty()) {
4205+
Value *V = Worklist.pop_back_val();
4206+
if (!Visited.insert(V).second)
4207+
continue;
4208+
4209+
// Avoid walking large instruction graphs.
4210+
if (Visited.size() > 16)
4211+
return false;
4212+
4213+
// Either the value can't be poison, or the S would also be poison if it
4214+
// is.
4215+
if (PoisonVals.contains(V) || isGuaranteedNotToBePoison(V))
4216+
continue;
4217+
4218+
auto *I = dyn_cast<Instruction>(V);
4219+
if (!I)
4220+
return false;
4221+
4222+
// Disjoint or instructions are interpreted as adds by SCEV. However, we
4223+
// can't replace an arbitrary add with disjoint or, even if we drop the
4224+
// flag. We would need to convert the or into an add.
4225+
if (auto *PDI = dyn_cast<PossiblyDisjointInst>(I))
4226+
if (PDI->isDisjoint())
4227+
return false;
4228+
4229+
// FIXME: Ignore vscale, even though it technically could be poison. Do this
4230+
// because SCEV currently assumes it can't be poison. Remove this special
4231+
// case once we proper model when vscale can be poison.
4232+
if (auto *II = dyn_cast<IntrinsicInst>(I);
4233+
II && II->getIntrinsicID() == Intrinsic::vscale)
4234+
continue;
4235+
4236+
if (canCreatePoison(cast<Operator>(I), /*ConsiderFlagsAndMetadata*/ false))
4237+
return false;
4238+
4239+
// If the instruction can't create poison, we can recurse to its operands.
4240+
if (I->hasPoisonGeneratingFlagsOrMetadata())
4241+
DropPoisonGeneratingInsts.push_back(I);
4242+
4243+
for (Value *Op : I->operands())
4244+
Worklist.push_back(Op);
4245+
}
4246+
return true;
4247+
}
4248+
41874249
const SCEV *
41884250
ScalarEvolution::getSequentialMinMaxExpr(SCEVTypes Kind,
41894251
SmallVectorImpl<const SCEV *> &Ops) {

llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp

Lines changed: 1 addition & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,68 +1363,6 @@ Value *SCEVExpander::expandCodeFor(const SCEV *SH, Type *Ty) {
13631363
return V;
13641364
}
13651365

1366-
static bool
1367-
canReuseInstruction(ScalarEvolution &SE, const SCEV *S, Instruction *I,
1368-
SmallVectorImpl<Instruction *> &DropPoisonGeneratingInsts) {
1369-
// If the instruction cannot be poison, it's always safe to reuse.
1370-
if (programUndefinedIfPoison(I))
1371-
return true;
1372-
1373-
// Otherwise, it is possible that I is more poisonous that S. Collect the
1374-
// poison-contributors of S, and then check whether I has any additional
1375-
// poison-contributors. Poison that is contributed through poison-generating
1376-
// flags is handled by dropping those flags instead.
1377-
SmallPtrSet<const Value *, 8> PoisonVals;
1378-
SE.getPoisonGeneratingValues(PoisonVals, S);
1379-
1380-
SmallVector<Value *> Worklist;
1381-
SmallPtrSet<Value *, 8> Visited;
1382-
Worklist.push_back(I);
1383-
while (!Worklist.empty()) {
1384-
Value *V = Worklist.pop_back_val();
1385-
if (!Visited.insert(V).second)
1386-
continue;
1387-
1388-
// Avoid walking large instruction graphs.
1389-
if (Visited.size() > 16)
1390-
return false;
1391-
1392-
// Either the value can't be poison, or the S would also be poison if it
1393-
// is.
1394-
if (PoisonVals.contains(V) || isGuaranteedNotToBePoison(V))
1395-
continue;
1396-
1397-
auto *I = dyn_cast<Instruction>(V);
1398-
if (!I)
1399-
return false;
1400-
1401-
// Disjoint or instructions are interpreted as adds by SCEV. However, we
1402-
// can't replace an arbitrary add with disjoint or, even if we drop the
1403-
// flag. We would need to convert the or into an add.
1404-
if (auto *PDI = dyn_cast<PossiblyDisjointInst>(I))
1405-
if (PDI->isDisjoint())
1406-
return false;
1407-
1408-
// FIXME: Ignore vscale, even though it technically could be poison. Do this
1409-
// because SCEV currently assumes it can't be poison. Remove this special
1410-
// case once we proper model when vscale can be poison.
1411-
if (auto *II = dyn_cast<IntrinsicInst>(I);
1412-
II && II->getIntrinsicID() == Intrinsic::vscale)
1413-
continue;
1414-
1415-
if (canCreatePoison(cast<Operator>(I), /*ConsiderFlagsAndMetadata*/ false))
1416-
return false;
1417-
1418-
// If the instruction can't create poison, we can recurse to its operands.
1419-
if (I->hasPoisonGeneratingFlagsOrMetadata())
1420-
DropPoisonGeneratingInsts.push_back(I);
1421-
1422-
for (Value *Op : I->operands())
1423-
Worklist.push_back(Op);
1424-
}
1425-
return true;
1426-
}
1427-
14281366
Value *SCEVExpander::FindValueInExprValueMap(
14291367
const SCEV *S, const Instruction *InsertPt,
14301368
SmallVectorImpl<Instruction *> &DropPoisonGeneratingInsts) {
@@ -1452,7 +1390,7 @@ Value *SCEVExpander::FindValueInExprValueMap(
14521390
continue;
14531391

14541392
// Make sure reusing the instruction is poison-safe.
1455-
if (canReuseInstruction(SE, S, EntInst, DropPoisonGeneratingInsts))
1393+
if (SE.canReuseInstruction(S, EntInst, DropPoisonGeneratingInsts))
14561394
return V;
14571395
DropPoisonGeneratingInsts.clear();
14581396
}

0 commit comments

Comments
 (0)