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

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 9 07:43:43 PDT 2021


https://reviews.llvm.org/rG84cdccc9dc68

On Thu, Apr 8, 2021 at 5:38 PM Sanjay Patel <spatel at rotateright.com> wrote:

> Yes, good point. We can't guarantee that we'll get the result we want from
> here, but it makes a difference in the motivating test because it's not
> getting CSE'd that late.
>
> On Thu, Apr 8, 2021 at 2:58 PM Craig Topper <craig.topper at gmail.com>
> wrote:
>
>> 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/20210409/0051beb1/attachment.html>


More information about the llvm-commits mailing list