Extend LoopVectorize's SelectCmp pattern for non-invariant statements,
and get LoopUtils' createCmpSelectTargetReduction to CodeGen for this
case. Consider 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;Here, r = i is non-invariant, and CodeGen'ing for this case involves the
following:
- Create a Splat with the int_min/int_max values, depending on the loop direction.
- 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 above case is vectorized.
For the following case, the final value might not be able to pick by the min/max reduction.
int test(int a[32000]) { int k = -1; for (int i = 0; i < 32000; i++) if (a[i] < 0) k = a[i]; return k; }Extra checking of NonPhi might be needed. So the reduction can generate min/max.
auto *AR = dyn_cast<SCEVAddRecExpr>(SE->getSCEV(NonPhi)); if (AR) { const SCEV *Step = AR->getStepRecurrence(*SE); const SCEVConstant *ConstStep = dyn_cast<SCEVConstant>(Step); if (!ConstStep && !SE->isLoopInvariant(Step, Loop)) return InstDesc(false, I); } else return InstDesc(false, I);Would it need to check AR->hasNoUnsignedWrap?