match: Fix the max<a,b>==0 pattern for pointers [PR117646]

For pointers I forgot that BIT_IOR_EXPR is not valid so when
I added the pattern to convert `max<a,b> != 0` (r15-5356), GCC
would start to ICEing saying pointer types were not valid for
BIT_IOR_EXPR.
This fixes the problem by casting to the unsigned type of the
inner type. There was another way of fixing this to handling it
as `a == 0 & b == 0` but both match and reassoication (for pointers)
will then convert it back into the form I am creating here so
let's just use that form instead.

Bootstrapped and tested on x86_64-linux-gnu.

	PR tree-optimization/117646

gcc/ChangeLog:

	* match.pd (`max<a,b>==0`): Add casts to `unsigned type`.

gcc/testsuite/ChangeLog:

	* gcc.dg/torture/minmaxneeqptr-1.c: New test.

Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
This commit is contained in:
Andrew Pinski 2024-11-17 20:21:58 -08:00
parent dffc37dead
commit 45a3277149
2 changed files with 25 additions and 2 deletions

View File

@ -4799,9 +4799,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
MAX (A, B) != 0 -> (A|B) != 0 iff unsigned. */ MAX (A, B) != 0 -> (A|B) != 0 iff unsigned. */
(for cmp (eq ne) (for cmp (eq ne)
(simplify (simplify
(cmp (max @0 @1) integer_zerop@2) (cmp (max @0 @1) integer_zerop)
(if (TYPE_UNSIGNED (TREE_TYPE (@0))) (if (TYPE_UNSIGNED (TREE_TYPE (@0)))
(cmp (bit_ior @0 @1) @2)))) (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
(cmp (bit_ior (convert:utype @0) (convert:utype @1))
{ build_zero_cst (utype); } )))))
/* Undo fancy ways of writing max/min or other ?: expressions, like /* Undo fancy ways of writing max/min or other ?: expressions, like
a - ((a - b) & -(a < b)) and a - (a - b) * (a < b) into (a < b) ? b : a. a - ((a - b) & -(a < b)) and a - (a - b) * (a < b) into (a < b) ? b : a.

View File

@ -0,0 +1,21 @@
/* { dg-do compile } */
/* PR tree-optimization/117646 */
int maxeq(char *a, char *b) {
char *p = a < b ? b : a;
return p == (void*)0;
}
int maxne(char *a, char *b) {
char *p = a < b ? b : a;
return p == (void*)0;
}
int mineq(char *a, char *b) {
char *p = a > b ? b : a;
return p == (void*)0;
}
int minne(char *a, char *b) {
char *p = a > b ? b : a;
return p == (void*)0;
}