[llvm] 4069ccc - [InstCombine] fold icmp with sub and bool

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Sun May 22 09:17:03 PDT 2022


Thanks! Yes, the pattern without sub is probably good enough, and I botched
that implementation (bots failing), so reverted.

On Sun, May 22, 2022 at 12:14 PM Nikita Popov <nikita.ppv at gmail.com> wrote:

> On Sun, May 22, 2022 at 6:11 PM Nikita Popov <nikita.ppv at gmail.com> wrote:
>
>> On Sun, May 22, 2022 at 5:54 PM Sanjay Patel via llvm-commits <
>> llvm-commits at lists.llvm.org> wrote:
>>
>>>
>>> Author: Sanjay Patel
>>> Date: 2022-05-22T11:51:07-04:00
>>> New Revision: 4069cccf3b4ff4afb743d3d371ead9e2d5491e3a
>>>
>>> URL:
>>> https://github.com/llvm/llvm-project/commit/4069cccf3b4ff4afb743d3d371ead9e2d5491e3a
>>> DIFF:
>>> https://github.com/llvm/llvm-project/commit/4069cccf3b4ff4afb743d3d371ead9e2d5491e3a.diff
>>>
>>> LOG: [InstCombine] fold icmp with sub and bool
>>>
>>> This is the specific pattern seen in #53432, but it can be extended
>>> in multiple ways:
>>> 1. The 'zext' could be an 'and'
>>> 2. The 'sub' could be some other binop with a similar ==0 property
>>> (udiv).
>>>
>>> There might be some way to generalize using knownbits, but that
>>> would require checking that the 'bool' value is created with
>>> some instruction that can be replaced with new icmp+logic.
>>>
>>> https://alive2.llvm.org/ce/z/-KCfpa
>>>
>>
>> Are the multi-use cases here motivating? Otherwise, I would have found it
>> more intuitive to use a pattern like https://alive2.llvm.org/ce/z/XqbXm4
>> that is not specific to sub.
>>
>
> Also, isn't this missing a check that the zext is from i1 rather than some
> other type?
>
> Nikita
>
>
>>
>>
>>> Added:
>>>
>>>
>>> Modified:
>>>     llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
>>>     llvm/test/Transforms/InstCombine/icmp-range.ll
>>>
>>> Removed:
>>>
>>>
>>>
>>>
>>> ################################################################################
>>> diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
>>> b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
>>> index 4f20a0699ec50..e2a6b6b1495b8 100644
>>> --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
>>> +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
>>> @@ -5631,6 +5631,29 @@ Instruction
>>> *InstCombinerImpl::foldICmpUsingKnownBits(ICmpInst &I) {
>>>    return nullptr;
>>>  }
>>>
>>> +/// If one operand of an icmp is effectively a bool (value range of
>>> {0,1}),
>>> +/// then try to reduce patterns based on that limit.
>>> +static Instruction *foldICmpUsingBoolRange(ICmpInst &I,
>>> +                                           InstCombiner::BuilderTy
>>> &Builder) {
>>> +  Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
>>> +  const ICmpInst::Predicate Pred = I.getPredicate();
>>> +
>>> +  Value *X, *Y, *Z;
>>> +  if (Pred != ICmpInst::ICMP_ULT || !match(Op0, m_Sub(m_Value(X),
>>> m_Value(Y))))
>>> +    return nullptr;
>>> +
>>> +  unsigned ExtraUses = !Op0->hasOneUse() + !Op1->hasOneUse();
>>> +
>>> +  // Sub must be 0 and bool must be true for "ULT":
>>> +  // (sub X, Y) <u (zext i1 Z) --> (X == Y) && Z
>>> +  if (match(Op1, m_ZExt(m_Value(Z))) && ExtraUses < 2) {
>>> +    Value *EqXY = Builder.CreateICmpEQ(X, Y);
>>> +    return BinaryOperator::CreateAnd(EqXY, Z);
>>> +  }
>>> +
>>> +  return nullptr;
>>> +}
>>> +
>>>  llvm::Optional<std::pair<CmpInst::Predicate, Constant *>>
>>>  InstCombiner::getFlippedStrictnessPredicateAndConstant(CmpInst::Predicate
>>> Pred,
>>>                                                         Constant *C) {
>>> @@ -6058,6 +6081,9 @@ Instruction
>>> *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
>>>    if (Instruction *Res = foldICmpWithDominatingICmp(I))
>>>      return Res;
>>>
>>> +  if (Instruction *Res = foldICmpUsingBoolRange(I, Builder))
>>> +    return Res;
>>> +
>>>    if (Instruction *Res = foldICmpUsingKnownBits(I))
>>>      return Res;
>>>
>>>
>>> diff  --git a/llvm/test/Transforms/InstCombine/icmp-range.ll
>>> b/llvm/test/Transforms/InstCombine/icmp-range.ll
>>> index b67356675eba6..a29d4cd81b9d1 100644
>>> --- a/llvm/test/Transforms/InstCombine/icmp-range.ll
>>> +++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
>>> @@ -173,9 +173,8 @@ define i1 @test_two_ranges3(i32* nocapture readonly
>>> %arg1, i32* nocapture readon
>>>
>>>  define i1 @sub_ult_zext(i1 %b, i8 %x, i8 %y) {
>>>  ; CHECK-LABEL: @sub_ult_zext(
>>> -; CHECK-NEXT:    [[Z:%.*]] = zext i1 [[B:%.*]] to i8
>>> -; CHECK-NEXT:    [[S:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
>>> -; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[S]], [[Z]]
>>> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]]
>>> +; CHECK-NEXT:    [[R:%.*]] = and i1 [[TMP1]], [[B:%.*]]
>>>  ; CHECK-NEXT:    ret i1 [[R]]
>>>  ;
>>>    %z = zext i1 %b to i8
>>> @@ -188,8 +187,8 @@ define i1 @sub_ult_zext_use1(i1 %b, i8 %x, i8 %y) {
>>>  ; CHECK-LABEL: @sub_ult_zext_use1(
>>>  ; CHECK-NEXT:    [[Z:%.*]] = zext i1 [[B:%.*]] to i8
>>>  ; CHECK-NEXT:    call void @use(i8 [[Z]])
>>> -; CHECK-NEXT:    [[S:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
>>> -; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[S]], [[Z]]
>>> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]]
>>> +; CHECK-NEXT:    [[R:%.*]] = and i1 [[TMP1]], [[B]]
>>>  ; CHECK-NEXT:    ret i1 [[R]]
>>>  ;
>>>    %z = zext i1 %b to i8
>>> @@ -201,10 +200,10 @@ define i1 @sub_ult_zext_use1(i1 %b, i8 %x, i8 %y) {
>>>
>>>  define <2 x i1> @zext_ugt_sub_use2(<2 x i1> %b, <2 x i8> %x, <2 x i8>
>>> %y) {
>>>  ; CHECK-LABEL: @zext_ugt_sub_use2(
>>> -; CHECK-NEXT:    [[Z:%.*]] = zext <2 x i1> [[B:%.*]] to <2 x i8>
>>>  ; CHECK-NEXT:    [[S:%.*]] = sub <2 x i8> [[X:%.*]], [[Y:%.*]]
>>>  ; CHECK-NEXT:    call void @use_vec(<2 x i8> [[S]])
>>> -; CHECK-NEXT:    [[R:%.*]] = icmp ult <2 x i8> [[S]], [[Z]]
>>> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i8> [[X]], [[Y]]
>>> +; CHECK-NEXT:    [[R:%.*]] = and <2 x i1> [[TMP1]], [[B:%.*]]
>>>  ; CHECK-NEXT:    ret <2 x i1> [[R]]
>>>  ;
>>>    %z = zext <2 x i1> %b to <2 x i8>
>>> @@ -214,6 +213,8 @@ define <2 x i1> @zext_ugt_sub_use2(<2 x i1> %b, <2 x
>>> i8> %x, <2 x i8> %y) {
>>>    ret <2 x i1> %r
>>>  }
>>>
>>> +; negative test - too many extra uses
>>> +
>>>  define i1 @sub_ult_zext_use3(i1 %b, i8 %x, i8 %y) {
>>>  ; CHECK-LABEL: @sub_ult_zext_use3(
>>>  ; CHECK-NEXT:    [[Z:%.*]] = zext i1 [[B:%.*]] to i8
>>> @@ -231,6 +232,8 @@ define i1 @sub_ult_zext_use3(i1 %b, i8 %x, i8 %y) {
>>>    ret i1 %r
>>>  }
>>>
>>> +; negative test - wrong predicate
>>> +
>>>  define i1 @sub_ule_zext(i1 %b, i8 %x, i8 %y) {
>>>  ; CHECK-LABEL: @sub_ule_zext(
>>>  ; CHECK-NEXT:    [[Z:%.*]] = zext i1 [[B:%.*]] to i8
>>>
>>>
>>>
>>> _______________________________________________
>>> 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/20220522/b19d6dd2/attachment.html>


More information about the llvm-commits mailing list