mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-24 07:19:16 +08:00
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.
This commit is contained in:
parent
a0c30fe3b8
commit
ab981aab92
13
gcc/match.pd
13
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
|
||||
|
49
gcc/testsuite/gcc.dg/pr94899.c
Normal file
49
gcc/testsuite/gcc.dg/pr94899.c
Normal file
@ -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"} } */
|
Loading…
Reference in New Issue
Block a user