summaryrefslogtreecommitdiff
path: root/gcc/c-common.c
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2002-03-07 11:37:16 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2002-03-07 11:37:16 +0000
commit920d0fb5731b8a6a4888e16cbf5ecc792c0ae262 (patch)
tree74f74ccd7ea753279bc20a10577c6a90a6a4ba38 /gcc/c-common.c
parentb77df3304ca427a035a4a8bf14f231f1dfd170a0 (diff)
downloadgcc-920d0fb5731b8a6a4888e16cbf5ecc792c0ae262.tar.gz
* defaults.h (MODE_HAS_NANS, MODE_HAS_INFINITIES): New.
(MODE_HAS_SIGNED_ZEROS, MODE_HAS_SIGN_DEPENDENT_ROUNDING): New. * flags.h (HONOR_NANS, HONOR_INFINITIES, HONOR_SIGNED_ZEROS): New. (HONOR_SIGN_DEPENDENT_ROUNDING): New. * builtins.c (expand_builtin_mathfn): Use HONOR_NANS. * c-common.c (truthvalue_conversion): Reduce x - y != 0 to x != y unless x and y could be infinite. (expand_unordered_cmp): New, mostly split from expand_tree_builtin. Check that the common type of both arguments is a real, even for targets without unordered comparisons. Allow an integer argument to be compared against a real. (expand_tree_builtin): Use expand_unordered_cmp. * combine.c (combine_simplify_rtx): Use the new HONOR_... macros. * cse.c (fold_rtx): Likewise. Fix indentation. * fold-const.c (fold_real_zero_addition_p): New. (fold): Use it, and the new HONOR_... macros. * ifcvt.c (noce_try_minmax): Use the new HONOR_... macros. * jump.c (reversed_comparison_code_parts): After searching for the true comparison mode, use HONOR_NANS to decide whether it can be safely reversed. (reverse_condition_maybe_unordered): Remove IEEE check. * simplify-rtx.c (simplify_binary_operation): Use the new macros to decide which simplifications are valid. Allow the following simplifications for IEEE: (-a + b) to (b - a), (a + -b) to (a - b), and (a - -b) to (a + b). (simplify_relational_operation): Use HONOR_NANS. * doc/tm.texi: Document the MODE_HAS_... macros. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@50401 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-common.c')
-rw-r--r--gcc/c-common.c152
1 files changed, 90 insertions, 62 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c
index ed67bb05b91..7fad4b304f2 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -2202,10 +2202,15 @@ truthvalue_conversion (expr)
break;
case MINUS_EXPR:
- /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
- this case. */
- if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
- && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
+ /* Perhaps reduce (x - y) != 0 to (x != y). The expressions
+ aren't guaranteed to the be same for modes that can represent
+ infinity, since if x and y are both +infinity, or both
+ -infinity, then x - y is not a number.
+
+ Note that this transformation is safe when x or y is NaN.
+ (x - y) is then NaN, and both (x - y) != 0 and x != y will
+ be false. */
+ if (HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (TREE_OPERAND (expr, 0)))))
break;
/* fall through... */
case BIT_XOR_EXPR:
@@ -3051,6 +3056,81 @@ strip_array_types (type)
return type;
}
+static tree expand_unordered_cmp PARAMS ((tree, tree, enum tree_code,
+ enum tree_code));
+
+/* Expand a call to an unordered comparison function such as
+ __builtin_isgreater(). FUNCTION is the function's declaration and
+ PARAMS a list of the values passed. For __builtin_isunordered(),
+ UNORDERED_CODE is UNORDERED_EXPR and ORDERED_CODE is NOP_EXPR. In
+ other cases, UNORDERED_CODE and ORDERED_CODE are comparison codes
+ that give the opposite of the desired result. UNORDERED_CODE is
+ used for modes that can hold NaNs and ORDERED_CODE is used for the
+ rest. */
+
+static tree
+expand_unordered_cmp (function, params, unordered_code, ordered_code)
+ tree function, params;
+ enum tree_code unordered_code, ordered_code;
+{
+ tree arg0, arg1, type;
+ enum tree_code code0, code1;
+
+ /* Check that we have exactly two arguments. */
+ if (params == 0 || TREE_CHAIN (params) == 0)
+ {
+ error ("too few arguments to function `%s'",
+ IDENTIFIER_POINTER (DECL_NAME (function)));
+ return error_mark_node;
+ }
+ else if (TREE_CHAIN (TREE_CHAIN (params)) != 0)
+ {
+ error ("too many arguments to function `%s'",
+ IDENTIFIER_POINTER (DECL_NAME (function)));
+ return error_mark_node;
+ }
+
+ arg0 = TREE_VALUE (params);
+ arg1 = TREE_VALUE (TREE_CHAIN (params));
+
+ code0 = TREE_CODE (TREE_TYPE (arg0));
+ code1 = TREE_CODE (TREE_TYPE (arg1));
+
+ /* Make sure that the arguments have a common type of REAL. */
+ type = 0;
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+ type = common_type (TREE_TYPE (arg0), TREE_TYPE (arg1));
+
+ if (type == 0 || TREE_CODE (type) != REAL_TYPE)
+ {
+ error ("non-floating-point argument to function `%s'",
+ IDENTIFIER_POINTER (DECL_NAME (function)));
+ return error_mark_node;
+ }
+
+ if (unordered_code == UNORDERED_EXPR)
+ {
+ if (MODE_HAS_NANS (TYPE_MODE (type)))
+ return build_binary_op (unordered_code,
+ convert (type, arg0),
+ convert (type, arg1),
+ 0);
+ else
+ return integer_zero_node;
+ }
+
+ return build_unary_op (TRUTH_NOT_EXPR,
+ build_binary_op (MODE_HAS_NANS (TYPE_MODE (type))
+ ? unordered_code
+ : ordered_code,
+ convert (type, arg0),
+ convert (type, arg1),
+ 0),
+ 0);
+}
+
+
/* Recognize certain built-in functions so we can make tree-codes
other than CALL_EXPR. We do this when it enables fold-const.c
to do something useful. */
@@ -3063,8 +3143,6 @@ tree
expand_tree_builtin (function, params, coerced_params)
tree function, params, coerced_params;
{
- enum tree_code code;
-
if (DECL_BUILT_IN_CLASS (function) != BUILT_IN_NORMAL)
return NULL_TREE;
@@ -3103,72 +3181,22 @@ expand_tree_builtin (function, params, coerced_params)
return build_unary_op (IMAGPART_EXPR, TREE_VALUE (coerced_params), 0);
case BUILT_IN_ISGREATER:
- if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
- code = UNLE_EXPR;
- else
- code = LE_EXPR;
- goto unordered_cmp;
+ return expand_unordered_cmp (function, params, UNLE_EXPR, LE_EXPR);
case BUILT_IN_ISGREATEREQUAL:
- if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
- code = UNLT_EXPR;
- else
- code = LT_EXPR;
- goto unordered_cmp;
+ return expand_unordered_cmp (function, params, UNLT_EXPR, LT_EXPR);
case BUILT_IN_ISLESS:
- if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
- code = UNGE_EXPR;
- else
- code = GE_EXPR;
- goto unordered_cmp;
+ return expand_unordered_cmp (function, params, UNGE_EXPR, GE_EXPR);
case BUILT_IN_ISLESSEQUAL:
- if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
- code = UNGT_EXPR;
- else
- code = GT_EXPR;
- goto unordered_cmp;
+ return expand_unordered_cmp (function, params, UNGT_EXPR, GT_EXPR);
case BUILT_IN_ISLESSGREATER:
- if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
- code = UNEQ_EXPR;
- else
- code = EQ_EXPR;
- goto unordered_cmp;
+ return expand_unordered_cmp (function, params, UNEQ_EXPR, EQ_EXPR);
case BUILT_IN_ISUNORDERED:
- if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
- return integer_zero_node;
- code = UNORDERED_EXPR;
- goto unordered_cmp;
-
- unordered_cmp:
- {
- tree arg0, arg1;
-
- if (params == 0
- || TREE_CHAIN (params) == 0)
- {
- error ("too few arguments to function `%s'",
- IDENTIFIER_POINTER (DECL_NAME (function)));
- return error_mark_node;
- }
- else if (TREE_CHAIN (TREE_CHAIN (params)) != 0)
- {
- error ("too many arguments to function `%s'",
- IDENTIFIER_POINTER (DECL_NAME (function)));
- return error_mark_node;
- }
-
- arg0 = TREE_VALUE (params);
- arg1 = TREE_VALUE (TREE_CHAIN (params));
- arg0 = build_binary_op (code, arg0, arg1, 0);
- if (code != UNORDERED_EXPR)
- arg0 = build_unary_op (TRUTH_NOT_EXPR, arg0, 0);
- return arg0;
- }
- break;
+ return expand_unordered_cmp (function, params, UNORDERED_EXPR, NOP_EXPR);
default:
break;