<div dir="ltr">Yes, that should be better. I knew there was a sibling 'ugt' fold, but I hadn't considered signed preds. Will add tests and try to enhance in the near future.<br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Oct 26, 2021 at 5:47 PM Roman Lebedev <<a href="mailto:lebedev.ri@gmail.com">lebedev.ri@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Should this simply use `decomposeBitTestICmp()`?<br>
<br>
Roman<br>
<br>
On Wed, Oct 27, 2021 at 12:45 AM Sanjay Patel via llvm-commits<br>
<<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br>
><br>
><br>
> Author: Sanjay Patel<br>
> Date: 2021-10-26T17:43:28-04:00<br>
> New Revision: acabad9ff6bf13e00305d9d8621ee8eafc1f8b08<br>
><br>
> URL: <a href="https://github.com/llvm/llvm-project/commit/acabad9ff6bf13e00305d9d8621ee8eafc1f8b08" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/acabad9ff6bf13e00305d9d8621ee8eafc1f8b08</a><br>
> DIFF: <a href="https://github.com/llvm/llvm-project/commit/acabad9ff6bf13e00305d9d8621ee8eafc1f8b08.diff" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/acabad9ff6bf13e00305d9d8621ee8eafc1f8b08.diff</a><br>
><br>
> LOG: [InstCombine] try to canonicalize icmp with trunc op into mask and cmp<br>
><br>
> The motivating test is based on:<br>
> <a href="https://llvm.org/PR52260" rel="noreferrer" target="_blank">https://llvm.org/PR52260</a><br>
><br>
> We have better analysis for X == 0, so try harder to form that.<br>
><br>
> Added:<br>
><br>
><br>
> Modified:<br>
>     llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp<br>
>     llvm/test/Transforms/InstCombine/icmp-trunc.ll<br>
>     llvm/test/Transforms/InstCombine/signed-truncation-check.ll<br>
><br>
> Removed:<br>
><br>
><br>
><br>
> ################################################################################<br>
> diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp<br>
> index 54d751e30ee3..a2db1bc83e76 100644<br>
> --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp<br>
> +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp<br>
> @@ -4589,6 +4589,31 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) {<br>
>    return nullptr;<br>
>  }<br>
><br>
> +static Instruction *foldICmpWithTrunc(ICmpInst &ICmp,<br>
> +                                      InstCombiner::BuilderTy &Builder) {<br>
> +  const ICmpInst::Predicate Pred = ICmp.getPredicate();<br>
> +  Value *Op0 = ICmp.getOperand(0), *Op1 = ICmp.getOperand(1);<br>
> +<br>
> +  // Try to canonicalize trunc + compare-to-constant into a mask + cmp.<br>
> +  // The trunc masks high bits while the compare may effectively mask low bits.<br>
> +  Value *X;<br>
> +  const APInt *C;<br>
> +  if (match(Op0, m_OneUse(m_Trunc(m_Value(X)))) && match(Op1, m_Power2(C))) {<br>
> +    if (Pred == ICmpInst::ICMP_ULT) {<br>
> +      // (trunc X) u< Pow2C --> (X & MaskC) == 0<br>
> +      unsigned SrcBits = X->getType()->getScalarSizeInBits();<br>
> +      unsigned DstBits = Op0->getType()->getScalarSizeInBits();<br>
> +      APInt MaskC = APInt::getOneBitSet(SrcBits, DstBits) - C->zext(SrcBits);<br>
> +      Value *And = Builder.CreateAnd(X, MaskC);<br>
> +      Constant *Zero = ConstantInt::getNullValue(X->getType());<br>
> +      return new ICmpInst(ICmpInst::ICMP_EQ, And, Zero);<br>
> +    }<br>
> +    // TODO: Handle ugt.<br>
> +  }<br>
> +<br>
> +  return nullptr;<br>
> +}<br>
> +<br>
>  static Instruction *foldICmpWithZextOrSext(ICmpInst &ICmp,<br>
>                                             InstCombiner::BuilderTy &Builder) {<br>
>    assert(isa<CastInst>(ICmp.getOperand(0)) && "Expected cast for operand 0");<br>
> @@ -4732,6 +4757,9 @@ Instruction *InstCombinerImpl::foldICmpWithCastOp(ICmpInst &ICmp) {<br>
>        return new ICmpInst(ICmp.getPredicate(), Op0Src, NewOp1);<br>
>    }<br>
><br>
> +  if (Instruction *R = foldICmpWithTrunc(ICmp, Builder))<br>
> +    return R;<br>
> +<br>
>    return foldICmpWithZextOrSext(ICmp, Builder);<br>
>  }<br>
><br>
><br>
> diff  --git a/llvm/test/Transforms/InstCombine/icmp-trunc.ll b/llvm/test/Transforms/InstCombine/icmp-trunc.ll<br>
> index 7f961f2ccfaf..39ca767a6d2a 100644<br>
> --- a/llvm/test/Transforms/InstCombine/icmp-trunc.ll<br>
> +++ b/llvm/test/Transforms/InstCombine/icmp-trunc.ll<br>
> @@ -5,8 +5,8 @@ declare void @use(i8)<br>
><br>
>  define i1 @ult_2(i32 %x) {<br>
>  ; CHECK-LABEL: @ult_2(<br>
> -; CHECK-NEXT:    [[T:%.*]] = trunc i32 [[X:%.*]] to i8<br>
> -; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[T]], 2<br>
> +; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[X:%.*]], 254<br>
> +; CHECK-NEXT:    [[R:%.*]] = icmp eq i32 [[TMP1]], 0<br>
>  ; CHECK-NEXT:    ret i1 [[R]]<br>
>  ;<br>
>    %t = trunc i32 %x to i8<br>
> @@ -16,8 +16,8 @@ define i1 @ult_2(i32 %x) {<br>
><br>
>  define <2 x i1> @ult_16_splat(<2 x i16> %x) {<br>
>  ; CHECK-LABEL: @ult_16_splat(<br>
> -; CHECK-NEXT:    [[T:%.*]] = trunc <2 x i16> [[X:%.*]] to <2 x i11><br>
> -; CHECK-NEXT:    [[R:%.*]] = icmp ult <2 x i11> [[T]], <i11 16, i11 16><br>
> +; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i16> [[X:%.*]], <i16 2032, i16 2032><br>
> +; CHECK-NEXT:    [[R:%.*]] = icmp eq <2 x i16> [[TMP1]], zeroinitializer<br>
>  ; CHECK-NEXT:    ret <2 x i1> [[R]]<br>
>  ;<br>
>    %t = trunc <2 x i16> %x to <2 x i11><br>
> @@ -25,6 +25,8 @@ define <2 x i1> @ult_16_splat(<2 x i16> %x) {<br>
>    ret <2 x i1> %r<br>
>  }<br>
><br>
> +; negative test - need power-of-2 constant<br>
> +<br>
>  define i1 @ult_3(i32 %x) {<br>
>  ; CHECK-LABEL: @ult_3(<br>
>  ; CHECK-NEXT:    [[T:%.*]] = trunc i32 [[X:%.*]] to i8<br>
> @@ -36,6 +38,8 @@ define i1 @ult_3(i32 %x) {<br>
>    ret i1 %r<br>
>  }<br>
><br>
> +; negative test - no extra use allowed<br>
> +<br>
>  define i1 @ult_2_use(i32 %x) {<br>
>  ; CHECK-LABEL: @ult_2_use(<br>
>  ; CHECK-NEXT:    [[T:%.*]] = trunc i32 [[X:%.*]] to i8<br>
> @@ -53,12 +57,7 @@ define i1 @ult_2_use(i32 %x) {<br>
><br>
>  define i1 @PR52260(i32 %x) {<br>
>  ; CHECK-LABEL: @PR52260(<br>
> -; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[X:%.*]] to i64<br>
> -; CHECK-NEXT:    [[IDX:%.*]] = getelementptr inbounds [3 x i32], [3 x i32]* @a, i64 0, i64 [[IDXPROM]]<br>
> -; CHECK-NEXT:    [[T1:%.*]] = load i32, i32* [[IDX]], align 4<br>
> -; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[T1]] to i8<br>
> -; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ult i8 [[TMP1]], 2<br>
> -; CHECK-NEXT:    ret i1 [[TOBOOL]]<br>
> +; CHECK-NEXT:    ret i1 true<br>
>  ;<br>
>    %idxprom = sext i32 %x to i64<br>
>    %idx = getelementptr inbounds [3 x i32], [3 x i32]* @a, i64 0, i64 %idxprom<br>
> @@ -69,4 +68,3 @@ define i1 @PR52260(i32 %x) {<br>
>    %tobool = icmp eq i8 %conv2, 0<br>
>    ret i1 %tobool<br>
>  }<br>
> -<br>
><br>
> diff  --git a/llvm/test/Transforms/InstCombine/signed-truncation-check.ll b/llvm/test/Transforms/InstCombine/signed-truncation-check.ll<br>
> index 105e77284b93..6681d5021472 100644<br>
> --- a/llvm/test/Transforms/InstCombine/signed-truncation-check.ll<br>
> +++ b/llvm/test/Transforms/InstCombine/signed-truncation-check.ll<br>
> @@ -397,8 +397,8 @@ define i1 @positive_trunc_signbit_logical(i32 %arg) {<br>
><br>
>  define i1 @positive_trunc_base(i32 %arg) {<br>
>  ; CHECK-LABEL: @positive_trunc_base(<br>
> -; CHECK-NEXT:    [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i16<br>
> -; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp ult i16 [[T1]], 128<br>
> +; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARG:%.*]], 65408<br>
> +; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp eq i32 [[TMP1]], 0<br>
>  ; CHECK-NEXT:    ret i1 [[T5_SIMPLIFIED]]<br>
>  ;<br>
>    %t1 = trunc i32 %arg to i16<br>
> @@ -411,8 +411,8 @@ define i1 @positive_trunc_base(i32 %arg) {<br>
><br>
>  define i1 @positive_trunc_base_logical(i32 %arg) {<br>
>  ; CHECK-LABEL: @positive_trunc_base_logical(<br>
> -; CHECK-NEXT:    [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i16<br>
> -; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp ult i16 [[T1]], 128<br>
> +; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARG:%.*]], 65408<br>
> +; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp eq i32 [[TMP1]], 0<br>
>  ; CHECK-NEXT:    ret i1 [[T5_SIMPLIFIED]]<br>
>  ;<br>
>    %t1 = trunc i32 %arg to i16<br>
><br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
> <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>