From 6b30e838cd7f8dc66aa69b76c8622bf375220e95 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 12 Oct 2018 19:31:33 +0200 Subject: [PATCH] backport: re PR middle-end/86627 (Signed 128-bit division by 2 no longer expanded to RTL) Backported from mainline 2018-07-24 Jakub Jelinek 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: r265119 --- gcc/ChangeLog | 7 +++++++ gcc/expmed.c | 9 +++++--- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.target/i386/pr86627.c | 28 +++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr86627.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0af69b9be55d..c09e3c77a846 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,6 +1,13 @@ 2018-10-12 Jakub Jelinek Backported from mainline + 2018-07-24 Jakub Jelinek + + 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-17 Jakub Jelinek PR middle-end/86542 diff --git a/gcc/expmed.c b/gcc/expmed.c index 8e069455bc2b..2b42deedb65d 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -4345,6 +4345,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. */ @@ -4388,9 +4393,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode, compute_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) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 29b048361a5f..986f6b6fdd5f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,11 @@ 2018-10-12 Jakub Jelinek Backported from mainline + 2018-07-24 Jakub Jelinek + + PR middle-end/86627 + * gcc.target/i386/pr86627.c: New test. + 2018-07-16 Jakub Jelinek PR c++/3698 diff --git a/gcc/testsuite/gcc.target/i386/pr86627.c b/gcc/testsuite/gcc.target/i386/pr86627.c new file mode 100644 index 000000000000..5aefbed0a0b9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr86627.c @@ -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; +} -- 2.47.2