]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: re PR target/65368 (_bzhi_u32 intrinsic generates incorrect code when ...
authorJakub Jelinek <jakub@redhat.com>
Wed, 3 Jun 2015 21:34:36 +0000 (23:34 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 3 Jun 2015 21:34:36 +0000 (23:34 +0200)
Backported from mainline
2015-03-10  Jakub Jelinek  <jakub@redhat.com>

PR target/65368
* config/i386/i386.md (bmi2_bzhi_<mode>3): Removed define_insn,
new define_expand.
(*bmi2_bzhi_<mode>3, *bmi2_bzhi_<mode>3_1): New define_insns.

* gcc.target/i386/bmi2-bzhi-2.c: New test.

From-SVN: r224103

gcc/ChangeLog
gcc/config/i386/i386.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/bmi2-bzhi-2.c [new file with mode: 0644]

index 5e502416bddd27e6795daf596e001e8d557dc36d..bce34d61075ed7c811afa5c03e7dc15348a46f01 100644 (file)
@@ -1,6 +1,13 @@
 2015-06-03  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
+       2015-03-10  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/65368
+       * config/i386/i386.md (bmi2_bzhi_<mode>3): Removed define_insn,
+       new define_expand.
+       (*bmi2_bzhi_<mode>3, *bmi2_bzhi_<mode>3_1): New define_insns.
+
        2015-02-18  Jakub Jelinek  <jakub@redhat.com>
 
        PR gcov-profile/64634
index 372ae63f03d4c21585d6a18ac17e3cf691cfa19c..c08a2245dd126c2a84eeba442f7b7bf912f40d78 100644 (file)
    (set_attr "mode" "<MODE>")])
 
 ;; BMI2 instructions.
-(define_insn "bmi2_bzhi_<mode>3"
+(define_expand "bmi2_bzhi_<mode>3"
+  [(parallel
+    [(set (match_operand:SWI48 0 "register_operand")
+         (zero_extract:SWI48
+           (match_operand:SWI48 1 "nonimmediate_operand")
+           (umin:SWI48
+             (and:SWI48 (match_operand:SWI48 2 "register_operand")
+                        (const_int 255))
+             (match_dup 3))
+           (const_int 0)))
+     (clobber (reg:CC FLAGS_REG))])]
+  "TARGET_BMI2"
+  "operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode));")
+
+(define_insn "*bmi2_bzhi_<mode>3"
   [(set (match_operand:SWI48 0 "register_operand" "=r")
-       (and:SWI48 (lshiftrt:SWI48 (const_int -1)
-                                  (match_operand:SWI48 2 "register_operand" "r"))
-                  (match_operand:SWI48 1 "nonimmediate_operand" "rm")))
+       (zero_extract:SWI48
+         (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+         (umin:SWI48
+           (and:SWI48 (match_operand:SWI48 2 "register_operand" "r")
+                      (const_int 255))
+           (match_operand:SWI48 3 "const_int_operand" "n"))
+         (const_int 0)))
    (clobber (reg:CC FLAGS_REG))]
-  "TARGET_BMI2"
+  "TARGET_BMI2 && INTVAL (operands[3]) == GET_MODE_BITSIZE (<MODE>mode)"
   "bzhi\t{%2, %1, %0|%0, %1, %2}"
   [(set_attr "type" "bitmanip")
    (set_attr "prefix" "vex")
    (set_attr "mode" "<MODE>")])
 
+(define_mode_attr k [(SI "k") (DI "q")])
+(define_insn "*bmi2_bzhi_<mode>3_1"
+  [(set (match_operand:SWI48 0 "register_operand" "=r")
+       (zero_extract:SWI48
+         (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+         (umin:SWI48
+           (zero_extend:SWI48 (match_operand:QI 2 "register_operand" "r"))
+           (match_operand:SWI48 3 "const_int_operand" "n"))
+         (const_int 0)))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_BMI2 && INTVAL (operands[3]) == GET_MODE_BITSIZE (<MODE>mode)"
+  "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 132c0f216a3ac7d43c902431567f6f0dc1bd13c0..2f9244416790b4d5f88a02bd5f3691d98392b965 100644 (file)
@@ -1,6 +1,11 @@
 2015-06-03  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
+       2015-03-10  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/65368
+       * gcc.target/i386/bmi2-bzhi-2.c: New test.
+
        2015-02-18  Jakub Jelinek  <jakub@redhat.com>
 
        PR gcov-profile/64634
diff --git a/gcc/testsuite/gcc.target/i386/bmi2-bzhi-2.c b/gcc/testsuite/gcc.target/i386/bmi2-bzhi-2.c
new file mode 100644 (file)
index 0000000..34579d5
--- /dev/null
@@ -0,0 +1,67 @@
+/* PR target/65368 */
+/* { dg-do assemble { target bmi2 } } */
+/* { dg-options "-O2 -mbmi2" } */
+
+#include <x86intrin.h>
+#include "bmi2-check.h"
+
+unsigned int a;
+unsigned long long b;
+
+#define A __attribute__((noinline, noclone))
+
+A unsigned int f1 (void) { return _bzhi_u32 (a, 0); }
+A unsigned int f2 (unsigned int x) { return _bzhi_u32 (x, 0); }
+A unsigned int f3 (void) { return _bzhi_u32 (a, 5); }
+A unsigned int f4 (unsigned int x) { return _bzhi_u32 (x, 5); }
+A unsigned int f5 (void) { return _bzhi_u32 (a, 31); }
+A unsigned int f6 (unsigned int x) { return _bzhi_u32 (x, 31); }
+A unsigned int f7 (void) { return _bzhi_u32 (a, 32); }
+A unsigned int f8 (unsigned int x) { return _bzhi_u32 (x, 32); }
+A unsigned int f9 (void) { return _bzhi_u32 (a, 37); }
+A unsigned int f10 (unsigned int x) { return _bzhi_u32 (x, 37); }
+A unsigned int f11 (void) { return _bzhi_u32 (a, 257); }
+A unsigned int f12 (unsigned int x) { return _bzhi_u32 (x, 257); }
+A unsigned int f13 (void) { return _bzhi_u32 (a, 289); }
+A unsigned int f14 (unsigned int x) { return _bzhi_u32 (x, 289); }
+#ifdef __x86_64__
+A unsigned long long f21 (void) { return _bzhi_u64 (b, 0); }
+A unsigned long long f22 (unsigned long long x) { return _bzhi_u64 (x, 0); }
+A unsigned long long f23 (void) { return _bzhi_u64 (b, 5); }
+A unsigned long long f24 (unsigned long long x) { return _bzhi_u64 (x, 5); }
+A unsigned long long f25 (void) { return _bzhi_u64 (b, 63); }
+A unsigned long long f26 (unsigned long long x) { return _bzhi_u64 (x, 63); }
+A unsigned long long f27 (void) { return _bzhi_u64 (b, 64); }
+A unsigned long long f28 (unsigned long long x) { return _bzhi_u64 (x, 64); }
+A unsigned long long f29 (void) { return _bzhi_u64 (b, 69); }
+A unsigned long long f30 (unsigned long long x) { return _bzhi_u64 (x, 69); }
+A unsigned long long f31 (void) { return _bzhi_u64 (b, 257); }
+A unsigned long long f32 (unsigned long long x) { return _bzhi_u64 (x, 257); }
+A unsigned long long f33 (void) { return _bzhi_u64 (b, 321); }
+A unsigned long long f34 (unsigned long long x) { return _bzhi_u64 (x, 321); }
+#endif
+
+static void
+bmi2_test ()
+{
+  a = -1U;
+  b = -1ULL;
+  if (f1 () != 0 || f2 (-1U) != 0
+      || f3 () != 0x1f || f4 (-1U) != 0x1f
+      || f5 () != 0x7fffffffU || f6 (-1U) != 0x7fffffffU
+      || f7 () != -1U || f8 (-1U) != -1U
+      || f9 () != -1U || f10 (-1U) != -1U
+      || f11 () != 1 || f12 (-1U) != 1
+      || f13 () != -1U || f14 (-1U) != -1U)
+    abort ();
+#ifdef __x86_64__
+  if (f21 () != 0 || f22 (-1ULL) != 0
+      || f23 () != 0x1f || f24 (-1ULL) != 0x1f
+      || f25 () != 0x7fffffffffffffffULL || f26 (-1ULL) != 0x7fffffffffffffffULL
+      || f27 () != -1ULL || f28 (-1ULL) != -1ULL
+      || f29 () != -1ULL || f30 (-1ULL) != -1ULL
+      || f31 () != 1 || f32 (-1ULL) != 1
+      || f33 () != -1ULL || f34 (-1ULL) != -1ULL)
+    abort ();
+#endif
+}