i386: Use bzhi for x & ((1 << y) - 1) or x & ((1U << y) - 1) [PR93346]
diff mbox series

Message ID 20200123075617.GU10088@tucnak
State New
Headers show
Series
  • i386: Use bzhi for x & ((1 << y) - 1) or x & ((1U << y) - 1) [PR93346]
Related show

Commit Message

Jakub Jelinek Jan. 23, 2020, 7:56 a.m. UTC
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  <jakub@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.


	Jakub

Comments

Uros Bizjak Jan. 23, 2020, 9:10 a.m. UTC | #1
On Thu, Jan 23, 2020 at 8:56 AM Jakub Jelinek <jakub@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  <jakub@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
>

Patch
diff mbox series

--- 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);
+}