[llvm] [LoopVectorize] Vectorize select-cmp reduction pattern for increasing integer induction variable (PR #67812)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Sat Nov 30 14:27:11 PST 2024
================
@@ -658,6 +660,93 @@ RecurrenceDescriptor::isAnyOfPattern(Loop *Loop, PHINode *OrigPhi,
: RecurKind::FAnyOf);
}
+// We are looking for loops that do something like this:
+// int r = 0;
+// for (int i = 0; i < n; i++) {
+// if (src[i] > 3)
+// r = i;
+// }
+// The reduction value (r) is derived from either the values of an increasing
+// induction variable (i) sequence, or from the start value (0).
+// The LLVM IR generated for such loops would be as follows:
+// for.body:
+// %r = phi i32 [ %spec.select, %for.body ], [ 0, %entry ]
+// %i = phi i32 [ %inc, %for.body ], [ 0, %entry ]
+// ...
+// %cmp = icmp sgt i32 %5, 3
+// %spec.select = select i1 %cmp, i32 %i, i32 %r
+// %inc = add nsw i32 %i, 1
+// ...
+// Since 'i' is an increasing induction variable, the reduction value after the
+// loop will be the maximum value of 'i' that the condition (src[i] > 3) is
+// satisfied, or the start value (0 in the example above). When the start value
+// of the increasing induction variable 'i' is greater than the minimum value of
+// the data type, we can use the minimum value of the data type as a sentinel
+// value to replace the start value. This allows us to perform a single
+// reduction max operation to obtain the final reduction result.
+// TODO: It is possible to solve the case where the start value is the minimum
+// value of the data type or a non-constant value by using mask and multiple
+// reduction operations.
+RecurrenceDescriptor::InstDesc
+RecurrenceDescriptor::isFindLastIVPattern(PHINode *OrigPhi, Instruction *I,
+ ScalarEvolution &SE) {
+ // TODO: Support the vectorization of FindLastIV when the reduction phi is
+ // used by more than one select instruction. This vectorization is only
+ // performed when the SCEV of each increasing induction variable used by the
+ // select instructions is identical.
+ if (!OrigPhi->hasOneUse())
+ return InstDesc(false, I);
+
+ // TODO: Match selects with multi-use cmp conditions.
+ Value *NonRdxPhi = nullptr;
+ if (!match(I, m_CombineOr(m_Select(m_OneUse(m_Cmp()), m_Value(NonRdxPhi),
+ m_Specific(OrigPhi)),
+ m_Select(m_OneUse(m_Cmp()), m_Specific(OrigPhi),
+ m_Value(NonRdxPhi)))))
+ return InstDesc(false, I);
+
+ auto IsIncreasingLoopInduction = [&](Value *V) {
+ Type *Ty = V->getType();
+ if (!SE.isSCEVable(Ty))
+ return false;
+
+ auto *AR = dyn_cast<SCEVAddRecExpr>(SE.getSCEV(V));
+ if (!AR)
----------------
fhahn wrote:
Would probably also be good to check if the AddRec is for the right loop and not for an outer loop? If is not in the current loop, it will just be a regular select of integer reduction, but would still be good to explicitly check (or assert if possible). Also would be good to make sure there's a test case where the select op is an IV from an outer loop.
https://github.com/llvm/llvm-project/pull/67812
More information about the llvm-commits
mailing list