diff options
author | Joseph Myers <joseph@codesourcery.com> | 2009-03-30 02:50:44 +0100 |
---|---|---|
committer | Joseph Myers <jsm28@gcc.gnu.org> | 2009-03-30 02:50:44 +0100 |
commit | 8ce94e44465bcc958dc11270d9dee1775c7a4f43 (patch) | |
tree | 07c0a2aef08a00219e11f34b2e1a27c0dd432823 /gcc/c-common.c | |
parent | 1e57bf475bf7651b30a5a3199bc669617c5004a6 (diff) | |
download | gcc-8ce94e44465bcc958dc11270d9dee1775c7a4f43.zip gcc-8ce94e44465bcc958dc11270d9dee1775c7a4f43.tar.gz gcc-8ce94e44465bcc958dc11270d9dee1775c7a4f43.tar.bz2 |
re PR middle-end/323 (optimized code gives strange floating point results)
PR rtl-optimization/323
* c-common.c (c_fully_fold, convert_and_check,
c_common_truthvalue_conversion): Handle EXCESS_PRECISION_EXPR.
(c_fully_fold_internal): Disallow EXCESS_PRECISION_EXPR.
* c-common.def (EXCESS_PRECISION_EXPR): New.
* c-cppbuiltin.c (builtin_define_float_constants): Define
constants with enough digits for long double.
* c-lex.c (interpret_float): Interpret constant with excess
precision where appropriate.
* c-opts.c (c_common_post_options): Set
flag_excess_precision_cmdline. Give an error for
-fexcess-precision=standard for C++ for processors where the
option is significant.
* c-parser.c (c_parser_conditional_expression): Handle excess
precision in condition.
* c-typeck.c (convert_arguments): Handle arguments with excess
precision.
(build_unary_op): Move excess precision outside operation.
(build_conditional_expr): Likewise.
(build_compound_expr): Likewise.
(build_c_cast): Do cast on operand of EXCESS_PRECISION_EXPR.
(build_modify_expr): Handle excess precision in RHS.
(convert_for_assignment): Handle excess precision in converted
value.
(digest_init, output_init_element, process_init_element): Handle
excess precision in initializer.
(c_finish_return): Handle excess precision in return value.
(build_binary_op): Handle excess precision in operands and add
excess precision as needed for operation.
* common.opt (-fexcess-precision=): New option.
* config/i386/i386.h (X87_ENABLE_ARITH, X87_ENABLE_FLOAT): New.
* config/i386/i386.md (float<SSEMODEI24:mode><X87MODEF:mode>2):
For standard excess precision, output explicit conversion to and
truncation from XFmode.
(*float<SSEMODEI24:mode><X87MODEF:mode>2_1,
*float<SSEMODEI24:mode><X87MODEF:mode>2_i387_with_temp,
*float<SSEMODEI24:mode><X87MODEF:mode>2_i387, two unnamed
define_splits, floatdi<X87MODEF:mode>2_i387_with_xmm, two unnamed
define_splits, *floatunssi<mode>2_1, two unnamed define_splits,
floatunssi<mode>2, add<mode>3, sub<mode>3, mul<mode>3, divdf3,
divsf3, *fop_<mode>_comm_i387, *fop_<mode>_1_i387,
*fop_<MODEF:mode>_2_i387, *fop_<MODEF:mode>_3_i387,
*fop_df_4_i387, *fop_df_5_i387, *fop_df_6_i387, two unnamed
define_splits, sqrt<mode>2): Disable where appropriate for
standard excess precision.
* convert.c (convert_to_real): Do not shorten arithmetic to type
for which excess precision would be used.
* defaults.h (TARGET_FLT_EVAL_METHOD_NON_DEFAULT): Define.
* doc/invoke.texi (-fexcess-precision=): Document option.
(-mfpmath=): Correct index entry.
* flags.h (enum excess_precision, flag_excess_precision_cmdline,
flag_excess_precision): New.
* langhooks.c (lhd_post_options): Set
flag_excess_precision_cmdline.
* opts.c (common_handle_option): Handle -fexcess-precision=.
* toplev.c (flag_excess_precision_cmdline, flag_excess_precision,
init_excess_precision): New.
(lang_dependent_init_target): Call init_excess_precision.
* tree.c (excess_precision_type): New.
* tree.h (excess_precision_type): Declare.
ada:
* gcc-interface/misc.c (gnat_post_options): Set
flag_excess_precision_cmdline. Give an error for
-fexcess-precision=standard for processors where the option is
significant.
fortran:
* options.c (gfc_post_options): Set
flag_excess_precision_cmdline. Give an error for
-fexcess-precision=standard for processors where the option is
significant.
java:
* lang.c (java_post_options): Set flag_excess_precision_cmdline.
Give an error for -fexcess-precision=standard for processors where
the option is significant.
testsuite:
* gcc.target/i386/excess-precision-1.c,
gcc.target/i386/excess-precision-2.c,
gcc.target/i386/excess-precision-3.c,
gcc.target/i386/excess-precision-4.c,
gcc.target/i386/excess-precision-5.c,
gcc.target/i386/excess-precision-6.c: New tests.
From-SVN: r145272
Diffstat (limited to 'gcc/c-common.c')
-rw-r--r-- | gcc/c-common.c | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c index 9abd006..b1ac9bc 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -1131,6 +1131,7 @@ tree c_fully_fold (tree expr, bool in_init, bool *maybe_const) { tree ret; + tree eptype = NULL_TREE; bool dummy = true; bool maybe_const_itself = true; @@ -1142,8 +1143,15 @@ c_fully_fold (tree expr, bool in_init, bool *maybe_const) if (!maybe_const) maybe_const = &dummy; + if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR) + { + eptype = TREE_TYPE (expr); + expr = TREE_OPERAND (expr, 0); + } ret = c_fully_fold_internal (expr, in_init, maybe_const, &maybe_const_itself); + if (eptype) + ret = fold_convert (eptype, ret); *maybe_const &= maybe_const_itself; return ret; } @@ -1444,6 +1452,15 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, *maybe_const_itself &= op2_const_self; goto out; + case EXCESS_PRECISION_EXPR: + /* Each case where an operand with excess precision may be + encountered must remove the EXCESS_PRECISION_EXPR around + inner operands and possibly put one around the whole + expression or possibly convert to the semantic type (which + c_fully_fold does); we cannot tell at this stage which is + appropriate in any particular case. */ + gcc_unreachable (); + default: /* Various codes may appear through folding built-in functions and their arguments. */ @@ -2174,6 +2191,21 @@ tree convert_and_check (tree type, tree expr) { tree result; + tree expr_for_warning; + + /* Convert from a value with possible excess precision rather than + via the semantic type, but do not warn about values not fitting + exactly in the semantic type. */ + if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR) + { + tree orig_type = TREE_TYPE (expr); + expr = TREE_OPERAND (expr, 0); + expr_for_warning = convert (orig_type, expr); + if (orig_type == type) + return expr_for_warning; + } + else + expr_for_warning = expr; if (TREE_TYPE (expr) == type) return expr; @@ -2181,7 +2213,7 @@ convert_and_check (tree type, tree expr) result = convert (type, expr); if (!skip_evaluation && !TREE_OVERFLOW_P (expr) && result != error_mark_node) - warnings_for_convert_and_check (type, expr, result); + warnings_for_convert_and_check (type, expr_for_warning, result); return result; } @@ -3862,6 +3894,7 @@ c_common_truthvalue_conversion (location_t location, tree expr) case NEGATE_EXPR: case ABS_EXPR: case FLOAT_EXPR: + case EXCESS_PRECISION_EXPR: /* These don't change whether an object is nonzero or zero. */ return c_common_truthvalue_conversion (location, TREE_OPERAND (expr, 0)); |