[llvm] 8d48766 - [CVP] Soften SDiv into a UDiv as long as we know domains of both of the operands.
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Sat Jul 18 09:03:57 PDT 2020
> On Jul 18, 2020, at 16:00, Roman Lebedev via llvm-commits <llvm-commits at lists.llvm.org> wrote:
>
>
> Author: Roman Lebedev
> Date: 2020-07-18T17:59:56+03:00
> New Revision: 8d487668d09fb0e4e54f36207f07c1480ffabbfd
>
> URL: https://github.com/llvm/llvm-project/commit/8d487668d09fb0e4e54f36207f07c1480ffabbfd
> DIFF: https://github.com/llvm/llvm-project/commit/8d487668d09fb0e4e54f36207f07c1480ffabbfd.diff
>
> LOG: [CVP] Soften SDiv into a UDiv as long as we know domains of both of the operands.
>
> Yes, if operands are non-positive this comes at the extra cost
> of two extra negations. But a. division is already just
> ridiculously costly, two more subtractions can't hurt much :)
> and b. we have better/more analyzes/folds for an unsigned division,
> we could end up narrowing it's bitwidth, converting it to lshr, etc.
>
> This is essentially a take two on 0fdcca07ad2c0bdc2cdd40ba638109926f4f513b,
> which didn't fix the potential regression i was seeing,
> because ValueTracking's computeKnownBits() doesn't make use
> of dominating conditions in it's analysis.
> While i could teach it that, this seems like the more general fix.
>
> This big hammer actually does catch said potential regression.
>
> Over vanilla test-suite + RawSpeed + darktable
> (10M IR instrs, 1M IR BB, 1M X86 ASM instrs), this fires/converts 5 more
> (+2%) SDiv's, the total instruction count at the end of middle-end pipeline
> is only +6, so out of +10 extra negations, ~half are folded away,
> and asm instr count is only +1, so practically speaking all extra
> negations are folded away and are therefore free.
> Sadly, all these new UDiv's remained, none folded away.
> But there are two less basic blocks.
>
> https://rise4fun.com/Alive/VS6
>
> Name: v0
> Pre: C0 >= 0 && C1 >= 0
> %r = sdiv i8 C0, C1
> =>
> %r = udiv i8 C0, C1
>
> Name: v1
> Pre: C0 <= 0 && C1 >= 0
> %r = sdiv i8 C0, C1
> =>
> %t0 = udiv i8 -C0, C1
> %r = sub i8 0, %t0
>
> Name: v2
> Pre: C0 >= 0 && C1 <= 0
> %r = sdiv i8 C0, C1
> =>
> %t0 = udiv i8 C0, -C1
> %r = sub i8 0, %t0
>
> Name: v3
> Pre: C0 <= 0 && C1 <= 0
> %r = sdiv i8 C0, C1
> =>
> %r = udiv i8 -C0, -C1
>
> Added:
>
>
> Modified:
> llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
> llvm/test/Transforms/CorrelatedValuePropagation/sdiv.ll
>
> Removed:
>
>
>
> ################################################################################
> diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
> index 284312eaf822..fb7a005708e5 100644
> --- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
> +++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
> @@ -607,6 +607,12 @@ static bool isNonNegative(Value *V, LazyValueInfo *LVI, Instruction *CxtI) {
> return Result == LazyValueInfo::True;
> }
>
> +static bool isNonPositive(Value *V, LazyValueInfo *LVI, Instruction *CxtI) {
> + Constant *Zero = ConstantInt::get(V->getType(), 0);
> + auto Result = LVI->getPredicateAt(ICmpInst::ICMP_SLE, V, Zero, CxtI);
> + return Result == LazyValueInfo::True;
> +}
> +
> static bool allOperandsAreNonNegative(BinaryOperator *SDI, LazyValueInfo *LVI) {
> return all_of(SDI->operands(),
> [&](Value *Op) { return isNonNegative(Op, LVI, SDI); });
> @@ -672,24 +678,65 @@ static bool processSRem(BinaryOperator *SDI, LazyValueInfo *LVI) {
> }
>
> /// See if LazyValueInfo's ability to exploit edge conditions or range
> -/// information is sufficient to prove the both operands of this SDiv are
> -/// positive. If this is the case, replace the SDiv with a UDiv. Even for local
> +/// information is sufficient to prove the signs of both operands of this SDiv.
> +/// If this is the case, replace the SDiv with a UDiv. Even for local
> /// conditions, this can sometimes prove conditions instcombine can't by
> /// exploiting range information.
> static bool processSDiv(BinaryOperator *SDI, LazyValueInfo *LVI) {
> - if (SDI->getType()->isVectorTy() || !allOperandsAreNonNegative(SDI, LVI))
> + if (SDI->getType()->isVectorTy())
> return false;
>
> + enum class Domain { NonNegative, NonPositive, Unknown };
> + auto getDomain = [&](Value *V) {
> + if (isNonNegative(V, LVI, SDI))
> + return Domain::NonNegative;
> + if (isNonPositive(V, LVI, SDI))
> + return Domain::NonPositive;
> + return Domain::Unknown;
> + };
> +
> + struct Operand {
> + Value *V;
> + Domain Domain;
> + };
> + std::array<Operand, 2> Ops;
> + for (const auto &I : zip(Ops, SDI->operands())) {
It looks like this is causing the following warning:
lvm-project/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp:703:20: warning: loop variable 'I' is always a copy because the range of type 'detail::zippy<detail::zip_shortest, array<Operand, 2> &, iterator_range<Use *> >' does not return a reference [-Wrange-loop-analysis]
for (const auto &I : zip(Ops, SDI->operands())) {
More information about the llvm-commits
mailing list