re PR target/82498 (Missed optimization for x86 rotate instruction)
authorJakub Jelinek <jakub@redhat.com>
Fri, 13 Oct 2017 07:17:06 +0000 (09:17 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 13 Oct 2017 07:17:06 +0000 (09:17 +0200)
PR target/82498
* config/i386/ia32intrin.h (__rold, __rord, __rolq, __rorq): Allow
any values of __C while still being pattern recognizable as a simple
rotate instruction.

* gcc.dg/ubsan/pr82498.c: New test.

From-SVN: r253708

gcc/ChangeLog
gcc/config/i386/ia32intrin.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/ubsan/pr82498.c [new file with mode: 0644]

index bff2a6fe00dc71b4e7e0b55834958a60c5e9db64..58923e8835a428d42061a8e8bfc9387b319653b5 100644 (file)
@@ -1,3 +1,10 @@
+2017-10-13  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/82498
+       * config/i386/ia32intrin.h (__rold, __rord, __rolq, __rorq): Allow
+       any values of __C while still being pattern recognizable as a simple
+       rotate instruction.
+
 2017-10-13  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/82451
index 5f954fce85eec92ee87ced61c6708853e1992579..1f4e484d55b8215a695223a6a5501abc433fdae9 100644 (file)
@@ -147,7 +147,8 @@ extern __inline unsigned int
 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
 __rold (unsigned int __X, int __C)
 {
-  return (__X << __C) | (__X >> (32 - __C));
+  __C &= 31;
+  return (__X << __C) | (__X >> (-__C & 31));
 }
 
 /* 8bit ror */
@@ -171,7 +172,8 @@ extern __inline unsigned int
 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
 __rord (unsigned int __X, int __C)
 {
-  return (__X >> __C) | (__X << (32 - __C));
+  __C &= 31;
+  return (__X >> __C) | (__X << (-__C & 31));
 }
 
 /* Pause */
@@ -239,7 +241,8 @@ extern __inline unsigned long long
 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
 __rolq (unsigned long long __X, int __C)
 {
-  return (__X << __C) | (__X >> (64 - __C));
+  __C &= 63;
+  return (__X << __C) | (__X >> (-__C & 63));
 }
 
 /* 64bit ror */
@@ -247,7 +250,8 @@ extern __inline unsigned long long
 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
 __rorq (unsigned long long __X, int __C)
 {
-  return (__X >> __C) | (__X << (64 - __C));
+  __C &= 63;
+  return (__X >> __C) | (__X << (-__C & 63));
 }
 
 /* Read flags register */
index a830453eabdf646605119acc34344814d7be8ed3..0a8246fd980f54f5046280c5a9df441b6f85d3f0 100644 (file)
@@ -1,3 +1,8 @@
+2017-10-13  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/82498
+       * gcc.dg/ubsan/pr82498.c: New test.
+
 2017-10-13  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/82451
diff --git a/gcc/testsuite/gcc.dg/ubsan/pr82498.c b/gcc/testsuite/gcc.dg/ubsan/pr82498.c
new file mode 100644 (file)
index 0000000..1d093a0
--- /dev/null
@@ -0,0 +1,159 @@
+/* PR target/82498 */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=undefined" } */
+
+#include <x86intrin.h>
+
+volatile unsigned int a;
+volatile unsigned long long b;
+volatile int c;
+
+int
+main ()
+{
+  a = 0x12345678U;
+  a = __rold (a, 0);
+  if (a != 0x12345678U)
+    __builtin_abort ();
+  a = __rold (a, 32);
+  if (a != 0x12345678U)
+    __builtin_abort ();
+  a = __rold (a, -32);
+  if (a != 0x12345678U)
+    __builtin_abort ();
+  a = __rold (a, 37);
+  if (a != 0x468acf02U)
+    __builtin_abort ();
+  a = __rold (a, -5);
+  if (a != 0x12345678U)
+    __builtin_abort ();
+  a = __rord (a, 0);
+  if (a != 0x12345678U)
+    __builtin_abort ();
+  a = __rord (a, 32);
+  if (a != 0x12345678U)
+    __builtin_abort ();
+  a = __rord (a, -32);
+  if (a != 0x12345678U)
+    __builtin_abort ();
+  a = __rord (a, -37);
+  if (a != 0x468acf02U)
+    __builtin_abort ();
+  a = __rord (a, 5);
+  if (a != 0x12345678U)
+    __builtin_abort ();
+  c = 0;
+  a = __rold (a, c);
+  if (a != 0x12345678U)
+    __builtin_abort ();
+  c = 32;
+  a = __rold (a, c);
+  if (a != 0x12345678U)
+    __builtin_abort ();
+  c = -32;
+  a = __rold (a, c);
+  if (a != 0x12345678U)
+    __builtin_abort ();
+  c = 37;
+  a = __rold (a, c);
+  if (a != 0x468acf02U)
+    __builtin_abort ();
+  c = -5;
+  a = __rold (a, c);
+  if (a != 0x12345678U)
+    __builtin_abort ();
+  c = 0;
+  a = __rord (a, c);
+  if (a != 0x12345678U)
+    __builtin_abort ();
+  c = 32;
+  a = __rord (a, c);
+  if (a != 0x12345678U)
+    __builtin_abort ();
+  c = -32;
+  a = __rord (a, c);
+  if (a != 0x12345678U)
+    __builtin_abort ();
+  c = -37;
+  a = __rord (a, c);
+  if (a != 0x468acf02U)
+    __builtin_abort ();
+  c = 5;
+  a = __rord (a, c);
+  if (a != 0x12345678U)
+    __builtin_abort ();
+#ifdef __x86_64__
+  b = 0x123456789abcdef1ULL;
+  b = __rolq (b, 0);
+  if (b != 0x123456789abcdef1ULL)
+    __builtin_abort ();
+  b = __rolq (b, 64);
+  if (b != 0x123456789abcdef1ULL)
+    __builtin_abort ();
+  b = __rolq (b, -64);
+  if (b != 0x123456789abcdef1ULL)
+    __builtin_abort ();
+  b = __rolq (b, 69);
+  if (b != 0x468acf13579bde22ULL)
+    __builtin_abort ();
+  b = __rolq (b, -5);
+  if (b != 0x123456789abcdef1ULL)
+    __builtin_abort ();
+  b = __rorq (b, 0);
+  if (b != 0x123456789abcdef1ULL)
+    __builtin_abort ();
+  b = __rorq (b, 64);
+  if (b != 0x123456789abcdef1ULL)
+    __builtin_abort ();
+  b = __rorq (b, -64);
+  if (b != 0x123456789abcdef1ULL)
+    __builtin_abort ();
+  b = __rorq (b, -69);
+  if (b != 0x468acf13579bde22ULL)
+    __builtin_abort ();
+  b = __rorq (b, 5);
+  if (b != 0x123456789abcdef1ULL)
+    __builtin_abort ();
+  c = 0;
+  b = __rolq (b, c);
+  if (b != 0x123456789abcdef1ULL)
+    __builtin_abort ();
+  c = 64;
+  b = __rolq (b, c);
+  if (b != 0x123456789abcdef1ULL)
+    __builtin_abort ();
+  c = -64;
+  b = __rolq (b, c);
+  if (b != 0x123456789abcdef1ULL)
+    __builtin_abort ();
+  c = 69;
+  b = __rolq (b, c);
+  if (b != 0x468acf13579bde22ULL)
+    __builtin_abort ();
+  c = -5;
+  b = __rolq (b, c);
+  if (b != 0x123456789abcdef1ULL)
+    __builtin_abort ();
+  c = 0;
+  b = __rorq (b, c);
+  if (b != 0x123456789abcdef1ULL)
+    __builtin_abort ();
+  c = 64;
+  b = __rorq (b, c);
+  if (b != 0x123456789abcdef1ULL)
+    __builtin_abort ();
+  c = -64;
+  b = __rorq (b, c);
+  if (b != 0x123456789abcdef1ULL)
+    __builtin_abort ();
+  c = -69;
+  b = __rorq (b, c);
+  if (b != 0x468acf13579bde22ULL)
+    __builtin_abort ();
+  c = 5;
+  b = __rorq (b, c);
+  if (b != 0x123456789abcdef1ULL)
+    __builtin_abort ();
+#endif
+  return 0;
+}