On Thu, Jan 23, 2020 at 8:56 AM Jakub Jelinek <ja...@redhat.com> wrote: > > Hi! > > The bzhi patterns are quite complicated because they need to accurately > describe the behavior of the instruction for all input values. > The following patterns are simple and make bzhi recognizable even for > cases where not all input values are valid, because the user used > a shift, in which case the low 8 bit of the last operand need to be in > between 0 and precision-1. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 2020-01-23 Jakub Jelinek <ja...@redhat.com> > > PR target/93346 > * config/i386/i386.md (*bmi2_bzhi_<mode>3_2, *bmi2_bzhi_<mode>3_3): > New define_insn patterns. > > * gcc.target/i386/pr93346.c: New test.
We could also define zero_extended version for x86_64, but I don't think it is worth complication. OK. Thanks, Uros. > --- gcc/config/i386/i386.md.jj 2020-01-22 09:49:27.379413302 +0100 > +++ gcc/config/i386/i386.md 2020-01-22 13:34:35.226270365 +0100 > @@ -14304,6 +14304,35 @@ (define_insn "*bmi2_bzhi_<mode>3_1_ccz" > (set_attr "prefix" "vex") > (set_attr "mode" "<MODE>")]) > > +(define_insn "*bmi2_bzhi_<mode>3_2" > + [(set (match_operand:SWI48 0 "register_operand" "=r") > + (and:SWI48 > + (plus:SWI48 > + (ashift:SWI48 (const_int 1) > + (match_operand:QI 2 "register_operand" "r")) > + (const_int -1)) > + (match_operand:SWI48 1 "nonimmediate_operand" "rm"))) > + (clobber (reg:CC FLAGS_REG))] > + "TARGET_BMI2" > + "bzhi\t{%<k>2, %1, %0|%0, %1, %<k>2}" > + [(set_attr "type" "bitmanip") > + (set_attr "prefix" "vex") > + (set_attr "mode" "<MODE>")]) > + > +(define_insn "*bmi2_bzhi_<mode>3_3" > + [(set (match_operand:SWI48 0 "register_operand" "=r") > + (and:SWI48 > + (not:SWI48 > + (ashift:SWI48 (const_int -1) > + (match_operand:QI 2 "register_operand" "r"))) > + (match_operand:SWI48 1 "nonimmediate_operand" "rm"))) > + (clobber (reg:CC FLAGS_REG))] > + "TARGET_BMI2" > + "bzhi\t{%<k>2, %1, %0|%0, %1, %<k>2}" > + [(set_attr "type" "bitmanip") > + (set_attr "prefix" "vex") > + (set_attr "mode" "<MODE>")]) > + > (define_insn "bmi2_pdep_<mode>3" > [(set (match_operand:SWI48 0 "register_operand" "=r") > (unspec:SWI48 [(match_operand:SWI48 1 "register_operand" "r") > --- gcc/testsuite/gcc.target/i386/pr93346.c.jj 2020-01-22 13:42:27.907101420 > +0100 > +++ gcc/testsuite/gcc.target/i386/pr93346.c 2020-01-22 13:42:09.330383163 > +0100 > @@ -0,0 +1,76 @@ > +/* PR target/93346 */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -mbmi2" } */ > +/* { dg-final { scan-assembler-times "\tbzhi\t" 12 } } */ > + > +unsigned int > +f1 (unsigned int x, unsigned int y) > +{ > + return x & ((1 << y) - 1); > +} > + > +unsigned int > +f2 (unsigned int x, unsigned int y) > +{ > + return x & ((1U << y) - 1); > +} > + > +int > +f3 (int x, unsigned int y) > +{ > + return x & ((1 << y) - 1); > +} > + > +unsigned long > +f4 (unsigned long x, unsigned int y) > +{ > + return x & ((1L << y) - 1); > +} > + > +unsigned long > +f5 (unsigned long x, unsigned int y) > +{ > + return x & ((1UL << y) - 1); > +} > + > +long > +f6 (long x, unsigned int y) > +{ > + return x & ((1L << y) - 1); > +} > + > +unsigned int > +f7 (unsigned int x, int y) > +{ > + return x & ((1 << y) - 1); > +} > + > +unsigned int > +f8 (unsigned int x, int y) > +{ > + return x & ((1U << y) - 1); > +} > + > +int > +f9 (int x, int y) > +{ > + return x & ((1 << y) - 1); > +} > + > +unsigned long > +f10 (unsigned long x, int y) > +{ > + return x & ((1L << y) - 1); > +} > + > +unsigned long > +f11 (unsigned long x, int y) > +{ > + return x & ((1UL << y) - 1); > +} > + > +long > +f12 (long x, int y) > +{ > + return x & ((1L << y) - 1); > +} > > Jakub >