aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorRoger Sayle <roger@nextmovesoftware.com>2021-06-11 17:15:38 +0100
committerRoger Sayle <roger@nextmovesoftware.com>2021-06-11 17:17:58 +0100
commit5b02ed4b87685c0f7c5da9b46cde3ce56fcfd457 (patch)
tree5383dd4f566eb945a79017ed6c292af4f627257c /gcc/fold-const.c
parentb8b80b8aa3d9a7abbcb59b651ea5e84c2ea12d0b (diff)
downloadgcc-5b02ed4b87685c0f7c5da9b46cde3ce56fcfd457.zip
gcc-5b02ed4b87685c0f7c5da9b46cde3ce56fcfd457.tar.gz
gcc-5b02ed4b87685c0f7c5da9b46cde3ce56fcfd457.tar.bz2
[PATCH] PR tree-optimization/96392 Optimize x+0.0 if x is an integer
The patch implements a missed optimization enhancement. Under usual IEEE rules, x+0.0 can't be simplified to x when x might potentially be an IEEE minus zero (-0.0). The current logic in the middle-end checks whether the type of x should honor signed zeros, but with this patch we introduce tree_expr_maybe_real_minus_zero_p that allows us to confirm that the value can't possibly be -0.0, for example, the result of a conversion from an integer type, or the result of fabs (or has a type that doesn't honor signed zero). Whilst modifying match.pd, I also converted some additional folding transformations from "testing the type" to "testing the value". 2020-06-10 Roger Sayle <roger@nextmovesoftware.com> gcc/ChangeLog PR tree-optimization/96392 * fold-const.c (fold_real_zero_addition_p): Take both arguments of the addition or subtraction, not just the zero. Use this other argument in tests for signaling NaNs and signed zeros. (tree_expr_maybe_real_minus_zero_p): New predicate. * fold-const.h (fold_real_zero_addition_p): Update prototype. (tree_expr_maybe_real_minus_zero_p): New function prototype. * match.pd: Update calls to fold_real_zero_addition_p. Replace HONOR_NANS with tree_expr_maybe_nan_p. Replace HONOR_SIGNED_ZEROS with tree_expr_maybe_real_minus_zero_p. Replace HONOR_SNANS with tree_expr_maybe_signaling_nan_p. * tree-ssa-reassoc.c (eliminate_using_constants): Update call to fold_real_zero_addition_p. gcc/testsuite/ChangeLog PR tree-optimization/96392 * gcc.dg/pr96392.c: New test.
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c70
1 files changed, 56 insertions, 14 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 6e5835a..95673d2 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -7127,11 +7127,13 @@ fold_binary_op_with_conditional_arg (location_t loc,
}
-/* Subroutine of fold() that checks for the addition of +/- 0.0.
+/* Subroutine of fold() that checks for the addition of ARG +/- 0.0.
- If !NEGATE, return true if ADDEND is +/-0.0 and, for all X of type
- TYPE, X + ADDEND is the same as X. If NEGATE, return true if X -
- ADDEND is the same as X.
+ If !NEGATE, return true if ZERO_ARG is +/-0.0 and, for all ARG of
+ type TYPE, ARG + ZERO_ARG is the same as ARG. If NEGATE, return true
+ if ARG - ZERO_ARG is the same as X.
+
+ If ARG is NULL, check for any value of type TYPE.
X + 0 and X - 0 both give X when X is NaN, infinite, or nonzero
and finite. The problematic cases are when X is zero, and its mode
@@ -7140,13 +7142,14 @@ fold_binary_op_with_conditional_arg (location_t loc,
modes, X + 0 is not the same as X because -0 + 0 is 0. */
bool
-fold_real_zero_addition_p (const_tree type, const_tree addend, int negate)
+fold_real_zero_addition_p (const_tree type, const_tree arg,
+ const_tree zero_arg, int negate)
{
- if (!real_zerop (addend))
+ if (!real_zerop (zero_arg))
return false;
/* Don't allow the fold with -fsignaling-nans. */
- if (HONOR_SNANS (type))
+ if (arg ? tree_expr_maybe_signaling_nan_p (arg) : HONOR_SNANS (type))
return false;
/* Allow the fold if zeros aren't signed, or their sign isn't important. */
@@ -7158,19 +7161,20 @@ fold_real_zero_addition_p (const_tree type, const_tree addend, int negate)
return false;
/* In a vector or complex, we would need to check the sign of all zeros. */
- if (TREE_CODE (addend) == VECTOR_CST)
- addend = uniform_vector_p (addend);
- if (!addend || TREE_CODE (addend) != REAL_CST)
+ if (TREE_CODE (zero_arg) == VECTOR_CST)
+ zero_arg = uniform_vector_p (zero_arg);
+ if (!zero_arg || TREE_CODE (zero_arg) != REAL_CST)
return false;
/* Treat x + -0 as x - 0 and x - -0 as x + 0. */
- if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (addend)))
+ if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (zero_arg)))
negate = !negate;
/* The mode has signed zeros, and we have to honor their sign.
- In this situation, there is only one case we can return true for.
- X - 0 is the same as X with default rounding. */
- return negate;
+ In this situation, there are only two cases we can return true for.
+ (i) X - 0 is the same as X with default rounding.
+ (ii) X + 0 is X when X can't possibly be -0.0. */
+ return negate || (arg && !tree_expr_maybe_real_minus_zero_p (arg));
}
/* Subroutine of match.pd that optimizes comparisons of a division by
@@ -14375,6 +14379,44 @@ tree_expr_maybe_nan_p (const_tree x)
}
}
+/* Return true if expression X could evaluate to -0.0.
+ This function returns true if uncertain. */
+
+bool
+tree_expr_maybe_real_minus_zero_p (const_tree x)
+{
+ if (!HONOR_SIGNED_ZEROS (x))
+ return false;
+ switch (TREE_CODE (x))
+ {
+ case REAL_CST:
+ return REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (x));
+ case INTEGER_CST:
+ case FLOAT_EXPR:
+ case ABS_EXPR:
+ return false;
+ case NON_LVALUE_EXPR:
+ case SAVE_EXPR:
+ return tree_expr_maybe_real_minus_zero_p (TREE_OPERAND (x, 0));
+ case COND_EXPR:
+ return tree_expr_maybe_real_minus_zero_p (TREE_OPERAND (x, 1))
+ || tree_expr_maybe_real_minus_zero_p (TREE_OPERAND (x, 2));
+ case CALL_EXPR:
+ switch (get_call_combined_fn (x))
+ {
+ CASE_CFN_FABS:
+ return false;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+ /* Ideally !(tree_expr_nonzero_p (X) || tree_expr_nonnegative_p (X))
+ * but currently those predicates require tree and not const_tree. */
+ return true;
+}
+
#define tree_expr_nonnegative_warnv_p(X, Y) \
_Pragma ("GCC error \"Use RECURSE for recursive calls\"") 0