i386: Use bzhi for x & ((1 << y) - 1) or x & ((1U << y) - 1) [PR93346]
authorJakub Jelinek <jakub@redhat.com>
Thu, 23 Jan 2020 11:39:13 +0000 (12:39 +0100)
committerJakub Jelinek <jakub@redhat.com>
Thu, 23 Jan 2020 11:39:13 +0000 (12:39 +0100)
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.

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.

gcc/ChangeLog
gcc/config/i386/i386.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr93346.c [new file with mode: 0644]

index d634b378afc487fcb8237675d609d1b45f95f1eb..e62d3c02331194ed1983626c7f5d239af839b952 100644 (file)
@@ -1,3 +1,9 @@
+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.
+
 2020-01-23  Richard Sandiford  <richard.sandiford@arm.com>
 
        * doc/sourcebuild.texi (check-function-bodies): Add an
index 6c674aaea5bf80a6e5618e05686ac7ccef8ca905..b5b53bbcfaa7580ca0435f920dcec5ab1456dfc4 100644 (file)
    (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")
index 22c172f299bb95c063d74347007db7c9c072ff5c..dbcd8dd83902b9d25d8af958c43b74f29f9e3ade 100644 (file)
@@ -1,3 +1,8 @@
+2020-01-23  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/93346
+       * gcc.target/i386/pr93346.c: New test.
+
 2020-01-23  Martin Sebor  <msebor@redhat.com>
 
        PR c/84919
diff --git a/gcc/testsuite/gcc.target/i386/pr93346.c b/gcc/testsuite/gcc.target/i386/pr93346.c
new file mode 100644 (file)
index 0000000..bad5c48
--- /dev/null
@@ -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);
+}