[llvm] [LV] Support argmin/argmax with strict predicates. (PR #170223)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Sat Jan 24 13:58:11 PST 2026
================
@@ -1390,7 +1392,136 @@ bool VPlanTransforms::handleFindLastReductions(VPlan &Plan) {
return true;
}
-bool VPlanTransforms::handleMultiUseReductions(VPlan &Plan) {
+/// For argmin/argmax reductions with strict predicates, convert the existing
+/// FindLastIV reduction to a new UMin reduction of a wide canonical IV. If the
+/// original IV was not canonical, a new canonical wide IV is added, and the
+/// final result is scaled back to the original IV.
+static bool handleFirstArgMinOrMax(VPlan &Plan,
+ VPReductionPHIRecipe *MinOrMaxPhiR,
+ VPReductionPHIRecipe *FindLastIVPhiR,
+ VPWidenIntOrFpInductionRecipe *WideIV,
+ VPInstruction *MinOrMaxResult) {
+ Type *Ty = Plan.getVectorLoopRegion()->getCanonicalIVType();
+ // TODO: Support non (i.e., narrower than) canonical IV types.
+ if (Ty != VPTypeAnalysis(Plan).inferScalarType(WideIV))
+ return false;
+
+ // If the original wide IV is not canonical, create a new one. The wide IV is
+ // guaranteed to not wrap for all lanes that are active in the vector loop.
+ auto *FindIVSelectR = cast<VPSingleDefRecipe>(
+ FindLastIVPhiR->getBackedgeValue()->getDefiningRecipe());
+ if (!WideIV->isCanonical()) {
+ VPIRValue *Zero = Plan.getConstantInt(Ty, 0);
+ VPIRValue *One = Plan.getConstantInt(Ty, 1);
+ auto *WidenCanIV = new VPWidenIntOrFpInductionRecipe(
+ nullptr, Zero, One, WideIV->getVFValue(),
+ WideIV->getInductionDescriptor(),
+ VPIRFlags::WrapFlagsTy(/*HasNUW=*/true, /*HasNSW=*/false),
+ WideIV->getDebugLoc());
+ WidenCanIV->insertBefore(WideIV);
+
+ // Update the select to use the wide canonical IV.
+ assert(
+ match(FindIVSelectR, m_Select(m_VPValue(), m_VPValue(), m_VPValue())) &&
+ "backedge value must be a select");
+ WideIV->replaceUsesWithIf(WidenCanIV,
+ [FindIVSelectR](const VPUser &U, unsigned) {
+ return FindIVSelectR == &U;
+ });
+ }
+
+ // Create the new UMin reduction recipe to track the minimum index.
+ assert(!FindLastIVPhiR->isInLoop() && !FindLastIVPhiR->isOrdered() &&
+ "inloop and ordered reductions not supported");
+ VPValue *MaxIV =
+ Plan.getConstantInt(APInt::getMaxValue(Ty->getIntegerBitWidth()));
+ assert(FindLastIVPhiR->getVFScaleFactor() == 1 &&
+ "FindIV reduction must not be scaled");
+ ReductionStyle Style = RdxUnordered{1};
+ auto *FirstIdxPhiR = new VPReductionPHIRecipe(
+ dyn_cast_or_null<PHINode>(FindLastIVPhiR->getUnderlyingValue()),
+ RecurKind::UMin, *MaxIV, *FindIVSelectR, Style,
+ FindLastIVPhiR->hasUsesOutsideReductionChain());
----------------
fhahn wrote:
the phis still store the recurrence kind, and leaving it as FindLastXX may be confusing/misleading?
https://github.com/llvm/llvm-project/pull/170223
More information about the llvm-commits
mailing list