[LV] Support predicated div/rem operations via safe-divisor select idiom
authorPhilip Reames <preames@rivosinc.com>
Wed, 24 Aug 2022 16:48:01 +0000 (09:48 -0700)
committerPhilip Reames <listmail@philipreames.com>
Wed, 24 Aug 2022 17:07:59 +0000 (10:07 -0700)
commitf79214d1e1fd79f684b53a8a1d34efeb37a33a28
treeda9477d7ead4c90ec602f52aa6b5a3fba98f2b5b
parent689895f432be9504cdbaf698a14625c950c6c6ad
[LV] Support predicated div/rem operations via safe-divisor select idiom

This patch adds support for vectorizing conditionally executed div/rem operations via a variant of widening. The existing support for predicated divrem in the vectorizer requires scalarization which we can't do for scalable vectors.

The basic idea is that we can always divide (take remainder) by 1 without executing UB. As such, we can use the active lane mask to conditional select either the actual divisor for active lanes, or a constant one for inactive lanes. We already account for the cost of the active lane mask, so the only additional cost is a splat of one and the vector select. This is one of several possible approaches to this problem; see the review thread for discussion on some of the others.  This one was chosen mostly because it was straight forward, and none of the others seemed oviously better.

I enabled the new code only for scalable vectors. We could also legally enable it for fixed vectors as well, but I haven't thought through the cost tradeoffs between widening and scalarization enough to know if that's profitable. This will be explored in future patches.

Differential Revision: https://reviews.llvm.org/D130164
llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h
llvm/test/Transforms/LoopVectorize/AArch64/scalable-predicate-instruction.ll
llvm/test/Transforms/LoopVectorize/AArch64/sve-tail-folding.ll
llvm/test/Transforms/LoopVectorize/RISCV/scalable-divrem.ll