diff options
author | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-03-07 11:37:16 +0000 |
---|---|---|
committer | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-03-07 11:37:16 +0000 |
commit | 920d0fb5731b8a6a4888e16cbf5ecc792c0ae262 (patch) | |
tree | 74f74ccd7ea753279bc20a10577c6a90a6a4ba38 /gcc/c-common.c | |
parent | b77df3304ca427a035a4a8bf14f231f1dfd170a0 (diff) | |
download | gcc-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.c | 152 |
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; |