LoopVectorize's SelectCmp pattern suffers from the deficiency that it
cannot handle non-invariant statements. In order to support
vectorization of the following example,
int src[n] = {4, 5, 2}; int r = 331; for (int i = 0; i < n; i++) { if (src[i] > 3) r = i; } return r;
introduce RecurKind::InductionIMax, RecurKind::InductionIMin,
RecurKind::InductionFMax, and RecurKind::InductionFMin. We currently
only support assignments to the induction variable; in particular, we do
not support the following case:
int src[n] = {4, 5, 2}; int r = 331; for (int i = 0; i < n; i++) { if (src[i] > 3) r = src[i]; } return r;
CodeGen'ing for our original example involves checking the SCEV AddRec
expression (the min/max is inverted if the assignment is r = -i, in
place of r = i). Indeed, once we determine whether it's a min or max
reduction, CodeGen'ing involves the following:
- Create a Splat with the int_min/int_max values, depending on the RecurKind.
- The Src is filled with values: {0, 1, 2, 3, 4, ...}.
- The Right is filled with values: {0, 1, 331, 331, 331, ...}.
- The CmpVector is filled with values: {1, 1, 0, 0, 0, ...}.
- Select using this CmpVector between Src and the Splat with int_min/int_max values.
- Use a max-reduce/min-reduce on the result of the Select.
- Use the exising Cmp which determines whether or not any assignment took place in the loop to select between the result of the max-reduce/min-reduce, and the initial value (InitVal).
Hence, the original example is vectorized.
I can understand the literal meaning of "the induction variable to be maximized/minimized," but perhaps there is a better way to describe this pattern, such as "monotonic increasing" and "monotonic decreasing."