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/config | |
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/config')
-rw-r--r-- | gcc/config/i386/i386.h | 14 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 89 |
2 files changed, 78 insertions, 25 deletions
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index e4d4463..89e26f6 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -611,6 +611,20 @@ enum target_cpu_default #define TARGET_FLT_EVAL_METHOD \ (TARGET_MIX_SSE_I387 ? -1 : TARGET_SSE_MATH ? 0 : 2) +/* Whether to allow x87 floating-point arithmetic on MODE (one of + SFmode, DFmode and XFmode) in the current excess precision + configuration. */ +#define X87_ENABLE_ARITH(MODE) \ + (flag_excess_precision == EXCESS_PRECISION_FAST || (MODE) == XFmode) + +/* Likewise, whether to allow direct conversions from integer mode + IMODE (HImode, SImode or DImode) to MODE. */ +#define X87_ENABLE_FLOAT(MODE, IMODE) \ + (flag_excess_precision == EXCESS_PRECISION_FAST \ + || (MODE) == XFmode \ + || ((MODE) == DFmode && (IMODE) == SImode) \ + || (IMODE) == HImode) + /* target machine storage layout */ #define SHORT_TYPE_SIZE 16 diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index a112198..9592f91 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -5137,13 +5137,28 @@ "TARGET_80387 || ((<SSEMODEI24:MODE>mode != DImode || TARGET_64BIT) && SSE_FLOAT_MODE_P (<X87MODEF:MODE>mode) && TARGET_SSE_MATH)" - "") + " +{ + if (!((<SSEMODEI24:MODE>mode != DImode || TARGET_64BIT) + && SSE_FLOAT_MODE_P (<X87MODEF:MODE>mode) && TARGET_SSE_MATH) + && !X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, <SSEMODEI24:MODE>mode)) + { + rtx reg = gen_reg_rtx (XFmode); + emit_insn (gen_float<SSEMODEI24:mode>xf2 (reg, operands[1])); +/* Avoid references to nonexistent function in dead code in XFmode case. */ +#define gen_truncxfxf2 gen_truncxfdf2 + emit_insn (gen_truncxf<X87MODEF:mode>2 (operands[0], reg)); +#undef gen_truncxfxf2 + DONE; + } +}") ;; Pre-reload splitter to add memory clobber to the pattern. (define_insn_and_split "*float<SSEMODEI24:mode><X87MODEF:mode>2_1" [(set (match_operand:X87MODEF 0 "register_operand" "") (float:X87MODEF (match_operand:SSEMODEI24 1 "register_operand" "")))] "((TARGET_80387 + && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, <SSEMODEI24:MODE>mode) && (!((<SSEMODEI24:MODE>mode != DImode || TARGET_64BIT) && SSE_FLOAT_MODE_P (<X87MODEF:MODE>mode) && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)) @@ -5524,7 +5539,8 @@ (float:X87MODEF (match_operand:SSEMODEI24 1 "nonimmediate_operand" "m,?r"))) (clobber (match_operand:SSEMODEI24 2 "memory_operand" "=X,m"))] - "TARGET_80387" + "TARGET_80387 + && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, <SSEMODEI24:MODE>mode)" "@ fild%z1\t%1 #" @@ -5537,7 +5553,8 @@ [(set (match_operand:X87MODEF 0 "register_operand" "=f") (float:X87MODEF (match_operand:SSEMODEI24 1 "memory_operand" "m")))] - "TARGET_80387" + "TARGET_80387 + && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, <SSEMODEI24:MODE>mode)" "fild%z1\t%1" [(set_attr "type" "fmov") (set_attr "mode" "<X87MODEF:MODE>") @@ -5548,6 +5565,7 @@ (float:X87MODEF (match_operand:SSEMODEI24 1 "register_operand" ""))) (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))] "TARGET_80387 + && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, <SSEMODEI24:MODE>mode) && reload_completed && FP_REG_P (operands[0])" [(set (match_dup 2) (match_dup 1)) @@ -5559,6 +5577,7 @@ (float:X87MODEF (match_operand:SSEMODEI24 1 "memory_operand" ""))) (clobber (match_operand:SSEMODEI24 2 "memory_operand" ""))] "TARGET_80387 + && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, <SSEMODEI24:MODE>mode) && reload_completed && FP_REG_P (operands[0])" [(set (match_dup 0) (float:X87MODEF (match_dup 1)))] @@ -5574,7 +5593,8 @@ (clobber (match_scratch:V4SI 3 "=X,x")) (clobber (match_scratch:V4SI 4 "=X,x")) (clobber (match_operand:DI 2 "memory_operand" "=X,m"))] - "TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES + "TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode) + && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES && !TARGET_64BIT && optimize_function_for_speed_p (cfun)" "#" [(set_attr "type" "multi") @@ -5588,7 +5608,8 @@ (clobber (match_scratch:V4SI 3 "")) (clobber (match_scratch:V4SI 4 "")) (clobber (match_operand:DI 2 "memory_operand" ""))] - "TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES + "TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode) + && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES && !TARGET_64BIT && optimize_function_for_speed_p (cfun) && reload_completed && FP_REG_P (operands[0])" @@ -5612,7 +5633,8 @@ (clobber (match_scratch:V4SI 3 "")) (clobber (match_scratch:V4SI 4 "")) (clobber (match_operand:DI 2 "memory_operand" ""))] - "TARGET_80387 && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES + "TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode) + && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES && !TARGET_64BIT && optimize_function_for_speed_p (cfun) && reload_completed && FP_REG_P (operands[0])" @@ -5632,7 +5654,8 @@ (clobber (match_operand:DI 2 "memory_operand" "=m,m")) (clobber (match_scratch:SI 3 "=X,x"))] "!TARGET_64BIT - && TARGET_80387 && TARGET_SSE" + && TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, SImode) + && TARGET_SSE" "#" [(set_attr "type" "multi") (set_attr "mode" "<MODE>")]) @@ -5644,7 +5667,8 @@ (clobber (match_operand:DI 2 "memory_operand" "")) (clobber (match_scratch:SI 3 ""))] "!TARGET_64BIT - && TARGET_80387 && TARGET_SSE + && TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, SImode) + && TARGET_SSE && reload_completed" [(set (match_dup 2) (match_dup 1)) (set (match_dup 0) @@ -5658,7 +5682,8 @@ (clobber (match_operand:DI 2 "memory_operand" "")) (clobber (match_scratch:SI 3 ""))] "!TARGET_64BIT - && TARGET_80387 && TARGET_SSE + && TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, SImode) + && TARGET_SSE && reload_completed" [(set (match_dup 2) (match_dup 3)) (set (match_dup 0) @@ -5676,7 +5701,8 @@ (clobber (match_dup 2)) (clobber (match_scratch:SI 3 ""))])] "!TARGET_64BIT - && ((TARGET_80387 && TARGET_SSE) + && ((TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, SImode) + && TARGET_SSE) || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))" { if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH) @@ -7475,7 +7501,8 @@ [(set (match_operand:MODEF 0 "register_operand" "") (plus:MODEF (match_operand:MODEF 1 "register_operand" "") (match_operand:MODEF 2 "nonimmediate_operand" "")))] - "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" + "(TARGET_80387 && X87_ENABLE_ARITH (<MODE>mode)) + || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" "") ;; Subtract instructions @@ -7835,7 +7862,8 @@ [(set (match_operand:MODEF 0 "register_operand" "") (minus:MODEF (match_operand:MODEF 1 "register_operand" "") (match_operand:MODEF 2 "nonimmediate_operand" "")))] - "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" + "(TARGET_80387 && X87_ENABLE_ARITH (<MODE>mode)) + || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" "") ;; Multiply instructions @@ -8390,7 +8418,8 @@ [(set (match_operand:MODEF 0 "register_operand" "") (mult:MODEF (match_operand:MODEF 1 "register_operand" "") (match_operand:MODEF 2 "nonimmediate_operand" "")))] - "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" + "(TARGET_80387 && X87_ENABLE_ARITH (<MODE>mode)) + || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" "") ;; SSE5 scalar multiply/add instructions are defined in sse.md. @@ -8431,14 +8460,16 @@ [(set (match_operand:DF 0 "register_operand" "") (div:DF (match_operand:DF 1 "register_operand" "") (match_operand:DF 2 "nonimmediate_operand" "")))] - "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)" + "(TARGET_80387 && X87_ENABLE_ARITH (DFmode)) + || (TARGET_SSE2 && TARGET_SSE_MATH)" "") (define_expand "divsf3" [(set (match_operand:SF 0 "register_operand" "") (div:SF (match_operand:SF 1 "register_operand" "") (match_operand:SF 2 "nonimmediate_operand" "")))] - "TARGET_80387 || TARGET_SSE_MATH" + "(TARGET_80387 && X87_ENABLE_ARITH (SFmode)) + || TARGET_SSE_MATH" { if (TARGET_SSE_MATH && TARGET_RECIP && optimize_insn_for_speed_p () && flag_finite_math_only && !flag_trapping_math @@ -16317,7 +16348,7 @@ (match_operator:MODEF 3 "binary_fp_operator" [(match_operand:MODEF 1 "nonimmediate_operand" "%0") (match_operand:MODEF 2 "nonimmediate_operand" "fm")]))] - "TARGET_80387 + "TARGET_80387 && X87_ENABLE_ARITH (<MODE>mode) && COMMUTATIVE_ARITH_P (operands[3]) && !(MEM_P (operands[1]) && MEM_P (operands[2]))" "* return output_387_binary_op (insn, operands);" @@ -16431,7 +16462,8 @@ (match_operator:MODEF 3 "binary_fp_operator" [(match_operand:MODEF 1 "nonimmediate_operand" "0,fm") (match_operand:MODEF 2 "nonimmediate_operand" "fm,0")]))] - "TARGET_80387 && !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH) + "TARGET_80387 && X87_ENABLE_ARITH (<MODE>mode) + && !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH) && !COMMUTATIVE_ARITH_P (operands[3]) && !(MEM_P (operands[1]) && MEM_P (operands[2]))" "* return output_387_binary_op (insn, operands);" @@ -16451,7 +16483,8 @@ [(float:MODEF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r")) (match_operand:MODEF 2 "register_operand" "0,0")]))] - "TARGET_80387 && !(SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH) + "TARGET_80387 && X87_ENABLE_FLOAT (<MODEF:MODE>mode, <X87MODEI12:MODE>mode) + && !(SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH) && (TARGET_USE_<X87MODEI12:MODE>MODE_FIOP || optimize_function_for_size_p (cfun))" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") @@ -16470,7 +16503,8 @@ [(match_operand:MODEF 1 "register_operand" "0,0") (float:MODEF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))] - "TARGET_80387 && !(SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH) + "TARGET_80387 && X87_ENABLE_FLOAT (<MODEF:MODE>mode, <X87MODEI12:MODE>mode) + && !(SSE_FLOAT_MODE_P (<MODEF:MODE>mode) && TARGET_SSE_MATH) && (TARGET_USE_<X87MODEI12:MODE>MODE_FIOP || optimize_function_for_size_p (cfun))" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") @@ -16489,7 +16523,8 @@ [(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,0")) (match_operand:DF 2 "register_operand" "0,f")]))] - "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH) + "TARGET_80387 && X87_ENABLE_ARITH (DFmode) + && !(TARGET_SSE2 && TARGET_SSE_MATH) && !(MEM_P (operands[1]) && MEM_P (operands[2]))" "* return output_387_binary_op (insn, operands);" [(set (attr "type") @@ -16507,7 +16542,8 @@ [(match_operand:DF 1 "register_operand" "0,f") (float_extend:DF (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))] - "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)" + "TARGET_80387 && X87_ENABLE_ARITH (DFmode) + && !(TARGET_SSE2 && TARGET_SSE_MATH)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:DF 3 "mult_operator" "") @@ -16525,7 +16561,8 @@ (match_operand:SF 1 "register_operand" "0,f")) (float_extend:DF (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))] - "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)" + "TARGET_80387 && X87_ENABLE_ARITH (DFmode) + && !(TARGET_SSE2 && TARGET_SSE_MATH)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:DF 3 "mult_operator" "") @@ -16661,7 +16698,8 @@ [(float (match_operand:X87MODEI12 1 "register_operand" "")) (match_operand 2 "register_operand" "")]))] "reload_completed - && X87_FLOAT_MODE_P (GET_MODE (operands[0]))" + && X87_FLOAT_MODE_P (GET_MODE (operands[0])) + && X87_ENABLE_FLOAT (GET_MODE (operands[0]), GET_MODE (operands[1]))" [(const_int 0)] { operands[4] = ix86_force_to_memory (GET_MODE (operands[1]), operands[1]); @@ -16681,7 +16719,8 @@ [(match_operand 1 "register_operand" "") (float (match_operand:X87MODEI12 2 "register_operand" ""))]))] "reload_completed - && X87_FLOAT_MODE_P (GET_MODE (operands[0]))" + && X87_FLOAT_MODE_P (GET_MODE (operands[0])) + && X87_ENABLE_FLOAT (GET_MODE (operands[0]), GET_MODE (operands[2]))" [(const_int 0)] { operands[4] = ix86_force_to_memory (GET_MODE (operands[2]), operands[2]); @@ -16767,7 +16806,7 @@ [(set (match_operand:MODEF 0 "register_operand" "") (sqrt:MODEF (match_operand:MODEF 1 "nonimmediate_operand" "")))] - "TARGET_USE_FANCY_MATH_387 + "(TARGET_USE_FANCY_MATH_387 && X87_ENABLE_ARITH (<MODE>mode)) || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" { if (<MODE>mode == SFmode |