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 > >> > >> >