summaryrefslogtreecommitdiff
path: root/gcc/toplev.c
diff options
context:
space:
mode:
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>2009-03-30 01:50:44 +0000
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>2009-03-30 01:50:44 +0000
commitc6418a4e44bad350f57aac0ce1d0f6ce6c6a1c9f (patch)
tree07c0a2aef08a00219e11f34b2e1a27c0dd432823 /gcc/toplev.c
parent7666d572f2a547f09f39811c7af07f9532251a02 (diff)
downloadgcc-c6418a4e44bad350f57aac0ce1d0f6ce6c6a1c9f.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@145272 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/toplev.c')
-rw-r--r--gcc/toplev.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 8417cfed6cb..72f3d3087d3 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -281,6 +281,11 @@ enum ira_region flag_ira_region = IRA_REGION_MIXED;
unsigned int flag_ira_verbose = 5;
+/* Set the default for excess precision. */
+
+enum excess_precision flag_excess_precision_cmdline = EXCESS_PRECISION_DEFAULT;
+enum excess_precision flag_excess_precision = EXCESS_PRECISION_DEFAULT;
+
/* Nonzero means change certain warnings into errors.
Usually these are warnings about failure to conform to some standard. */
@@ -2033,11 +2038,51 @@ backend_init (void)
backend_init_target ();
}
+/* Initialize excess precision settings. */
+static void
+init_excess_precision (void)
+{
+ /* Adjust excess precision handling based on the target options. If
+ the front end cannot handle it, flag_excess_precision_cmdline
+ will already have been set accordingly in the post_options
+ hook. */
+ gcc_assert (flag_excess_precision_cmdline != EXCESS_PRECISION_DEFAULT);
+ flag_excess_precision = flag_excess_precision_cmdline;
+ if (flag_unsafe_math_optimizations)
+ flag_excess_precision = EXCESS_PRECISION_FAST;
+ if (flag_excess_precision == EXCESS_PRECISION_STANDARD)
+ {
+ int flt_eval_method = TARGET_FLT_EVAL_METHOD;
+ switch (flt_eval_method)
+ {
+ case -1:
+ case 0:
+ /* Either the target acts unpredictably (-1) or has all the
+ operations required not to have excess precision (0). */
+ flag_excess_precision = EXCESS_PRECISION_FAST;
+ break;
+ case 1:
+ case 2:
+ /* In these cases, predictable excess precision makes
+ sense. */
+ break;
+ default:
+ /* Any other implementation-defined FLT_EVAL_METHOD values
+ require the compiler to handle the associated excess
+ precision rules in excess_precision_type. */
+ gcc_unreachable ();
+ }
+ }
+}
+
/* Initialize things that are both lang-dependent and target-dependent.
This function can be called more than once if target parameters change. */
static void
lang_dependent_init_target (void)
{
+ /* This determines excess precision settings. */
+ init_excess_precision ();
+
/* This creates various _DECL nodes, so needs to be called after the
front end is initialized. It also depends on the HAVE_xxx macros
generated from the target machine description. */