public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Arjun Shankar <arjun@redhat.com>
To: GCC Patches <gcc-patches@gcc.gnu.org>
Cc: Arjun Shankar <arjun@redhat.com>,
	Richard Biener <richard.guenther@gmail.com>,
	Jakub Jelinek <jakub@redhat.com>
Subject: [PATCH v4] tree-optimization/94899: Remove "+ 0x80000000" in int comparisons
Date: Mon, 20 Jun 2022 16:23:33 +0200	[thread overview]
Message-ID: <20220620142333.33065-1-arjun@redhat.com> (raw)

Expressions of the form "X + CST < Y + CST" where:

* CST is an unsigned integer constant with only the MSB set, and
* X and Y's types have integer conversion ranks <= CST's

can be simplified to "(signed) X < (signed) Y".

This is because, assuming a 32-bit signed numbers,
(unsigned) INT_MIN + 0x80000000 is 0, and
(unsigned) INT_MAX + 0x80000000 is UINT_MAX.

i.e. the result increases monotonically with signed input.

This means:
((signed) X < (signed) Y) iff (X + 0x80000000 < Y + 0x80000000)

gcc/
        * match.pd (X + C < Y + C -> (signed) X < (signed) Y, if C is
        0x80000000): New simplification.
gcc/testsuite/
        * gcc.dg/pr94899.c: New test.
---
 gcc/match.pd                   | 13 +++++++++
 gcc/testsuite/gcc.dg/pr94899.c | 49 ++++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/pr94899.c
---
v3: https://gcc.gnu.org/pipermail/gcc-patches/2022-June/596785.html

Notes on v4, based on Richard and Jakub's review comments:

Richard wrote:

> It might be possible to test for zero + or - operations instead?

OK. That seems more fool-proof. I've made the change.

Jakub wrote:

> Can't one just omit the INTEGER_CST part on the second @0?

I hadn't thought of that. Done!

> As a follow-up, it might be useful to make it work for vector integral types
> too,
> typedef unsigned V __attribute__((vector_size (4 * sizeof (int))));
> #define M __INT_MAX__ + 1U
> V foo (V x, V y)
> {
>   return x + (V) { M, M, M, M } < y + (V) { M, M, M, M };
> }
> using uniform_integer_cst_p.

OK. This syntax is unfamiliar to me. I'll read a bit and then try to work on
a follow-up. Thanks!

diff --git a/gcc/match.pd b/gcc/match.pd
index a63b649841b..4a570894b2e 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2089,6 +2089,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
        && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
    (op @0 @1))))
+
+/* As a special case, X + C < Y + C is the same as (signed) X < (signed) Y
+   when C is an unsigned integer constant with only the MSB set, and X and
+   Y have types of equal or lower integer conversion rank than C's.  */
+(for op (lt le ge gt)
+ (simplify
+  (op (plus @1 INTEGER_CST@0) (plus @2 @0))
+  (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+       && TYPE_UNSIGNED (TREE_TYPE (@0))
+       && wi::only_sign_bit_p (wi::to_wide (@0)))
+   (with { tree stype = signed_type_for (TREE_TYPE (@0)); }
+    (op (convert:stype @1) (convert:stype @2))))))
+
 /* For equality and subtraction, this is also true with wrapping overflow.  */
 (for op (eq ne minus)
  (simplify
diff --git a/gcc/testsuite/gcc.dg/pr94899.c b/gcc/testsuite/gcc.dg/pr94899.c
new file mode 100644
index 00000000000..2fc7009a2e7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr94899.c
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+typedef __INT16_TYPE__ int16_t;
+typedef __INT32_TYPE__ int32_t;
+typedef __UINT16_TYPE__ uint16_t;
+typedef __UINT32_TYPE__ uint32_t;
+
+#define MAGIC (~ (uint32_t) 0 / 2 + 1)
+
+int
+f_i16_i16 (int16_t x, int16_t y)
+{
+  return x + MAGIC < y + MAGIC;
+}
+
+int
+f_i16_i32 (int16_t x, int32_t y)
+{
+  return x + MAGIC < y + MAGIC;
+}
+
+int
+f_i32_i32 (int32_t x, int32_t y)
+{
+  return x + MAGIC < y + MAGIC;
+}
+
+int
+f_u32_i32 (uint32_t x, int32_t y)
+{
+  return x + MAGIC < y + MAGIC;
+}
+
+int
+f_u32_u32 (uint32_t x, uint32_t y)
+{
+  return x + MAGIC < y + MAGIC;
+}
+
+int
+f_i32_i32_sub (int32_t x, int32_t y)
+{
+  return x - MAGIC < y - MAGIC;
+}
+
+/* The addition/subtraction of constants should be optimized away.  */
+/* { dg-final { scan-tree-dump-not "\\+" "optimized"} } */
+/* { dg-final { scan-tree-dump-not "\\-" "optimized"} } */
-- 
2.35.3


             reply	other threads:[~2022-06-20 14:23 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-20 14:23 Arjun Shankar [this message]
2022-06-21  8:01 ` Richard Biener

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220620142333.33065-1-arjun@redhat.com \
    --to=arjun@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    --cc=richard.guenther@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).