[PATCH, i386]: Fix PR target/39228, 387 optimised __builtin_isinf() gives incorrect result
Uros Bizjak
ubizjak@gmail.com
Wed Feb 18 13:48:00 GMT 2009
Hello!
Attached patch fixes PR target/39228 by forcing operands[1] through
volatile memory. This will strip excess precision from input operand.
Patch was bootstrapped on i686-pc-linux-gnu. Patch also includes
generic testcase that will check for possible problems with isinf()
functions.
2009-02-18 Uros Bizjak <ubizjak@gmail.com>
PR target/39228
* config/i386/i386.md (isinfxf2): Split from isinf<mode>2.
(isinf<mode>2): Use MODEF mode iterator. Force operand[1]
through volatile memory to remove excess precision.
testsuite/ChangeLog:
2009-02-18 Uros Bizjak <ubizjak@gmail.com>
PR target/39228
* gcc.c-torture/execute/pr39228.c: New test.
I will wait for possible comments for a day or two before comitting
this patch to 4.4 mainline and 4.3 branch.
Uros.
-------------- next part --------------
Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md (revision 144259)
+++ config/i386/i386.md (working copy)
@@ -18811,9 +18811,35 @@
(set_attr "unit" "i387")
(set_attr "mode" "<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 "isinf<mode>2"
[(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>mode) && TARGET_SSE_MATH)"
@@ -18826,7 +18852,22 @@
rtx scratch = gen_reg_rtx (HImode);
rtx res = gen_reg_rtx (QImode);
+ /* Remove excess precision by forcing value through memory. */
+ if (REG_P (operands[1]))
+ {
+ int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL;
+ rtx temp = assign_386_stack_local (<MODE>mode, slot);
+
+ MEM_VOLATILE_P (temp) = 1;
+
+ emit_move_insn (temp, operands[1]);
+ emit_move_insn (operands[1], temp);
+ }
+ else
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+
emit_insn (gen_fxam<mode>2_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,
Index: testsuite/gcc.c-torture/execute/pr39228.c
===================================================================
--- testsuite/gcc.c-torture/execute/pr39228.c (revision 0)
+++ testsuite/gcc.c-torture/execute/pr39228.c (revision 0)
@@ -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()
+{
+ int x;
+
+ x = testf (__FLT_MAX__);
+ x &= test (__DBL_MAX__);
+ x &= testl (__LDBL_MAX__);
+
+ if (x == 0)
+ abort ();
+
+ return 0;
+}
More information about the Gcc-patches
mailing list