[llvm] 5094e12 - [InstCombine] fold min/max intrinsic with negated operand to abs

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 8 11:58:46 PDT 2021


Should we make any effort to pick I0 vs I1 as the input to the abs. If one
has one use and the other doesn't it might be better to pick the one with
multiple uses?

~Craig


On Thu, Apr 8, 2021 at 11:47 AM Sanjay Patel via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

>
> Author: Sanjay Patel
> Date: 2021-04-08T14:37:39-04:00
> New Revision: 5094e1279eb2e168bf6818b368bf6ff4835de2bc
>
> URL:
> https://github.com/llvm/llvm-project/commit/5094e1279eb2e168bf6818b368bf6ff4835de2bc
> DIFF:
> https://github.com/llvm/llvm-project/commit/5094e1279eb2e168bf6818b368bf6ff4835de2bc.diff
>
> LOG: [InstCombine] fold min/max intrinsic with negated operand to abs
>
> The smax case shows up in https://llvm.org/PR49885 .
> The others seem unlikely, but we might as well try
> for uniformity (although that could mean an extra
> instruction to create "nabs").
>
> smax -- https://alive2.llvm.org/ce/z/8yYaGy
> smin -- https://alive2.llvm.org/ce/z/0_7zc_
> umax -- https://alive2.llvm.org/ce/z/EcsZWs
> umin -- https://alive2.llvm.org/ce/z/Xw6WvB
>
> Added:
>
>
> Modified:
>     llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
>     llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
>
> Removed:
>
>
>
>
> ################################################################################
> diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
> b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
> index 4d9005840b4b6..b139960b478e6 100644
> --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
> +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
> @@ -911,6 +911,22 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst
> &CI) {
>        }
>      }
>
> +    // smax(X, -X) --> abs(X)
> +    // smin(X, -X) --> -abs(X)
> +    // umax(X, -X) --> -abs(X)
> +    // umin(X, -X) --> abs(X)
> +    if (isKnownNegation(I0, I1)) {
> +      // This is some variant of abs(). See if we can propagate 'nsw' to
> the abs
> +      // operation and potentially its negation.
> +      bool IntMinIsPoison = isKnownNegation(I0, I1, /* NeedNSW */ true);
> +      Value *Abs = Builder.CreateBinaryIntrinsic(
> +          Intrinsic::abs, I0,
> +          ConstantInt::getBool(II->getContext(), IntMinIsPoison));
> +      if (IID == Intrinsic::smin || IID == Intrinsic::umax)
> +        Abs = Builder.CreateNeg(Abs, "nabs", /* NUW */ false,
> IntMinIsPoison);
> +      return replaceInstUsesWith(CI, Abs);
> +    }
> +
>      break;
>    }
>    case Intrinsic::bswap: {
>
> diff  --git a/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
> b/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
> index 5d3064fb94e0c..3d6d3e333b2bf 100644
> --- a/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
> +++ b/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
> @@ -611,9 +611,8 @@ define i8 @not_umin_of_not_constant_op(i8 %x) {
>  define i8 @smax_negation(i8 %x, i8 %y) {
>  ; CHECK-LABEL: @smax_negation(
>  ; CHECK-NEXT:    [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
> -; CHECK-NEXT:    [[S2:%.*]] = sub i8 [[Y]], [[X]]
> -; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[S1]], i8 [[S2]])
> -; CHECK-NEXT:    ret i8 [[R]]
> +; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
> +; CHECK-NEXT:    ret i8 [[TMP1]]
>  ;
>    %s1 = sub i8 %x, %y
>    %s2 = sub i8 %y, %x
> @@ -624,9 +623,8 @@ define i8 @smax_negation(i8 %x, i8 %y) {
>  define i8 @smax_negation_nsw(i8 %x, i8 %y) {
>  ; CHECK-LABEL: @smax_negation_nsw(
>  ; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
> -; CHECK-NEXT:    [[S2:%.*]] = sub nsw i8 [[Y]], [[X]]
> -; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[S1]], i8 [[S2]])
> -; CHECK-NEXT:    ret i8 [[R]]
> +; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true)
> +; CHECK-NEXT:    ret i8 [[TMP1]]
>  ;
>    %s1 = sub nsw i8 %x, %y
>    %s2 = sub nsw i8 %y, %x
> @@ -637,9 +635,8 @@ define i8 @smax_negation_nsw(i8 %x, i8 %y) {
>  define i8 @smax_negation_not_nsw(i8 %x, i8 %y) {
>  ; CHECK-LABEL: @smax_negation_not_nsw(
>  ; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
> -; CHECK-NEXT:    [[S2:%.*]] = sub nuw i8 [[Y]], [[X]]
> -; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[S1]], i8 [[S2]])
> -; CHECK-NEXT:    ret i8 [[R]]
> +; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
> +; CHECK-NEXT:    ret i8 [[TMP1]]
>  ;
>    %s1 = sub nsw i8 %x, %y
>    %s2 = sub nuw i8 %y, %x
> @@ -649,9 +646,8 @@ define i8 @smax_negation_not_nsw(i8 %x, i8 %y) {
>
>  define <3 x i8> @smax_negation_vec(<3 x i8> %x) {
>  ; CHECK-LABEL: @smax_negation_vec(
> -; CHECK-NEXT:    [[S:%.*]] = sub <3 x i8> <i8 0, i8 undef, i8 0>,
> [[X:%.*]]
> -; CHECK-NEXT:    [[R:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8>
> [[X]], <3 x i8> [[S]])
> -; CHECK-NEXT:    ret <3 x i8> [[R]]
> +; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i8> @llvm.abs.v3i8(<3 x i8>
> [[X:%.*]], i1 false)
> +; CHECK-NEXT:    ret <3 x i8> [[TMP1]]
>  ;
>    %s = sub <3 x i8> <i8 0, i8 undef, i8 0>, %x
>    %r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %x, <3 x i8> %s)
> @@ -661,9 +657,9 @@ define <3 x i8> @smax_negation_vec(<3 x i8> %x) {
>  define i8 @smin_negation(i8 %x, i8 %y) {
>  ; CHECK-LABEL: @smin_negation(
>  ; CHECK-NEXT:    [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
> -; CHECK-NEXT:    [[S2:%.*]] = sub i8 [[Y]], [[X]]
> -; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[S1]], i8 [[S2]])
> -; CHECK-NEXT:    ret i8 [[R]]
> +; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
> +; CHECK-NEXT:    [[NABS:%.*]] = sub i8 0, [[TMP1]]
> +; CHECK-NEXT:    ret i8 [[NABS]]
>  ;
>    %s1 = sub i8 %x, %y
>    %s2 = sub i8 %y, %x
> @@ -674,9 +670,9 @@ define i8 @smin_negation(i8 %x, i8 %y) {
>  define i8 @umax_negation(i8 %x, i8 %y) {
>  ; CHECK-LABEL: @umax_negation(
>  ; CHECK-NEXT:    [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
> -; CHECK-NEXT:    [[S2:%.*]] = sub nsw i8 [[Y]], [[X]]
> -; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[S1]], i8 [[S2]])
> -; CHECK-NEXT:    ret i8 [[R]]
> +; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true)
> +; CHECK-NEXT:    [[NABS:%.*]] = sub nsw i8 0, [[TMP1]]
> +; CHECK-NEXT:    ret i8 [[NABS]]
>  ;
>    %s1 = sub nsw i8 %x, %y
>    %s2 = sub nsw i8 %y, %x
> @@ -686,9 +682,8 @@ define i8 @umax_negation(i8 %x, i8 %y) {
>
>  define i8 @umin_negation(i8 %x) {
>  ; CHECK-LABEL: @umin_negation(
> -; CHECK-NEXT:    [[S:%.*]] = sub nsw i8 0, [[X:%.*]]
> -; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[S]], i8 [[X]])
> -; CHECK-NEXT:    ret i8 [[R]]
> +; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1
> true)
> +; CHECK-NEXT:    ret i8 [[TMP1]]
>  ;
>    %s = sub nsw i8 0, %x
>    %r = call i8 @llvm.umin.i8(i8 %s, i8 %x)
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210408/1e5a801a/attachment.html>


More information about the llvm-commits mailing list