re PR middle-end/86627 (Signed 128-bit division by 2 no longer expanded to RTL)
authorJakub Jelinek <jakub@redhat.com>
Tue, 24 Jul 2018 14:23:18 +0000 (16:23 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 24 Jul 2018 14:23:18 +0000 (16:23 +0200)
PR middle-end/86627
* expmed.c (expand_divmod): Punt if d == HOST_WIDE_INT_MIN
and size > HOST_BITS_PER_WIDE_INT.  For size > HOST_BITS_PER_WIDE_INT
and abs_d == d, do the power of two handling if profitable.

* gcc.target/i386/pr86627.c: New test.

From-SVN: r262948

gcc/ChangeLog
gcc/expmed.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr86627.c [new file with mode: 0644]

index ff8ed780cf99ae59059e0bc8734027a06da1a411..c7b921b48359a69a09fbc672c9b071be8479980d 100644 (file)
@@ -1,3 +1,10 @@
+2018-07-24  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/86627
+       * expmed.c (expand_divmod): Punt if d == HOST_WIDE_INT_MIN
+       and size > HOST_BITS_PER_WIDE_INT.  For size > HOST_BITS_PER_WIDE_INT
+       and abs_d == d, do the power of two handling if profitable.
+
 2018-07-24  Richard Biener  <rguenther@suse.de>
 
        * match.pd: Add BIT_FIELD_REF canonicalizations.
index f114eb45e01fe57690b505af559571823819e2b1..101e7b88107702b06276cfcd94319d6b79751368 100644 (file)
@@ -4480,6 +4480,11 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
                HOST_WIDE_INT d = INTVAL (op1);
                unsigned HOST_WIDE_INT abs_d;
 
+               /* Not prepared to handle division/remainder by
+                  0xffffffffffffffff8000000000000000 etc.  */
+               if (d == HOST_WIDE_INT_MIN && size > HOST_BITS_PER_WIDE_INT)
+                 break;
+
                /* Since d might be INT_MIN, we have to cast to
                   unsigned HOST_WIDE_INT before negating to avoid
                   undefined signed overflow.  */
@@ -4522,9 +4527,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
                             || (optab_handler (sdivmod_optab, int_mode)
                                 != CODE_FOR_nothing)))
                  ;
-               else if (EXACT_POWER_OF_2_OR_ZERO_P (abs_d)
-                        && (size <= HOST_BITS_PER_WIDE_INT
-                            || abs_d != (unsigned HOST_WIDE_INT) d))
+               else if (EXACT_POWER_OF_2_OR_ZERO_P (abs_d))
                  {
                    if (rem_flag)
                      {
index a723a528ea610b20aeb80c86bb1a2291bb1ebf17..ca4d0bc8f35f5146ca2e99a4ab6d0853ced7985b 100644 (file)
@@ -1,5 +1,8 @@
 2018-07-24  Jakub Jelinek  <jakub@redhat.com>
 
+       PR middle-end/86627
+       * gcc.target/i386/pr86627.c: New test.
+
        PR testsuite/86649
        * g++.dg/tree-ssa-/pr19476-1.C: Check dom2 dump instead of ccp1.
        * g++.dg/tree-ssa-/pr19476-5.C: Likewise.
diff --git a/gcc/testsuite/gcc.target/i386/pr86627.c b/gcc/testsuite/gcc.target/i386/pr86627.c
new file mode 100644 (file)
index 0000000..5aefbed
--- /dev/null
@@ -0,0 +1,28 @@
+/* PR middle-end/86627 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "call\[^\n\r]*__divti3" } } */
+
+__int128_t
+f1 (__int128_t a)
+{
+  return a / 2;
+}
+
+__int128_t
+f2 (__int128_t a)
+{
+  return a / -2;
+}
+
+__int128_t
+f3 (__int128_t a)
+{
+  return a / 0x4000000000000000LL;
+}
+
+__int128_t
+f4 (__int128_t a)
+{
+  return a / -0x4000000000000000LL;
+}