From: Uros Bizjak Date: Thu, 19 Feb 2009 12:44:40 +0000 (+0100) Subject: re PR target/39228 (387 optimised __builtin_isinf() gives incorrect result) X-Git-Tag: releases/gcc-4.3.4~320 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=778492dcab72f6296abf139ae793dd222b476a94;p=thirdparty%2Fgcc.git re PR target/39228 (387 optimised __builtin_isinf() gives incorrect result) PR target/39228 * config/i386/i386.md (isinfxf2): Split from isinf2. (UNSPEC_FXAM_MEM): New unspec. (fxam2_i387_with_temp): New insn and split pattern. (isinf2): Use MODEF mode iterator. Force operand[1] through memory using fxam2_i387_with_temp to remove excess precision. testsuite/ChangeLog: PR target/39228 * gcc.c-torture/execute/pr39228.c: New test. From-SVN: r144295 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 58c89f0248f9..eac440672e9a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2009-02-19 Uros Bizjak + + PR target/39228 + * config/i386/i386.md (isinfxf2): Split from isinf2. + (UNSPEC_FXAM_MEM): New unspec. + (fxam2_i387_with_temp): New insn and split pattern. + (isinf2): Use MODEF mode iterator. Force operand[1] through + memory using fxam2_i387_with_temp to remove excess precision. + 2009-02-17 Uros Bizjak * config/soft-fp/double.h: Update from glibc CVS. diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 2487eb92392b..6e588ebb8694 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -145,6 +145,7 @@ (UNSPEC_FPREM1_U 91) (UNSPEC_C2_FLAG 95) + (UNSPEC_FXAM_MEM 96) ; SSP patterns (UNSPEC_SP_SET 100) @@ -18493,9 +18494,56 @@ (set_attr "unit" "i387") (set_attr "mode" "")]) +(define_insn_and_split "fxam2_i387_with_temp" + [(set (match_operand:HI 0 "register_operand" "") + (unspec:HI + [(match_operand:MODEF 1 "memory_operand" "")] + UNSPEC_FXAM_MEM))] + "TARGET_USE_FANCY_MATH_387 + && !(reload_completed || reload_in_progress)" + "#" + "&& 1" + [(set (match_dup 2)(match_dup 1)) + (set (match_dup 0) + (unspec:HI [(match_dup 2)] UNSPEC_FXAM))] +{ + operands[2] = gen_reg_rtx (mode); + + MEM_VOLATILE_P (operands[1]) = 1; +} + [(set_attr "type" "multi") + (set_attr "unit" "i387") + (set_attr "mode" "")]) + +(define_expand "isinfxf2" + [(use (match_operand:SI 0 "register_operand" "")) + (use (match_operand:XF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && TARGET_C99_FUNCTIONS" +{ + rtx mask = GEN_INT (0x45); + rtx val = GEN_INT (0x05); + + rtx cond; + + rtx scratch = gen_reg_rtx (HImode); + rtx res = gen_reg_rtx (QImode); + + emit_insn (gen_fxamxf2_i387 (scratch, operands[1])); + + emit_insn (gen_andqi_ext_0 (scratch, scratch, mask)); + emit_insn (gen_cmpqi_ext_3 (scratch, val)); + cond = gen_rtx_fmt_ee (EQ, QImode, + gen_rtx_REG (CCmode, FLAGS_REG), + const0_rtx); + emit_insn (gen_rtx_SET (VOIDmode, res, cond)); + emit_insn (gen_zero_extendqisi2 (operands[0], res)); + DONE; +}) + (define_expand "isinf2" [(use (match_operand:SI 0 "register_operand" "")) - (use (match_operand:X87MODEF 1 "register_operand" ""))] + (use (match_operand:MODEF 1 "nonimmediate_operand" ""))] "TARGET_USE_FANCY_MATH_387 && TARGET_C99_FUNCTIONS && !(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)" @@ -18508,7 +18556,18 @@ rtx scratch = gen_reg_rtx (HImode); rtx res = gen_reg_rtx (QImode); - emit_insn (gen_fxam2_i387 (scratch, operands[1])); + /* Remove excess precision by forcing value through memory. */ + if (memory_operand (operands[1], VOIDmode)) + emit_insn (gen_fxam2_i387_with_temp (scratch, operands[1])); + else + { + int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL; + rtx temp = assign_386_stack_local (mode, slot); + + emit_move_insn (temp, operands[1]); + emit_insn (gen_fxam2_i387_with_temp (scratch, temp)); + } + emit_insn (gen_andqi_ext_0 (scratch, scratch, mask)); emit_insn (gen_cmpqi_ext_3 (scratch, val)); cond = gen_rtx_fmt_ee (EQ, QImode, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2a9ceeba4605..9d0809dd2a19 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-02-19 Uros Bizjak + + PR target/39228 + * gcc.c-torture/execute/pr39228.c: New test. + 2009-02-19 Paul Thomas PR fortran/38852 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr39228.c b/gcc/testsuite/gcc.c-torture/execute/pr39228.c new file mode 100644 index 000000000000..06d8efd1a5bb --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr39228.c @@ -0,0 +1,36 @@ +extern void abort (void); + +static int __attribute__((always_inline)) testf (float b) +{ + float c = 1.01f * b; + + return __builtin_isinff (c); +} + +static int __attribute__((always_inline)) test (double b) +{ + double c = 1.01 * b; + + return __builtin_isinf (c); +} + +static int __attribute__((always_inline)) testl (long double b) +{ + long double c = 1.01L * b; + + return __builtin_isinfl (c); +} + +int main() +{ + if (testf (__FLT_MAX__) < 1) + abort (); + + if (test (__DBL_MAX__) < 1) + abort (); + + if (testl (__LDBL_MAX__) < 1) + abort (); + + return 0; +}