Hello,just a little tweak to that transformation. There is some overlap between the 2 versions, but it seemed easier to handle the NOP case (including the case without convert and the vector case) separately from the narrowing / sign-extending scalar integer case.
At some point it would be good to have fold_negate_expr call generic_simplify so we could remove some transformations from fold-const.c.
Bootstrap+regtest on powerpc64le-unknown-linux-gnu. 2017-11-01 Marc Glisse <marc.gli...@inria.fr> gcc/ * match.pd (-(-A)): Rewrite. gcc/testsuite/ * gcc.dg/negneg.c: New file. -- Marc Glisse
Index: gcc/match.pd =================================================================== --- gcc/match.pd (revision 254289) +++ gcc/match.pd (working copy) @@ -1498,24 +1498,33 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (with { tree t1 = type; if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type) != TYPE_OVERFLOW_WRAPS (TREE_TYPE (@1))) t1 = TYPE_OVERFLOW_WRAPS (type) ? type : TREE_TYPE (@1); } (convert (plus (convert:t1 @0) (convert:t1 @1)))))) /* -(-A) -> A */ (simplify - (negate (convert? (negate @1))) - (if (tree_nop_conversion_p (type, TREE_TYPE (@1)) - && !TYPE_OVERFLOW_SANITIZED (type)) + (negate (convert (negate @1))) + (if (INTEGRAL_TYPE_P (type) + && (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@1)) + || (!TYPE_UNSIGNED (TREE_TYPE (@1)) + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@1)))) + && !TYPE_OVERFLOW_SANITIZED (type) + && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@1))) (convert @1))) + (simplify + (negate (nop_convert (negate @1))) + (if (!TYPE_OVERFLOW_SANITIZED (type) + && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@1))) + (view_convert @1))) /* We can't reassociate floating-point unless -fassociative-math or fixed-point plus or minus because of saturation to +-Inf. */ (if ((!FLOAT_TYPE_P (type) || flag_associative_math) && !FIXED_POINT_TYPE_P (type)) /* Match patterns that allow contracting a plus-minus pair irrespective of overflow issues. */ /* (A +- B) - A -> +- B */ /* (A +- B) -+ B -> A */ Index: gcc/testsuite/gcc.dg/negneg.c =================================================================== --- gcc/testsuite/gcc.dg/negneg.c (nonexistent) +++ gcc/testsuite/gcc.dg/negneg.c (working copy) @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O -frounding-math -fdump-tree-optimized-raw -Wno-psabi" } */ + +#define DEF(num, T1, T2) T2 f##num(T1 x) { \ + T1 y = -x; \ + T2 z = (T2)y; \ + return -z; \ +} +DEF(0, int, long long) +DEF(1, int, unsigned long long) +DEF(2, long long, int) +DEF(3, unsigned long long, int) +DEF(4, long long, unsigned) +DEF(5, unsigned long long, unsigned) +//DEF(6, float, double) +double f6(float x){return -(double)(-x);} + +typedef int vec __attribute__((vector_size(4*sizeof(int)))); +typedef unsigned uvec __attribute__((vector_size(4*sizeof(int)))); +void h(vec*p,uvec*q){ + *q=-(uvec)(-*p); +} + +/* { dg-final { scan-tree-dump-not "negate_expr" "optimized"} } */