diff options
author | Arjun Shankar <arjun@redhat.com> | 2022-06-21 12:12:11 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2022-06-21 12:13:52 +0200 |
commit | ab981aab92cbc71918fbaadcf6fa64bdb2b69be7 (patch) | |
tree | f655a675752e9fd0e7a2c0b6f3d07fff26dcd8be | |
parent | a0c30fe3b888f20215f3e040d21b62b603804ca9 (diff) | |
download | gcc-ab981aab92cbc71918fbaadcf6fa64bdb2b69be7.zip gcc-ab981aab92cbc71918fbaadcf6fa64bdb2b69be7.tar.gz gcc-ab981aab92cbc71918fbaadcf6fa64bdb2b69be7.tar.bz2 |
match.pd: Remove "+ 0x80000000" in int comparisons [PR94899]
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/
PR tree-optimization/94899
* match.pd (X + C < Y + C -> (signed) X < (signed) Y, if C is
0x80000000): New simplification.
gcc/testsuite/
* gcc.dg/pr94899.c: New test.
-rw-r--r-- | gcc/match.pd | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr94899.c | 49 |
2 files changed, 62 insertions, 0 deletions
diff --git a/gcc/match.pd b/gcc/match.pd index a63b649..4a57089 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 0000000..9fad057 --- /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"} } */ |