@@ -959,6 +959,17 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
#endif
))))
+/* (nop_outer_cast)-(inner_cast)var -> -(outer_cast)(var)
+ if var is smaller in precision.
+ This is always safe for both doing the negative in signed or unsigned
+ as the value for undefined will not show up. */
+(simplify
+ (convert (negate:s@1 (convert:s @0)))
+ (if (INTEGRAL_TYPE_P (type)
+ && tree_nop_conversion_p (type, TREE_TYPE (@1))
+ && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (@0)))
+ (negate (convert @0))))
+
(for op (negate abs)
/* Simplify cos(-x) and cos(|x|) -> cos(x). Similarly for cosh. */
(for coss (COS COSH)
new file mode 100644
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-fre1 -fdump-tree-optimized" } */
+/* part of PR tree-optimization/108397 */
+
+long long
+foo (unsigned char o)
+{
+ unsigned long long t1 = -(long long) (o == 0);
+ unsigned long long t2 = -(long long) (t1 != 0);
+ unsigned long long t3 = -(long long) (t1 <= t2);
+ return t3;
+}
+
+/* Should be able to optimize this down to just `return -1;` during fre1. */
+/* { dg-final { scan-tree-dump "return -1;" "fre1" } } */
+/* FRE does not remove all dead statements so a few negate expressions are left behind. */
+/* { dg-final { scan-tree-dump-not " -\[^1\]" "fre1" { xfail *-*-* } } } */
+
+/* { dg-final { scan-tree-dump "return -1;" "optimized" } } */
+/* { dg-final { scan-tree-dump-not " - " "optimized" } } */
new file mode 100644
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-forwprop1 -fdump-tree-optimized" } */
+/* PR tree-optimization/107137 */
+
+unsigned f(_Bool a)
+{
+ int t = a;
+ t = -t;
+ return t;
+}
+
+/* There should be no cast to int at all. */
+/* Forwprop1 does not remove all of the statements. */
+/* { dg-final { scan-tree-dump-not "\\\(int\\\)" "forwprop1" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-not "\\\(int\\\)" "optimized" } } */