[llvm] [LV] Support argmin/argmax with strict predicates. (PR #170223)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 13 04:47:19 PST 2026
================
@@ -1432,7 +1433,143 @@ bool VPlanTransforms::handleFindLastReductions(VPlan &Plan) {
return true;
}
-bool VPlanTransforms::handleMultiUseReductions(VPlan &Plan) {
+/// Given a first argmin/argmax pattern with strict predicate consisting of
+/// 1) a MinOrMax reduction \p MinOrMaxPhiR producing \p MinOrMaxResult,
+/// 2) a wide induction \p WideIV,
+/// 3) a FindLastIV reduction \p FindLastIVPhiR,
+/// return the smallest index of the FindLastIV reduction result using UMin,
+/// unless \p MinOrMaxResult equals the start value of its MinOrMax reduction.
+/// In that case, return the start value of the FindLastIV reduction instead.
+/// If \p WideIV is not canonical, a new canonical wide IV is added, and the
+/// final result is scaled back to the non-canonical \p WideIV.
+/// The final value of the FindLastIV reduction was originally computed using
+/// \p FindIVSelect, \p FindIVCmp, and \p FindIVRdxResult, which are replaced
+/// and removed.
+/// Returns true if the pattern was handled successfully, false otherwise.
+static bool handleFirstArgMinOrMax(
+ VPlan &Plan, VPReductionPHIRecipe *MinOrMaxPhiR,
+ VPReductionPHIRecipe *FindLastIVPhiR, VPWidenIntOrFpInductionRecipe *WideIV,
+ VPInstruction *MinOrMaxResult, VPInstruction *FindIVSelect,
+ VPRecipeBase *FindIVCmp, VPInstruction *FindIVRdxResult) {
+ Type *Ty = Plan.getVectorLoopRegion()->getCanonicalIVType();
+ // TODO: Support non (i.e., narrower than) canonical IV types.
+ if (Ty != VPTypeAnalysis(Plan).inferScalarType(WideIV))
+ return false;
+
+ auto *FindIVSelectR = cast<VPSingleDefRecipe>(
+ FindLastIVPhiR->getBackedgeValue()->getDefiningRecipe());
+ assert(
+ match(FindIVSelectR, m_Select(m_VPValue(), m_VPValue(), m_VPValue())) &&
+ "backedge value must be a select");
+ if (FindIVSelectR->getOperand(1) != WideIV &&
+ FindIVSelectR->getOperand(2) != WideIV)
+ return false;
+
+ // If the original wide IV is not canonical, create a new one. The canonical
+ // wide IV is guaranteed to not wrap for all lanes that are active in the
+ // vector loop.
+ 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.
+ FindIVSelectR->setOperand(FindIVSelectR->getOperand(1) == WideIV ? 1 : 2,
+ WidenCanIV);
+ }
+
+ assert(!FindLastIVPhiR->isInLoop() && !FindLastIVPhiR->isOrdered() &&
+ "inloop and ordered reductions not supported");
+ assert(FindLastIVPhiR->getVFScaleFactor() == 1 &&
+ "FindIV reduction must not be scaled");
----------------
ayalz wrote:
Better place all such precondition asserts at the beginning?
https://github.com/llvm/llvm-project/pull/170223
More information about the llvm-commits
mailing list