summaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ScalarEvolution.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis/ScalarEvolution.cpp')
-rw-r--r--llvm/lib/Analysis/ScalarEvolution.cpp41
1 files changed, 34 insertions, 7 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 02972c75ca48..556472f54426 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -3897,17 +3897,44 @@ ScalarEvolution::getSequentialMinMaxExpr(SCEVTypes Kind,
{
SmallPtrSet<const SCEV *, 16> SeenOps;
unsigned Idx = 0;
- bool DeletedAny = false;
+ bool Changed = false;
while (Idx < Ops.size()) {
- if (SeenOps.insert(Ops[Idx]).second) {
- ++Idx;
- continue;
+ // Has the whole operand been seen already?
+ if (!SeenOps.insert(Ops[Idx]).second) {
+ Ops.erase(Ops.begin() + Idx);
+ Changed = true;
+ continue; // Look at operand under this index again.
}
- Ops.erase(Ops.begin() + Idx);
- DeletedAny = true;
+
+ // Look into non-sequential same-typed min/max expressions,
+ // drop any of it's operands that we have already seen.
+ // FIXME: once there are other sequential min/max types, generalize.
+ if (const auto *CommUMinExpr = dyn_cast<SCEVUMinExpr>(Ops[Idx])) {
+ SmallVector<const SCEV *> InnerOps;
+ InnerOps.reserve(CommUMinExpr->getNumOperands());
+ for (const SCEV *InnerOp : CommUMinExpr->operands()) {
+ if (SeenOps.insert(InnerOp).second) // Operand not seen before?
+ InnerOps.emplace_back(InnerOp); // Keep this inner operand.
+ }
+ // Were any operands of this 'umin' themselves redundant?
+ if (InnerOps.size() != CommUMinExpr->getNumOperands()) {
+ Changed = true;
+ // Was the whole operand effectively redundant? Note that it can
+ // happen even when the operand itself wasn't redundant as a whole.
+ if (InnerOps.empty()) {
+ Ops.erase(Ops.begin() + Idx);
+ continue; // Look at operand under this index again.
+ }
+ // Recreate our operand.
+ Ops[Idx] = getMinMaxExpr(Ops[Idx]->getSCEVType(), InnerOps);
+ }
+ }
+
+ // Ok, can't do anything else about this operand, move onto the next one.
+ ++Idx;
}
- if (DeletedAny)
+ if (Changed)
return getSequentialMinMaxExpr(Kind, Ops);
}