On Thu, Sep 24, 2026 at 2:45 PM Daniel Henrique Barboza
<[email protected]> wrote:
>
>
>
> On 9/21/2026 10:45 PM, Andrea Pinski wrote:
> > On Mon, Sep 21, 2026 at 4:45 AM Daniel Barboza
> > <[email protected]> wrote:
> >>
> >> RTL is able to do this optimization but doing it earlier on gimple
> >> can promote further optimizations during tree-opt.
> >>
> >> Boostrapped and regression tested in x86_64 and aarch64.
> >>
> >>          PR tree-optimization/126523
> >>
> >> gcc/ChangeLog:
> >>
> >>          * match.pd(`(SIGNED (bit_not (UNSIGNED signed_var)))`): New
> >>          pattern.
> >>
> >> gcc/testsuite/ChangeLog:
> >>
> >>          * gcc.dg/tree-ssa/pr126523.c: New test.
> >> ---
> >>   gcc/match.pd                             | 14 +++++++++++++
> >>   gcc/testsuite/gcc.dg/tree-ssa/pr126523.c | 26 ++++++++++++++++++++++++
> >>   2 files changed, 40 insertions(+)
> >>   create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr126523.c
> >>
> >> diff --git a/gcc/match.pd b/gcc/match.pd
> >> index e59c11d5d13..2b3713e7360 100644
> >> --- a/gcc/match.pd
> >> +++ b/gcc/match.pd
> >> @@ -13279,6 +13279,20 @@ and,
> >>         && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@0)))
> >>     (convert @0)))
> >>
> >> +/* PR126523: (SIGNED (~(UNSIGNED signed_var))) -> ~signed_var.  */
> >> +(simplify
> >> + (convert (bit_not (convert@1 @0)))
> >> + (if (INTEGRAL_TYPE_P (type)
> >> +      && !TYPE_UNSIGNED (type)
> >> +      && TREE_TYPE (@0) == type
> >> +      && TYPE_UNSIGNED (TREE_TYPE (@1))
> >> +      /* Check single_use since we're getting rid of @1.  */
> >> +      && single_use (@1)
> >> +      /* The unsigned convert cannot have less bits
> >> +        than the signed result.  */
> >> +      && TYPE_PRECISION (TREE_TYPE (@1)) >= TYPE_PRECISION (type))
> >> +  (bit_not @0)))
> >
> > Hmm, a few things here.
> > `TREE_TYPE (@0) == type` should be `types_match (@0, type)` (this will
> > allow for more types matching in gimple).
> > We want to remove the converts if the inner and outer precisions are
> > the same irrespective of the signedness.
> > I think if the inner convert is a nop_convert, and the outer one is a
> > truncation, then we should emit `(convert (bit_not @0))`; I think you
> > want a single_use on the bit_not instead of the convert (nop_converts
> > are "free") and not need to check the type of @0 here.
> > For (trunc (bit_not (widdening @0))), it does not matter what the
> > signedness of @0 if precision of @0 matches the precision of the type
> > because the bits which either sign or zero extended (and then `not`ed)
> > will be truncated away.
> > So maybe types_match should really be tree_nop_conversion_p and keep
> > around the convert to type around @0 (for gimple, that will be removed
> > for the case of types_match).
> > Even more we can truncate further than @0 here too; so this should be
> > a TYPE_PRECISION check then.
>
> I came up with a pattern that would cover more cases and managed to bootstrap
> it in x86.  But then when I added more test coverage I realized that the
> patterns weren't working ... in x86. They do work in aarch64.
>
> Or so I thought.  In reality this code generates different Gimple between x86 
> and
> aarch64, on trunk.  Since my main dev machine is an aarch64 box I was misled
> into thinking that my pattern was doing something.
>
> Here's an example:
>
> https://godbolt.org/z/59rzjs1a6
>
> The aarch64 dumps have one less type cast than x86 in all the functions.

The problem is obvious for me:
typedef char int8_t;

Here int8_t is unsigned for aarch64 and signed for x86.
You need to specify `signed char` instead of a plain char or use the
option -fsigned-char :).

Thanks,
Andrea



>
>
> I played a bit to see which patterns aren't already optimized in aarch64 and
> x86 and, so far, the only pattern that can be optimized by both happens to be
> the one for the bug, i.e.  same precision conversions.
>
>
> The pattern from this bug is covering signed -> unsigned -> signed only so I 
> can
> send a v2 that covers unsigned -> signed -> unsigned.  Aside from that I'm 
> not sure
> how to proceed with the other patterns.  Should we invest time in them given 
> that
> some targets are already doing a bit of the work in Gimple?  Should we 
> optimize
> these 2 patterns that we have in hand and open a new bug to see how to 
> optimize
> the rest?
>
>
> Thanks,
> Daniel
>
>
>
>
>
>
> >
> > Thanks,
> > Andrea
> >
> >
> >
> >
> >> +
> >>   /* Optimize
> >>      c1 = VEC_PERM_EXPR (a, a, mask)
> >>      c2 = VEC_PERM_EXPR (b, b, mask)
> >> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr126523.c 
> >> b/gcc/testsuite/gcc.dg/tree-ssa/pr126523.c
> >> new file mode 100644
> >> index 00000000000..a8199c0b7ee
> >> --- /dev/null
> >> +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr126523.c
> >> @@ -0,0 +1,26 @@
> >> +/* { dg-do compile } */
> >> +/* { dg-options "-O1 -fdump-tree-optimized" } */
> >> +
> >> +typedef int si;
> >> +typedef unsigned ui;
> >> +
> >> +si f(si a)
> >> +{
> >> +    ui t = a;
> >> +    t = ~t;
> >> +    si a1 = t;
> >> +    return a1;
> >> +}
> >> +
> >> +si f1(si a)
> >> +{
> >> +    return ~a;
> >> +}
> >> +
> >> +/* If everything went as planned g()
> >> +   will reduce to 'return 1'.  */
> >> +int g(si a)
> >> +{
> >> +    return f(a) + f1(a) == (si)(2*(~a));
> >> +}
> >> +/* { dg-final { scan-tree-dump-times " return 1;" 1 "optimized" } } */
> >> --
> >> 2.43.0
> >>
>

Reply via email to