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
>

Reply via email to