[llvm] [LV] Vectorize selecting last IV of min/max element. (PR #141431)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 18 05:54:01 PST 2025
================
@@ -965,3 +965,101 @@ bool VPlanTransforms::handleMaxMinNumReductions(VPlan &Plan) {
MiddleTerm->setOperand(0, NewCond);
return true;
}
+
+bool VPlanTransforms::legalizeMultiUseReductions(VPlan &Plan) {
+ for (auto &PhiR : make_early_inc_range(
+ Plan.getVectorLoopRegion()->getEntryBasicBlock()->phis())) {
+ auto *MinMaxPhiR = dyn_cast<VPReductionPHIRecipe>(&PhiR);
+ if (!MinMaxPhiR)
+ continue;
+
+ RecurKind RdxKind = MinMaxPhiR->getRecurrenceKind();
+ // TODO: check for multi-uses in VPlan directly.
+ if (!RecurrenceDescriptor::isIntMinMaxRecurrenceKind(RdxKind) ||
+ !MinMaxPhiR->isPhiMultiUse())
+ continue;
+
+ // One user of MinMaxPhiR is MinMaxOp, the other users must be a compare
+ // that's part of a FindLastIV chain.
+ auto *MinMaxOp =
+ dyn_cast<VPRecipeWithIRFlags>(MinMaxPhiR->getBackedgeValue());
+ if (!MinMaxOp || MinMaxOp->getNumUsers() != 2)
+ return false;
+ auto MinMaxUsers = to_vector(MinMaxPhiR->users());
+ auto *Cmp = dyn_cast<VPRecipeWithIRFlags>(
+ MinMaxUsers[0] == MinMaxOp ? MinMaxUsers[1] : MinMaxUsers[0]);
+ VPValue *CmpOpA;
+ VPValue *CmpOpB;
+ if (!Cmp || Cmp->getNumUsers() != 1 ||
+ !match(Cmp, m_Binary<Instruction::ICmp>(m_VPValue(CmpOpA),
+ m_VPValue(CmpOpB))))
+ return false;
+
+ // Normalize the predicate so MinMaxPhiR is on the right side.
+ CmpInst::Predicate Pred = Cmp->getPredicate();
+ if (CmpOpA == MinMaxPhiR)
+ Pred = CmpInst::getSwappedPredicate(Pred);
+
+ // Determine if the predicate is not strict.
+ bool IsNonStrictPred = ICmpInst::isLE(Pred) || ICmpInst::isGE(Pred);
+ // Account for a mis-match between RdxKind and the predicate.
+ switch (RdxKind) {
+ case RecurKind::UMin:
+ case RecurKind::SMin:
+ IsNonStrictPred |= ICmpInst::isGT(Pred);
+ break;
+ case RecurKind::UMax:
+ case RecurKind::SMax:
+ IsNonStrictPred |= ICmpInst::isLT(Pred);
+ break;
+ default:
+ llvm_unreachable("unsupported kind");
+ }
+
+ // TODO: Strict predicates need to find the first IV value for which the
+ // predicate holds, not the last.
+ if (Pred == CmpInst::ICMP_NE || !IsNonStrictPred)
+ return false;
+
+ // Cmp must be used by the select of a FindLastIV chain.
+ VPValue *Sel = dyn_cast<VPSingleDefRecipe>(*Cmp->user_begin());
+ VPValue *IVOp, *FindIV;
+ if (!Sel ||
+ !match(Sel,
+ m_Select(m_Specific(Cmp), m_VPValue(IVOp), m_VPValue(FindIV))) ||
+ Sel->getNumUsers() != 2 || !isa<VPWidenIntOrFpInductionRecipe>(IVOp))
+ return false;
----------------
ayalz wrote:
```suggestion
return false;
```
https://github.com/llvm/llvm-project/pull/141431
More information about the llvm-commits
mailing list