================
@@ -1001,3 +1005,138 @@ 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;
+
+ // MinMaxPhiR has users outside the reduction cycle in the loop. Check if
+ // the only other user is a FindLastIV reduction. MinMaxPhiR must have
+ // exactly 3 users: 1) the min/max operation, the compare of a FindLastIV
+ // reduction and ComputeReductionResult. The comparisom must compare
+ // MinMaxPhiR against the min/max operand used for the min/max reduction
+ // and only be used by the select of the FindLastIV reduction.
+ RecurKind RdxKind = MinMaxPhiR->getRecurrenceKind();
+ assert(
+ RecurrenceDescriptor::isIntMinMaxRecurrenceKind(RdxKind) &&
+ "only min/max recurrences support users outside the reduction chain");
+
+ auto *MinMaxOp =
+ dyn_cast<VPRecipeWithIRFlags>(MinMaxPhiR->getBackedgeValue());
+ if (!MinMaxOp)
+ return false;
+
+ // MinMaxOp must have 2 users: 1) MinMaxPhiR and 2) ComputeReductionResult
+ // (asserted below).
+ assert(MinMaxOp->getNumUsers() == 2 &&
+ "MinMaxOp must have exactly 2 users");
+
+ 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);
+ assert(MinMaxOpA == MinMaxPhiR &&
+ "one of MinMaxOp's operands must be the phi");
----------------
ayalz wrote:
Would this be clearer:
```suggestion
VPValue *TempValueBeingReduced = MinMaxOp->getOperand(0);
if (TempValueBeingReduced == MinMaxPhiR)
TempValueBeingReduced = MinMaxOp->getOperand(1);
```
"one of MinMaxOp's operands must be the phi" - is asserted later by making sure MinMaxOp uses MinMaxPhiR.
https://github.com/llvm/llvm-project/pull/141431