@@ -216,6 +216,52 @@ static bool checkOrderedReduction(RecurKind Kind, Instruction *ExactFPMathInst,
216216 return true ;
217217}
218218
219+ // / Returns true if \p Phi is a min/max reduction matching \p Kind where \p Phi
220+ // / is used outside the reduction chain. This is common for loops selecting the
221+ // / index of a minimum/maximum value (argmin/argmax).
222+ static bool isMinMaxReductionPhiWithUsersOutsideReductionChain (
223+ PHINode *Phi, RecurKind Kind, Loop *TheLoop, RecurrenceDescriptor &RedDes) {
224+ BasicBlock *Latch = TheLoop->getLoopLatch ();
225+ if (!Latch)
226+ return false ;
227+
228+ assert (Phi->getNumIncomingValues () == 2 && " phi must have 2 incoming values" );
229+ Value *Inc = Phi->getIncomingValueForBlock (Latch);
230+ if (Phi->hasOneUse () || !Inc->hasOneUse () ||
231+ !RecurrenceDescriptor::isIntMinMaxRecurrenceKind (Kind))
232+ return false ;
233+
234+ Value *A, *B;
235+ bool IsMinMax = [&]() {
236+ switch (Kind) {
237+ case RecurKind::UMax:
238+ return match (Inc, m_UMax (m_Value (A), m_Value (B)));
239+ case RecurKind::UMin:
240+ return match (Inc, m_UMin (m_Value (A), m_Value (B)));
241+ case RecurKind::SMax:
242+ return match (Inc, m_SMax (m_Value (A), m_Value (B)));
243+ case RecurKind::SMin:
244+ return match (Inc, m_SMin (m_Value (A), m_Value (B)));
245+ default :
246+ llvm_unreachable (" all min/max kinds must be handled" );
247+ }
248+ }();
249+ if (!IsMinMax)
250+ return false ;
251+
252+ if (A == B || (A != Phi && B != Phi))
253+ return false ;
254+
255+ SmallPtrSet<Instruction *, 4 > CastInsts;
256+ Value *RdxStart = Phi->getIncomingValueForBlock (TheLoop->getLoopPreheader ());
257+ RedDes =
258+ RecurrenceDescriptor (RdxStart, /* Exit=*/ nullptr , /* Store=*/ nullptr , Kind,
259+ FastMathFlags (), /* ExactFP=*/ nullptr , Phi->getType (),
260+ /* Signed=*/ false , /* Ordered=*/ false , CastInsts,
261+ /* MinWidthCastToRecurTy=*/ -1U , /* PhiMultiUse=*/ true );
262+ return true ;
263+ }
264+
219265bool RecurrenceDescriptor::AddReductionVar (
220266 PHINode *Phi, RecurKind Kind, Loop *TheLoop, FastMathFlags FuncFMF,
221267 RecurrenceDescriptor &RedDes, DemandedBits *DB, AssumptionCache *AC,
@@ -227,6 +273,11 @@ bool RecurrenceDescriptor::AddReductionVar(
227273 if (Phi->getParent () != TheLoop->getHeader ())
228274 return false ;
229275
276+ // Check for min/max reduction variables that feed other users in the loop.
277+ if (isMinMaxReductionPhiWithUsersOutsideReductionChain (Phi, Kind, TheLoop,
278+ RedDes))
279+ return true ;
280+
230281 // Obtain the reduction start value from the value that comes from the loop
231282 // preheader.
232283 Value *RdxStart = Phi->getIncomingValueForBlock (TheLoop->getLoopPreheader ());
0 commit comments