[llvm] [LV] Vectorize selecting last IV of min/max element. (PR #141431)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Nov 23 12:58:48 PST 2025
================
@@ -992,3 +996,98 @@ bool VPlanTransforms::handleMaxMinNumReductions(VPlan &Plan) {
MiddleTerm->setOperand(0, NewCond);
return true;
}
+
+bool VPlanTransforms::handleMultiUseReductions(VPlan &Plan) {
+ for (auto &PhiR : make_early_inc_range(
+ Plan.getVectorLoopRegion()->getEntryBasicBlock()->phis())) {
+ auto *MinMaxPhiR = dyn_cast<VPReductionPHIRecipe>(&PhiR);
+ // TODO: check for multi-uses in VPlan directly.
+ if (!MinMaxPhiR || !MinMaxPhiR->hasLoopUsesOutsideReductionChain())
+ continue;
+
+ RecurKind RdxKind = MinMaxPhiR->getRecurrenceKind();
+ assert(
+ RecurrenceDescriptor::isIntMinMaxRecurrenceKind(RdxKind) &&
+ "only min/max recurrences support users outside the reduction chain");
+
+ // One user of MinMaxPhiR is MinMaxOp, the other user 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;
+
+ assert((isa<VPWidenIntrinsicRecipe>(MinMaxOp) ||
+ (isa<VPReplicateRecipe>(MinMaxOp) &&
+ isa<IntrinsicInst>(
+ cast<VPReplicateRecipe>(MinMaxOp)->getUnderlyingValue()))) &&
+ "MinMaxOp must be a wide or scalar intrinsic");
+ VPValue *MinMaxOpA = MinMaxOp->getOperand(0);
+ VPValue *MinMaxOpB = MinMaxOp->getOperand(1);
+ if (MinMaxOpA != MinMaxPhiR)
+ std::swap(MinMaxOpA, MinMaxOpB);
+ if (MinMaxOpA != MinMaxPhiR)
+ return false;
+
+ VPValue *CmpOpA;
+ VPValue *CmpOpB;
+ CmpPredicate Pred;
+ auto *Cmp = dyn_cast_or_null<VPRecipeWithIRFlags>(findUserOf(
+ MinMaxPhiR, m_Cmp(Pred, m_VPValue(CmpOpA), m_VPValue(CmpOpB))));
+ if (!Cmp || Cmp->getNumUsers() != 1 ||
+ (CmpOpA != MinMaxOpB && CmpOpB != MinMaxOpB))
+ return false;
+
+ // TODO: Strict predicates need to find the first IV value for which the
+ // predicate holds, not the last.
+ if (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE ||
+ ICmpInst::isLT(Pred) || ICmpInst::isGT(Pred))
+ return false;
+
+ // Normalize the predicate so MinMaxPhiR is on the right side.
+ if (CmpOpA == MinMaxPhiR)
+ Pred = CmpInst::getSwappedPredicate(Pred);
----------------
ayalz wrote:
Is it important to normalize so MinMaxPhiR is on the right - `Pred` appears to be unused?
https://github.com/llvm/llvm-project/pull/141431
More information about the llvm-commits
mailing list