On Wed, Jun 5, 2019 at 2:09 PM Martin Liška <mli...@suse.cz> wrote:
>
> On 6/5/19 1:13 PM, Richard Biener wrote:
> > On Wed, Jun 5, 2019 at 12:56 PM Martin Liška <mli...@suse.cz> wrote:
> >>
> >> Hi.
> >>
> >> I'm suggesting one multiplication simplification pattern.
> >>
> >> Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
> >>
> >> Ready to be installed?
> >
> > +  (if (INTEGRAL_TYPE_P (type)
> > +       && wi::eq_p (get_nonzero_bits (@1), wi::one (TYPE_PRECISION (type)))
> > +       && wi::eq_p (get_nonzero_bits (@2), wi::one (TYPE_PRECISION 
> > (type))))
> >
> >   && wi::eq_p (wi::bit_or (get_nonzero_bits (@1), get_nonzero_bits  (@2)), 
> > 1))
> >
> > (I think literal 1 still works)?
>
> Yep, I can confirm that.
>
> > How does it behave for  singed/unsigned 1-bit
> > bitfields?  A gimple testcase maybe necessary to see.
>
> Can we really have a mult that will have a bitfield type?

As said you probably need a GIMPLE testcase to avoid
promoting to int.  Oh, and that doesn't work yet because
we cannot "parse" bit-precision types for temporaries.

struct X { int a : 1; int b : 1; };

int foo (struct X *p)
{
  return p->a;
}

produces

int __GIMPLE (ssa)
foo (struct X * p)
{
  int D_1913;
  <unnamed-signed:1> _1;
...

we have similar issues with dumping of vector types but
there at least one can use a typedef and manual editing.
For bit-precision types we need to invent a "C" extension
(thus also for vectors).

Anyway...

> $ cat gcc/testsuite/gcc.dg/pr87954-2.c
> #define __GFP_DMA 1u
> #define __GFP_RECLAIM 0x10u
>
> struct bt
> {
>   unsigned int v:1;
> };
>
> unsigned int
> imul(unsigned int flags)
> {
>   struct bt is_dma, is_rec;
>
>   is_dma.v = !!(flags & __GFP_DMA);
>   is_rec.v = !!(flags & __GFP_RECLAIM);
>
>   return is_rec.v * !is_dma.v;
> }
>
> $ ./xgcc -B. /home/marxin/Programming/gcc/gcc/testsuite/gcc.dg/pr87954-2.c 
> -fdump-tree-optimized=/dev/stdout -O2
>
> ;; Function imul (imul, funcdef_no=0, decl_uid=1909, cgraph_uid=1, 
> symbol_order=0)
>
> imul (unsigned int flags)
> {
>   struct bt is_dma;
>   _Bool _1;
>   unsigned int _2;
>   _Bool _3;
>   unsigned char _4;
>   _Bool _6;
>   unsigned int _9;
>   <unnamed-unsigned:1> _11;
>   unsigned char _14;
>
>   <bb 2> [local count: 1073741824]:
>   _1 = (_Bool) flags_7(D);
>   _2 = flags_7(D) & 16;
>   _3 = _2 != 0;
>   is_dma.v = _1;
>   _4 = BIT_FIELD_REF <is_dma, 8, 0>;
>   _14 = ~_4;
>   _6 = (_Bool) _14;
>   _11 = _3 & _6;
>   _9 = (unsigned int) _11;
>   is_dma ={v} {CLOBBER};
>   return _9;
> }
>
> >
> > Does this mean we want to turn plus into bit_ior when
> > get_nonzero_bits() & get_nonzero_bits() is zero?
>
> That's quite interesting transformation, I'll add it as a follow up patch.

I was just curious - maybe we should do the reverse instead?
For mult vs. bit-and I think the latter will be "faster" (well, probably not
even that...).  But for plus vs or?


> >
> > X * [0, 1] -> X & sign-extend-from-bit-1 also works I guess, but 
> > multiplication
> > looks more canonical.
> Ok here.
>
> Martin
>
> >
> > Thanks,
> > Richard.
> >
> >> Thanks,
> >> Martin
> >>
> >> gcc/ChangeLog:
> >>
> >> 2019-06-05  Martin Liska  <mli...@suse.cz>
> >>
> >>         PR tree-optimization/87954
> >>         * match.pd: Simplify mult where both arguments are 0 or 1.
> >>
> >> gcc/testsuite/ChangeLog:
> >>
> >> 2019-06-05  Martin Liska  <mli...@suse.cz>
> >>
> >>         PR tree-optimization/87954
> >>         * gcc.dg/pr87954.c: New test.
> >> ---
> >>  gcc/match.pd                   |  8 ++++++++
> >>  gcc/testsuite/gcc.dg/pr87954.c | 21 +++++++++++++++++++++
> >>  2 files changed, 29 insertions(+)
> >>  create mode 100644 gcc/testsuite/gcc.dg/pr87954.c
> >>
> >>
>

Reply via email to